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'

/**
 * Overall Dimensions (per the client meeting): brokers and carriers can
 * correct the load dimensions manually — the AI extraction is a starting
 * point, not the last word. Every permit is re-verified against the new
 * dimensions and the dimension warnings are refreshed.
 */

const dim = z.number().int().min(0).max(10_000_000).nullable()
// Partial update: send only the fields being edited (Load section sends
// load_*, Overall Dimensions section sends overall_*).
const schema = z
  .object({
    load_length_in: dim,
    load_width_in: dim,
    load_height_in: dim,
    load_weight_lbs: dim,
    overall_length_in: dim,
    overall_width_in: dim,
    overall_height_in: dim,
    overall_weight_lbs: dim,
  })
  .partial()
  .refine((v) => Object.keys(v).length > 0, { message: 'No fields to update.' })

// Driver feedback 2026-09-04: the driver also manages his overall dimensions
// ("the driver can go there and change it") — every edit is logged to trip
// history, so the change stays transparent to everyone on the trip.
const EDIT_ROLES = new Set(['broker', 'dispatcher', 'driver', 'admin'])

export async function PATCH(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

  if (!EDIT_ROLES.has(participant.role)) {
    return NextResponse.json(
      { error: 'Only the broker, carrier side, or driver can edit overall dimensions.' },
      { status: 403 },
    )
  }

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

  const admin = createAdminClient()
  const { data: trip, error: updateError } = await admin
    .from('trips')
    .update(dims)
    .eq('id', tripId)
    .select()
    .single()
  if (updateError || !trip) {
    return NextResponse.json({ error: 'Could not save dimensions.' }, { status: 500 })
  }

  // Re-verify all permits against the corrected dimensions.
  const { data: permits } = await admin.from('permits').select('*').eq('trip_id', tripId)
  const fresh = (permits ?? [])
    .flatMap((p) => computePermitWarnings(trip, p as Permit))
    .filter((w) => w.kind === 'dimension_mismatch')

  // Replace only the unresolved dimension warnings; other kinds stay put.
  await admin
    .from('warnings')
    .delete()
    .eq('trip_id', tripId)
    .eq('kind', 'dimension_mismatch')
    .eq('resolved', false)
  if (fresh.length > 0) {
    await admin.from('warnings').insert(
      fresh.map((w) => ({
        trip_id: tripId,
        permit_id: w.permitId ?? null,
        kind: w.kind,
        severity: w.severity,
        message: w.message,
      })),
    )
  }

  await logTripEvent({
    tripId,
    actorId: user.id,
    actorLabel: participant.name || user.email || 'participant',
    action: 'dimensions_updated',
    detail: dims,
  })

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