/**
 * The permit request email to Synchron Permits (Nash, 2026-09-23).
 *
 * "Every time a broker or a carrier clicks Request new permit… an email
 * should be triggered to Synchron Permits. It will include the rate
 * confirmation, the previous permit that is already attached to the order
 * as a point of reference, the overall dimensions and the load dimensions,
 * and request a new permit for the selected state… sent to
 * info@synchronpermits.com." — the intake address was then set to
 * synchronpermits@gmail.com (2026-09-23) and every environment delivers.
 *
 * Pure: turns the trip, unit sheet, permit, requester and attachments into
 * the template variables. The I/O (loading, fetching the PDFs, sending) is
 * in src/lib/data/permit-request-email.ts.
 */
import { formatFullDate, formatInches, formatWeight } from '@/lib/format'
import { stateName } from '@/lib/domain/states'
import type { Permit, Trip, TripUnit } from '@/types/db'

export const SYNCHRON_ORDER_EMAIL_DEFAULT = 'synchronpermits@gmail.com'
export const PERMIT_REQUEST_TEMPLATE = 'permit_reorder_request'
/** One attachment at most this size; the email at most 15 MB overall (ZeptoMail limit). */
export const MAX_ATTACHMENT_BYTES = 8 * 1024 * 1024
export const MAX_EMAIL_BYTES = 15 * 1024 * 1024

export interface RequesterInfo {
  name: string
  email: string
  phone: string | null
  role: string
  company: string | null
  companyMc: string | null
}

export interface AttachmentSummary { name: string; label: string; sizeBytes: number }

export const ROLE_LABELS: Record<string, string> = { broker: 'Freight Broker', dispatcher: 'Carrier Dispatcher', driver: 'Carrier Driver', pilot: 'Pilot Car', admin: 'HeavyHaul Agent staff' }

/** 600 in → 50'0" (600 in); null → "not on file". */
export function dim(inches: number | null | undefined): string {
  if (inches == null) return 'not on file'
  return `${formatInches(inches)} (${inches} in)`
}

/**
 * One dimensions line from whatever the order actually holds. Only the
 * measurements on file are printed — never "not on file L × not on file W"
 * (Nash, 2026-09-23: pull it from the actual trip).
 */
export function dimensionLine(d: { length_in: number | null; width_in: number | null; height_in: number | null; weight_lbs: number | null }, emptyNote: string): string {
  const parts = [
    d.length_in != null ? `${dim(d.length_in)} long` : '',
    d.width_in != null ? `${dim(d.width_in)} wide` : '',
    d.height_in != null ? `${dim(d.height_in)} high` : '',
    d.weight_lbs != null ? formatWeight(d.weight_lbs) : '',
  ].filter(Boolean)
  return parts.length ? parts.join(' · ') : emptyNote
}

/** Attachment names Synchron can read at a glance: "HH-KX9QG4 — NV permit 503912.pdf". */
export function attachmentFileName(parts: { tripRef: string; label: string; originalName: string }): string {
  const ext = (parts.originalName.match(/\.[a-z0-9]{1,5}$/i) ?? ['.pdf'])[0].toLowerCase()
  const clean = `${parts.tripRef} — ${parts.label}`.replace(/[\\/:*?"<>|]/g, '-').replace(/\s+/g, ' ').trim()
  return `${clean}${ext}`
}

export function payerLabel(payer: 'requester' | 'broker' | 'carrier' | null | undefined, requester: RequesterInfo, trip: Pick<Trip, 'carrier_name'>): string {
  if (payer === 'broker') return `The freight broker on this trip${requester.role === 'broker' ? ` (${requester.name}${requester.company ? `, ${requester.company}` : ''})` : ''}`
  if (payer === 'carrier') return `The carrier${trip.carrier_name ? ` (${trip.carrier_name})` : ''}`
  return `The requester — ${requester.name}${requester.company ? `, ${requester.company}` : ''}`
}

export function axleSummary(unit: TripUnit | null): string {
  if (!unit) return 'Unit sheet not on file yet'
  const parts: string[] = []
  if (unit.axle_count != null) parts.push(`${unit.axle_count} axles`)
  if (unit.axle_spacings_in?.length) parts.push(`spacings ${unit.axle_spacings_in.map((s) => formatInches(s)).join(' · ')}`)
  if (unit.kingpin_to_rear_axle_in != null) parts.push(`KPTRA ${formatInches(unit.kingpin_to_rear_axle_in)}`)
  if (unit.axle_weights_lbs?.length) parts.push(`axle weights ${unit.axle_weights_lbs.map((w) => w.toLocaleString()).join(' / ')} lbs`)
  return parts.join(' · ') || 'Axle details not on file'
}

export function vehicleLine(kind: 'truck' | 'trailer', unit: TripUnit | null): string {
  if (!unit) return 'not on file'
  const u = kind === 'truck'
    ? { unit_number: unit.truck_unit_number, vin: unit.truck_vin, make: unit.truck_make, model: unit.truck_model, year: unit.truck_year, axles: null as number | null }
    : { unit_number: unit.trailer_unit_number, vin: unit.trailer_vin, make: unit.trailer_make, model: unit.trailer_model, year: unit.trailer_year, axles: unit.trailer_axle_count }
  const parts = [[u.year, u.make, u.model].filter(Boolean).join(' '), u.unit_number ? `unit ${u.unit_number}` : '', u.vin ? `VIN ${u.vin}` : '', u.axles != null ? `${u.axles} axles` : ''].filter(Boolean)
  return parts.join(' · ') || 'not on file'
}

export function previousPermitSummary(permit: Permit | null, state: string): string {
  if (!permit) return `No ${state} permit is on file for this order yet — this is a first permit for ${state}.`
  const bits = [permit.permit_number ? `permit ${permit.permit_number}` : 'permit number not on file', permit.effective_date ? `effective ${formatFullDate(permit.effective_date)}` : '', permit.expiration_date ? `expired ${formatFullDate(permit.expiration_date)}` : '']
    .filter(Boolean).join(', ')
  const dims = [permit.permit_length_in, permit.permit_width_in, permit.permit_height_in, permit.permit_weight_lbs].some((v) => v != null)
    ? ` It was issued for ${dimensionLine({ length_in: permit.permit_length_in, width_in: permit.permit_width_in, height_in: permit.permit_height_in, weight_lbs: permit.permit_weight_lbs }, '—')}.`
    : ''
  return `The previous ${state} ${bits}.${dims} A copy is attached as a point of reference.`
}

export function attachmentsList(list: AttachmentSummary[]): string {
  if (list.length === 0) return 'No files could be attached — the workspace link below has every document on this order.'
  const title = (s: string) => s.charAt(0).toUpperCase() + s.slice(1)
  return list.map((a) => `- ${title(a.label)}: ${a.name} (${(a.sizeBytes / 1024).toFixed(0)} KB)`).join('\n')
}

/** Everything the template can print. Blank values are dropped from the rendered email (renderTemplateClean). */
export function permitRequestData(params: {
  trip: Trip
  unit: TripUnit | null
  stateCode: string
  previousPermit: Permit | null
  requester: RequesterInfo
  payer: 'requester' | 'broker' | 'carrier' | null
  notes: string | null
  orderNumber: string | null
  attachments: AttachmentSummary[]
  workspaceLink: string
  rateConUrl?: string
  synchronEmail: string
  now?: Date
}): Record<string, string> {
  const { trip, unit, requester } = params
  const state = stateName(params.stateCode) || params.stateCode
  const rateCon = params.attachments.find((a) => a.label.toLowerCase().includes('rate confirmation'))
  return {
    permit_state: state,
    permit_state_code: params.stateCode.toUpperCase(),
    trip_id: trip.ref_code,
    order_number: params.orderNumber ?? '',
    source_order_number: trip.source_order_number ?? '',
    requester_name: requester.name,
    requester_role: requester.role,
    requester_role_label: ROLE_LABELS[requester.role] ?? requester.role,
    requester_email: requester.email,
    requester_phone: requester.phone ?? '',
    requester_company: requester.company ? `${requester.company}${requester.companyMc ? ` (MC ${requester.companyMc})` : ''}` : '',
    requester_company_suffix: requester.company ? `, ${requester.company}` : '',
    // One non-empty line: renderTemplateClean drops any line holding an empty variable,
    // which silently removed the opening sentence (2026-09-23).
    requester_line: `${requester.name} (${ROLE_LABELS[requester.role] ?? requester.role}${requester.company ? `, ${requester.company}${requester.companyMc ? ` · MC ${requester.companyMc}` : ''}` : ''})`,
    payer: payerLabel(params.payer, requester, trip),
    carrier_company: trip.carrier_name || 'not on file',
    unit_number: trip.unit_number ?? '',
    commodity: trip.commodity || 'not on file',
    pickup_location: trip.origin || 'not on file',
    delivery_location: trip.destination || 'not on file',
    pickup_date: trip.pickup_date ? formatFullDate(trip.pickup_date) : '',
    delivery_date: trip.delivery_date ? formatFullDate(trip.delivery_date) : '',
    load_dimensions: dimensionLine({ length_in: trip.load_length_in, width_in: trip.load_width_in, height_in: trip.load_height_in, weight_lbs: trip.load_weight_lbs }, 'Not on file on this order — please confirm with the requester.'),
    overall_dimensions: dimensionLine(
      { length_in: trip.overall_length_in, width_in: trip.overall_width_in, height_in: trip.overall_height_in, weight_lbs: trip.overall_weight_lbs },
      params.previousPermit && [params.previousPermit.permit_length_in, params.previousPermit.permit_width_in, params.previousPermit.permit_height_in].some((v) => v != null)
        ? `Not on file on this order. For reference, the previous ${state} permit was issued for ${dimensionLine({ length_in: params.previousPermit.permit_length_in, width_in: params.previousPermit.permit_width_in, height_in: params.previousPermit.permit_height_in, weight_lbs: params.previousPermit.permit_weight_lbs }, '—')}.`
        : 'Not on file on this order — please confirm with the requester.',
    ),
    axle_summary: axleSummary(unit),
    truck_info: vehicleLine('truck', unit),
    trailer_info: vehicleLine('trailer', unit),
    permit_number: params.previousPermit?.permit_number ?? '',
    permit_expiration_date: params.previousPermit?.expiration_date ? formatFullDate(params.previousPermit.expiration_date) : '',
    previous_permit_summary: previousPermitSummary(params.previousPermit, state),
    rate_confirmation_summary: rateCon
      ? `The rate confirmation is attached (${rateCon.name}) and available at the link below.`
      : 'The rate confirmation is available at the download link below.',
    rate_confirmation_url: params.rateConUrl ?? '',
    // The permit for the state being requested, named so the reader knows which file is which.
    previous_permit_attachment: params.attachments.find((a) => a.label.toLowerCase().includes('permit'))?.name ?? '',
    attachments_list: attachmentsList(params.attachments),
    request_notes: params.notes ?? '',
    workspace_link: params.workspaceLink,
    synchron_order_email: params.synchronEmail,
    created_datetime: (params.now ?? new Date()).toLocaleString('en-US', { year: 'numeric', month: 'short', day: '2-digit', hour: 'numeric', minute: '2-digit', timeZone: 'America/New_York' }) + ' ET',
  }
}

/** Keep the email under the provider limit: drop the largest optional file first, never the previous permit. */
export function fitAttachments<T extends { sizeBytes: number; label: string }>(files: T[], maxTotal = MAX_EMAIL_BYTES): { kept: T[]; dropped: T[] } {
  const kept = files.filter((f) => f.sizeBytes <= MAX_ATTACHMENT_BYTES)
  const dropped = files.filter((f) => f.sizeBytes > MAX_ATTACHMENT_BYTES)
  const total = () => kept.reduce((a, f) => a + f.sizeBytes, 0)
  while (total() > maxTotal && kept.length) {
    const candidates = kept.filter((f) => !/^previous .*permit/i.test(f.label))
    const victim = (candidates.length ? candidates : kept).sort((a, b) => b.sizeBytes - a.sizeBytes)[0]
    kept.splice(kept.indexOf(victim), 1)
    dropped.push(victim)
  }
  return { kept, dropped }
}
