import 'server-only'

import { createAdminClient } from '@/lib/supabase/admin'

type Fields = Record<string, unknown>
type Admin = ReturnType<typeof createAdminClient>
export type ProfileEvidence = {
  source_system: string
  source_key: string
  trip_id?: string | null
  permit_id?: string | null
  document_id?: string | null
  synchron_order_token?: string | null
  synchron_permit_token?: string | null
  file_sha256?: string | null
  observation: Fields
}

const obj = (value: unknown): Fields => value && typeof value === 'object' && !Array.isArray(value) ? value as Fields : {}
const str = (value: unknown): string | null => typeof value === 'string' && value.trim() ? value.trim() : null
const digits = (value: unknown): string | null => str(value)?.replace(/\D/g, '') || null
const vin = (value: unknown): string | null => {
  const normalized = str(value)?.toUpperCase().replace(/[^A-Z0-9]/g, '')
  return normalized && /^[A-HJ-NPR-Z0-9]{17}$/.test(normalized) ? normalized : null
}
const number = (value: unknown): number | null => {
  const result = Number(value)
  return Number.isFinite(result) && result > 0 ? Math.round(result) : null
}
const blank = (value: unknown) => value === null || value === undefined || value === ''
const fail = (error: unknown, label: string) => { if (error) throw new Error(label) }

async function rows(admin: Admin, table: string, field: string, value: string) {
  const result = await admin.from(table).select('*').eq(field, value).limit(5)
  fail(result.error, `${table}_lookup_failed`)
  return result.data || []
}

function mergeEmpty(current: Fields, candidate: Fields, conflicts: string[], prefix: string) {
  const patch: Fields = {}
  for (const [key, value] of Object.entries(candidate)) {
    if (blank(value)) continue
    if (blank(current[key])) patch[key] = value
    else {
      const existing = ['mc_number', 'dot_number'].includes(key) ? digits(current[key]) : key === 'vin' ? vin(current[key]) : String(current[key]).trim().toUpperCase()
      const incoming = ['mc_number', 'dot_number'].includes(key) ? digits(value) : key === 'vin' ? vin(value) : String(value).trim().toUpperCase()
      if (existing !== incoming) conflicts.push(`${prefix}.${key}`)
    }
  }
  return patch
}

async function carrier(admin: Admin, evidence: Fields, conflicts: string[]) {
  const token = str(evidence.synchron_token)
  const mc = digits(evidence.mc_number)
  const dot = digits(evidence.dot_number)
  const candidates = new Map<string, Fields>()
  if (token) for (const row of await rows(admin, 'companies', 'source_token', token)) if (row.company_type === 'carrier') candidates.set(row.id, row)
  if (mc) for (const row of await rows(admin, 'companies', 'mc_normalized', mc)) if (row.company_type === 'carrier') candidates.set(row.id, row)
  if (dot) for (const row of await rows(admin, 'companies', 'dot_normalized', dot)) if (row.company_type === 'carrier') candidates.set(row.id, row)
  if (candidates.size > 1) { conflicts.push('carrier.identity_collision'); return null }
  const current = [...candidates.values()][0]
  const candidate: Fields = {
    mc_number: mc, dot_number: dot, corporate_email: str(evidence.email),
    corporate_phone: str(evidence.phone), physical_address: str(evidence.address),
  }
  if (current) {
    if (current.company_type !== 'carrier' || current.merged_into) { conflicts.push('carrier.invalid_match'); return null }
    if ((mc && current.mc_normalized && current.mc_normalized !== mc)
      || (dot && current.dot_normalized && current.dot_normalized !== dot)
      || (token && current.source_token && current.source_token !== token)) {
      conflicts.push('carrier.identifier_conflict')
      return null
    }
    const patch = mergeEmpty(current, candidate, conflicts, 'carrier')
    if (token && !current.source_token) patch.source_token = token
    if (Object.keys(patch).length) {
      const result = await admin.from('companies').update(patch).eq('id', current.id)
      fail(result.error, 'carrier_update_failed')
    }
    return current.id as string
  }
  // A name or email alone is evidence, never an automatic carrier identity.
  if (!token && !mc && !dot) return null
  const name = str(evidence.name) || `Carrier ${mc || dot || token}`
  const result = await admin.from('companies').insert({
    legal_name: name, display_name: name, company_type: 'carrier', is_placeholder: true,
    verification_status: 'unverified', source_system: token ? 'synchron' : 'permit', source_token: token,
    ...candidate,
  }).select('id').single()
  fail(result.error, 'carrier_create_failed')
  return result.data!.id as string
}

async function equipment(admin: Admin, kind: 'truck' | 'trailer', evidence: Fields, companyId: string | null, conflicts: string[]) {
  const token = str(evidence.synchron_token)
  const validVin = vin(evidence.vin)
  const unit = str(evidence.unit_number)
  const matches = new Map<string, Fields>()
  if (token) for (const row of await rows(admin, 'fleet_units', 'source_token', token)) if (row.kind === kind) matches.set(row.id, row)
  if (validVin) for (const row of await rows(admin, 'fleet_units', 'vin_normalized', validVin)) if (row.kind === kind) matches.set(row.id, row)
  if (companyId && unit) {
    const result = await admin.from('fleet_units').select('*').eq('kind', kind).eq('company_id', companyId).ilike('unit_number', unit).limit(5)
    fail(result.error, 'fleet_lookup_failed')
    for (const row of result.data || []) matches.set(row.id, row)
  }
  if (matches.size > 1) { conflicts.push(`${kind}.identity_collision`); return null }
  const current = [...matches.values()][0]
  const candidate: Fields = {
    vin: validVin, unit_number: unit, license_plate: str(evidence.license_plate),
    license_state: str(evidence.license_state), make: str(evidence.make), model: str(evidence.model),
    year: number(evidence.year), axle_count: number(evidence.axle_count),
    ...(kind === 'trailer' ? { trailer_type: str(evidence.trailer_type), length_in: number(evidence.length_in), empty_weight_lbs: number(evidence.empty_weight_lbs) } : {}),
  }
  if (current) {
    if (companyId && current.company_id && current.company_id !== companyId) {
      conflicts.push(`${kind}.carrier_conflict`)
      return null
    }
    if ((validVin && current.vin_normalized && current.vin_normalized !== validVin)
      || (token && current.source_token && current.source_token !== token)) {
      conflicts.push(`${kind}.identifier_conflict`)
      return null
    }
    const patch = mergeEmpty(current, candidate, conflicts, kind)
    if (companyId && !current.company_id) patch.company_id = companyId
    if (token && !current.source_token) patch.source_token = token
    if (Object.keys(patch).length) {
      const result = await admin.from('fleet_units').update(patch).eq('id', current.id)
      fail(result.error, 'fleet_update_failed')
    }
    return current.id as string
  }
  if (!validVin && !token && !(companyId && unit)) return null
  const result = await admin.from('fleet_units').insert({
    company_id: companyId, kind, source_system: token ? 'synchron' : 'permit',
    source_token: token, ...candidate,
  }).select('id').single()
  fail(result.error, 'fleet_create_failed')
  return result.data!.id as string
}

/** Idempotent reconciliation; permit evidence cannot verify users or change access. */
export async function reconcilePermitProfiles(input: ProfileEvidence) {
  const admin = createAdminClient()
  const observation = obj(input.observation)
  let tripId = input.trip_id || null
  if (!tripId && input.synchron_order_token) {
    const trip = await admin.from('trips').select('id').eq('synchron_order_token', input.synchron_order_token).maybeSingle()
    fail(trip.error, 'trip_lookup_failed')
    tripId = trip.data?.id || null
    // Older historical imports predate synchron_order_token (migration 0035)
    // but retained the same eight-digit token as source_order_number.
    if (!tripId && /^\d{8}$/.test(input.synchron_order_token)) {
      const legacy = await admin.from('trips').select('id').eq('source_system', 'synchron')
        .eq('source_order_number', input.synchron_order_token).limit(2)
      fail(legacy.error, 'legacy_trip_lookup_failed')
      if (legacy.data?.length === 1) tripId = legacy.data[0].id
    }
  }
  const saved = await admin.from('permit_profile_observations').upsert({
    source_system: input.source_system, source_key: input.source_key,
    trip_id: tripId, permit_id: input.permit_id || null, document_id: input.document_id || null,
    synchron_order_token: input.synchron_order_token || null,
    synchron_permit_token: input.synchron_permit_token || null,
    file_sha256: input.file_sha256 || null, observation,
  }, { onConflict: 'source_system,source_key' }).select('id').single()
  fail(saved.error, 'observation_save_failed')
  const conflicts: string[] = []
  const carrierId = await carrier(admin, obj(observation.carrier), conflicts)
  const truckId = await equipment(admin, 'truck', obj(observation.truck), carrierId, conflicts)
  const trailerId = await equipment(admin, 'trailer', obj(observation.trailer), carrierId, conflicts)
  if (tripId) {
    const config = obj(observation.configuration)
    const history = await admin.from('trip_equipment_history').upsert({
      observation_id: saved.data!.id, trip_id: tripId, carrier_company_id: carrierId,
      truck_fleet_unit_id: truckId, trailer_fleet_unit_id: trailerId,
      axle_spacings_in: Array.isArray(config.axle_spacings) ? config.axle_spacings : null,
      axle_weights_lbs: Array.isArray(config.axle_weights) ? config.axle_weights : null,
      overall_length_in: number(config.overall_length_in), overall_width_in: number(config.overall_width_in),
      overall_height_in: number(config.overall_height_in), gross_weight_lbs: number(config.gross_weight_lbs),
    }, { onConflict: 'observation_id' }).select('id').single()
    fail(history.error, 'trip_history_save_failed')
    const participants = await admin.from('trip_participants').select('id,role').eq('trip_id', tripId).in('role', ['driver', 'dispatcher'])
    fail(participants.error, 'participants_lookup_failed')
    for (const person of participants.data || []) {
      const linked = await admin.from('trip_equipment_history_people').upsert({
        history_id: history.data!.id, participant_id: person.id, role: person.role,
      }, { onConflict: 'history_id,participant_id' })
      fail(linked.error, 'history_person_save_failed')
    }
    const trip = await admin.from('trips').select('carrier_company_id').eq('id', tripId).single()
    fail(trip.error, 'trip_lookup_failed')
    if (carrierId && trip.data?.carrier_company_id && trip.data.carrier_company_id !== carrierId) conflicts.push('trip.carrier_conflict')
    if (carrierId && !trip.data?.carrier_company_id) {
      const linked = await admin.from('trips').update({ carrier_company_id: carrierId }).eq('id', tripId).is('carrier_company_id', null)
      fail(linked.error, 'trip_carrier_save_failed')
    }
    const unit = await admin.from('trip_units').select('truck_fleet_unit_id,trailer_fleet_unit_id').eq('trip_id', tripId).maybeSingle()
    fail(unit.error, 'trip_unit_lookup_failed')
    if (truckId && unit.data?.truck_fleet_unit_id && unit.data.truck_fleet_unit_id !== truckId) conflicts.push('trip.truck_conflict')
    if (trailerId && unit.data?.trailer_fleet_unit_id && unit.data.trailer_fleet_unit_id !== trailerId) conflicts.push('trip.trailer_conflict')
    const patch: Fields = {}
    if (truckId && !unit.data?.truck_fleet_unit_id) patch.truck_fleet_unit_id = truckId
    if (trailerId && !unit.data?.trailer_fleet_unit_id) patch.trailer_fleet_unit_id = trailerId
    if (Object.keys(patch).length) {
      const linked = await admin.from('trip_units').upsert({ trip_id: tripId, ...patch }, { onConflict: 'trip_id' })
      fail(linked.error, 'trip_unit_save_failed')
    }
  }
  const status = conflicts.length ? 'needs_review' : carrierId || truckId || trailerId ? 'linked' : 'insufficient_identity'
  const result = await admin.from('permit_profile_observations').update({
    carrier_company_id: carrierId, truck_fleet_unit_id: truckId, trailer_fleet_unit_id: trailerId,
    status, conflicts, processed_at: new Date().toISOString(),
  }).eq('id', saved.data!.id)
  fail(result.error, 'observation_update_failed')
  return { status, conflicts, carrierId, truckId, trailerId }
}
