import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { createAdminClient } from '@/lib/supabase/admin'
import { requireParticipant } from '@/lib/api-guard'
import { isMissingColumn } from '@/lib/db-compat'
import { logTripEvent } from '@/lib/audit'

/**
 * Unit profile for a trip (driver feedback 2026-09-04): axle count, axle
 * spacings/weights, truck info and trailer info. Pre-filled from the permits
 * where possible (extraction backend later); the driver can correct anything.
 * Every save is logged to trip history so the change stays transparent to
 * everyone on the trip — same rule as overall dimensions.
 */

const intOrNull = z.number().int().min(0).max(10_000_000).nullable()
const textOrNull = z.string().trim().max(120).nullable()
const yearOrNull = z.number().int().min(1900).max(2100).nullable()

const schema = z
  .object({
    axle_count: z.number().int().min(1).max(30).nullable(),
    axle_spacings_in: z.array(intOrNull).max(29).nullable(),
    axle_weights_lbs: z.array(intOrNull).max(30).nullable(),
    truck_unit_number: textOrNull,
    truck_vin: textOrNull,
    truck_make: textOrNull,
    truck_model: textOrNull,
    truck_year: yearOrNull,
    trailer_unit_number: textOrNull,
    trailer_vin: textOrNull,
    trailer_make: textOrNull,
    trailer_model: textOrNull,
    trailer_year: yearOrNull,
    trailer_axle_count: z.number().int().min(1).max(30).nullable(),
    // Kingpin to rear axle (KPTRA) — "the last one… extremely important" (Task 76).
    kingpin_to_rear_axle_in: intOrNull,
  })
  .partial()
  .refine((v) => Object.keys(v).length > 0, { message: 'No fields to update.' })

// The unit profile belongs to the trip: broker/carrier side manages it, and
// per the driver feedback the driver can go there and change it too.
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 the unit profile.' },
      { status: 403 },
    )
  }

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

  const admin = createAdminClient()
  const write = (payload: Record<string, unknown>) =>
    admin
      .from('trip_units')
      .upsert({ trip_id: tripId, ...payload, updated_at: new Date().toISOString() }, { onConflict: 'trip_id' })
      .select()
      .single()

  let { data: unit, error } = await write(fields)
  if (isMissingColumn(error, 'kingpin_to_rear_axle_in')) {
    // Migration 0011 not applied yet — save everything else rather than
    // failing the whole profile, and tell the driver what was not saved.
    const { kingpin_to_rear_axle_in: _skipped, ...rest } = fields
    void _skipped
    ;({ data: unit, error } = await write(rest))
    if (!error && unit && fields.kingpin_to_rear_axle_in != null) {
      return NextResponse.json({
        ok: true,
        unit,
        note: 'Saved — the kingpin-to-rear-axle value needs database migration 0011 before it can be stored.',
      })
    }
  }
  if (error || !unit) {
    return NextResponse.json({ error: 'Could not save the unit profile.' }, { status: 500 })
  }

  // Transparency (Nash): everyone on the trip sees who changed the unit profile.
  await logTripEvent({
    tripId,
    actorId: user.id,
    actorLabel: participant.name || user.email || 'participant',
    action: 'unit_updated',
    detail: fields,
  })

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