import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { createAdminClient } from '@/lib/supabase/admin'
import { publicOrigin, SUPPORT_EMAIL } from '@/lib/app-url'
import { requireParticipant } from '@/lib/api-guard'
import { logTripEvent } from '@/lib/audit'
import { sendPlatformEmail } from '@/lib/email/send'
import { DEFAULT_TEMPLATES, renderTemplate, DASHBOARD_LINKS } from '@/lib/email-templates'
import { pilotPaperworkAccess } from '@/lib/domain/invoicing'
import { canManagePilotAccess, documentSlotsFor, PAPERWORK_REQUESTED_ACTION } from '@/lib/domain/pilot'
import { localToday } from '@/lib/format'
import type { Profile, Trip, TripParticipant } from '@/types/db'

/**
 * Request a pilot's paperwork from the My Pilot tab (Nash, 2026-09-17).
 *
 * "If the pilot doesn't have any paperwork, we should have a button to
 * request paperwork… this is a feature for the Starter package… The request
 * of paperwork can be done only by the person that invited the pilot."
 *
 * Who: the person who invited THAT pilot, or an admin (`canManagePilotAccess`
 * — the same relation that governs sharing permits).
 *
 * Plan gate: Starter or higher, or inside the 90-day window that every
 * account gets (`pilotPaperworkAccess`). There is no paid plan on the server
 * yet — plans are a design preview in the browser — so today the real gate
 * is the 90-day window from `profiles.created_at`. Admins are exempt. When
 * billing lands, pass the real plan here and nothing else changes.
 *
 * What it does: renders the `pilot_paperwork_request` email (editable on the
 * admin Email Templates page; the default is used until it is saved there),
 * sends it through the email seam — delivered when ZeptoMail is configured,
 * otherwise recorded — and writes `paperwork_requested` to the trip history
 * so the tab can show "Requested on …".
 */

const schema = z.object({ participant_id: z.string().uuid() })
const TEMPLATE_KEY = 'pilot_paperwork_request'

export async function POST(req: NextRequest, ctx: { params: Promise<{ id: string }> }) {
  const { id: tripId } = await ctx.params
  const guard = await requireParticipant(tripId)
  if (!guard.ok) return guard.response
  const { user, participant } = guard

  const parsed = schema.safeParse(await req.json().catch(() => ({})))
  if (!parsed.success) return NextResponse.json({ error: 'Invalid request.' }, { status: 400 })

  const admin = createAdminClient()
  const [{ data: pilotRow }, { data: tripRow }, { data: profileRow }] = await Promise.all([
    admin.from('trip_participants').select('*').eq('id', parsed.data.participant_id).eq('trip_id', tripId).maybeSingle(),
    admin.from('trips').select('*').eq('id', tripId).maybeSingle(),
    admin.from('profiles').select('*').eq('id', user.id).maybeSingle(),
  ])
  const pilot = pilotRow as TripParticipant | null
  const trip = tripRow as Trip | null
  const profile = profileRow as Profile | null
  if (!trip) return NextResponse.json({ error: 'Trip not found.' }, { status: 404 })
  if (!pilot || pilot.status === 'removed') return NextResponse.json({ error: 'That pilot is not on this trip.' }, { status: 404 })
  if (pilot.role !== 'pilot') return NextResponse.json({ error: 'Paperwork is requested from pilots only.' }, { status: 400 })

  const isAdmin = user.role === 'admin'
  if (!canManagePilotAccess({ pilotInvitedBy: pilot.invited_by, viewerUserId: user.id, viewerIsAdmin: isAdmin })) {
    return NextResponse.json({ error: 'Only the person who invited this pilot can request their paperwork.' }, { status: 403 })
  }

  if (!isAdmin) {
    const access = pilotPaperworkAccess({ plan: 'Free', signedUpAt: profile?.created_at ?? new Date().toISOString(), today: localToday() })
    if (access.mode === 'locked') {
      return NextResponse.json({ error: 'Requesting pilot paperwork is a Starter feature.', locked: true }, { status: 402 })
    }
  }

  // Editable copy first; the shipped default until an admin saves one.
  const { data: saved } = await admin.from('email_templates').select('subject, body, active').eq('key', TEMPLATE_KEY).maybeSingle()
  const fallback = DEFAULT_TEMPLATES.find((t) => t.key === TEMPLATE_KEY)!
  const template = saved ?? { subject: fallback.subject, body: fallback.body, active: true }
  if (!template.active) return NextResponse.json({ error: 'The paperwork request email is turned off.' }, { status: 409 })

  // A real pilot participant has no account type on file yet; the driver's
  // list is the fuller one and the one a CDL holder is asked for.
  const paperworkList = documentSlotsFor('pilot_driver')
    .filter((s) => s.required)
    .map((s) => `- ${s.label}`)
    .join('\n')
  const requesterLabel = participant.name || user.name || user.email
  const data: Record<string, string> = {
    pilot_name: pilot.name || pilot.email,
    pilot_kind: 'Pilot driver',
    requester_name: requesterLabel,
    requester_role: participant.role,
    requester_email: user.email,
    trip_id: trip.ref_code,
    pickup_location: trip.origin || '—',
    delivery_location: trip.destination || '—',
    paperwork_list: paperworkList,
    workspace_link: `${publicOrigin(req)}/trips/${trip.id}`,
    support_email: SUPPORT_EMAIL,
    ...DASHBOARD_LINKS,
  }
  // Central sender (2026-09-22): transactional stream, preferences and delivery suppression applied, message logged.
  const result = await sendPlatformEmail({ templateKey: TEMPLATE_KEY, to: pilot.email, data, userId: pilot.user_id ?? null, actorUserId: user.id, clean: false, tags: { kind: 'paperwork_request', trip: trip.ref_code } })

  await logTripEvent({
    tripId,
    actorId: user.id,
    actorLabel: requesterLabel,
    action: PAPERWORK_REQUESTED_ACTION,
    detail: {
      email: pilot.email,
      participant_id: pilot.id,
      requested_by_role: participant.role,
      email_status: result.status,
      ...(result.status === 'failed' || result.status === 'suppressed' ? { error: result.reason } : {}),
    },
  })

  if (result.status === 'failed') {
    return NextResponse.json({ error: `The request was recorded but the email could not be sent: ${result.reason}` }, { status: 502 })
  }
  if (result.status === 'suppressed') {
    return NextResponse.json({ error: `The request was recorded but this address cannot receive email right now (${result.reason?.replace(/_/g, ' ')}).` }, { status: 409 })
  }
  return NextResponse.json({ ok: true, email_status: result.status })
}
