import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { createAdminClient } from '@/lib/supabase/admin'
import { requireParticipant } from '@/lib/api-guard'
import { logTripEvent } from '@/lib/audit'
import {
  canManagePilotAccess,
  describePilotAccess,
  PILOT_ACCESS_SHARED_ACTION,
  type PilotInviteAccess,
} from '@/lib/domain/pilot'
import type { TripParticipant } from '@/types/db'

/**
 * Share permits with a pilot already on the trip (Nash, 2026-09-17).
 *
 * "If I chose a pilot and it said to decide later, the user that invited that
 * pilot or that pilot dispatch has the power to decide… he can share a
 * specific state, a specific permit, or the entire trip, or multiple permits
 * or multiple states."
 *
 * Who may call it: the person who invited THAT pilot, or an admin — "an admin
 * has overall power to do the same thing for any pilot car". The rule lives in
 * `canManagePilotAccess`; this route is where it is enforced.
 *
 * The choice is appended to the trip history as `pilot_access_shared`, which
 * is what `pilotAccessFromEvents` reads back as the pilot's current access
 * (latest event wins) — the same mechanism the invitation already used, so
 * the driver's state cards and the My Pilot access line update at once.
 */

const accessSchema = z.discriminatedUnion('type', [
  z.object({ type: z.literal('full_trip') }),
  z.object({ type: z.literal('states'), states: z.array(z.string().trim().length(2)).min(1).max(60) }),
  z.object({
    type: z.literal('permits'),
    permit_ids: z.array(z.string().uuid()).min(1).max(200),
    labels: z.array(z.string().max(80)).max(200).optional(),
  }),
  z.object({ type: z.literal('decide_later') }),
])

const schema = z.object({
  participant_id: z.string().uuid(),
  access: accessSchema,
})

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 access choice.' }, { status: 400 })
  const input = parsed.data

  const admin = createAdminClient()
  const { data: pilotRow } = await admin
    .from('trip_participants')
    .select('*')
    .eq('id', input.participant_id)
    .eq('trip_id', tripId)
    .maybeSingle()
  const pilot = pilotRow as TripParticipant | null
  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: 'Permits are shared with pilots only.' }, { status: 400 })
  }

  if (
    !canManagePilotAccess({
      pilotInvitedBy: pilot.invited_by,
      viewerUserId: user.id,
      viewerIsAdmin: user.role === 'admin',
    })
  ) {
    return NextResponse.json(
      { error: 'Only the person who invited this pilot can share permits with them.' },
      { status: 403 },
    )
  }

  // Everything shared must belong to this trip — a permit id from elsewhere
  // would otherwise be written into the pilot's access line.
  const access = input.access as PilotInviteAccess
  if (access.type === 'permits' || access.type === 'states') {
    const { data: permits } = await admin
      .from('permits')
      .select('id, state_code')
      .eq('trip_id', tripId)
    const rows = (permits ?? []) as { id: string; state_code: string }[]
    const unknown =
      access.type === 'permits'
        ? access.permit_ids.filter((id) => !rows.some((p) => p.id === id))
        : access.states.filter((s) => !rows.some((p) => p.state_code === s))
    if (unknown.length) {
      return NextResponse.json({ error: 'That permit or state is not on this trip.' }, { status: 400 })
    }
  }

  const describedAccess = describePilotAccess(access)
  await logTripEvent({
    tripId,
    actorId: user.id,
    actorLabel: participant.name || user.email || 'participant',
    action: PILOT_ACCESS_SHARED_ACTION,
    detail: {
      email: pilot.email,
      pilot_access: describedAccess,
      participant_id: pilot.id,
      shared_by_role: participant.role,
    },
  })

  return NextResponse.json({ ok: true, access: describedAccess })
}
