import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { createAdminClient } from '@/lib/supabase/admin'
import { requireParticipant } from '@/lib/api-guard'
import { computePermitWarnings } from '@/lib/domain/warnings'
import { logTripEvent } from '@/lib/audit'
import type { Permit } from '@/types/db'

/**
 * Manual permit correction — ADMIN ONLY (internal). Nash (2026-09-04): "the
 * permit, we read that from the file. We do not give the power for the user
 * to edit those." No UI reaches this anymore; it stays as an internal fix
 * path when extraction misreads a file. Warnings recompute after every edit.
 */

const dim = z.number().int().min(0).max(10_000_000).nullable()
const dateStr = z
  .string()
  .regex(/^\d{4}-\d{2}-\d{2}$/)
  .nullable()
const schema = z.object({
  state_code: z.string().trim().toUpperCase().length(2),
  permit_number: z.string().trim().max(60).nullable(),
  effective_date: dateStr,
  expiration_date: dateStr,
  permit_length_in: dim,
  permit_width_in: dim,
  permit_height_in: dim,
  permit_weight_lbs: dim,
})

const EDIT_ROLES = new Set(['admin'])

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

  if (!EDIT_ROLES.has(participant.role)) {
    return NextResponse.json(
      { error: 'Permit fields are read from the file and cannot be edited.' },
      { status: 403 },
    )
  }

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

  const admin = createAdminClient()
  const { data: permit, error: updateError } = await admin
    .from('permits')
    .update({
      ...parsed.data,
      permit_number: parsed.data.permit_number || null,
      // a human verified/corrected the fields
      extraction_status: 'processed',
    })
    .eq('id', permitId)
    .eq('trip_id', tripId)
    .select()
    .single()
  if (updateError || !permit) {
    return NextResponse.json({ error: 'Could not save the permit.' }, { status: 500 })
  }

  // Recompute this permit's warnings against the trip.
  const { data: trip } = await admin.from('trips').select('*').eq('id', tripId).single()
  const { data: siblings } = await admin
    .from('permits')
    .select('id, state_code, effective_date, expiration_date')
    .eq('trip_id', tripId)
  const fresh = trip ? computePermitWarnings(trip, permit as Permit, new Date(), siblings ?? []) : []

  await admin
    .from('warnings')
    .delete()
    .eq('trip_id', tripId)
    .eq('permit_id', permitId)
    .eq('resolved', false)
  if (fresh.length > 0) {
    await admin.from('warnings').insert(
      fresh.map((w) => ({
        trip_id: tripId,
        permit_id: permitId,
        kind: w.kind,
        severity: w.severity,
        message: w.message,
      })),
    )
  }

  await logTripEvent({
    tripId,
    actorId: user.id,
    actorLabel: participant.name || user.email || 'participant',
    action: 'permit_updated',
    detail: { state: permit.state_code, permit_number: permit.permit_number },
  })

  return NextResponse.json({ ok: true, permit, warnings: fresh.length })
}
