'use client'

import { useMemo, useState } from 'react'
import { toast } from 'sonner'
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import {
  brokerCanSeePilotInvoices,
  calculateInvoice,
  DUE_DATE_OPTIONS,
  dueDateFor,
  invoiceEmailSubject,
  money,
  nextInvoiceNumber,
  type DueDateKey,
  type InvoiceStatus,
  type RecipientType,
} from '@/lib/domain/invoicing'
import { DEFAULT_TEMPLATES, renderTemplate, TEMPLATE_SAMPLE_DATA } from '@/lib/email-templates'
import { buildInvoicePdf, openPdf } from '@/lib/demo/invoice-pdf'
import {
  newId,
  useExpenses,
  useInvoiceLog,
  useInvoices,
  usePaymentPrefs,
  type InvoiceRecipient,
  type PilotInvoice,
} from '@/lib/demo/invoicing-store'
import { demoDriver, demoVehicle, inviterOf, tripContactsOf, type DemoPilotAssignment } from '@/lib/demo/pilot'
import type { PilotAccountType } from '@/lib/domain/pilot'

/**
 * Trip Invoice Generator (article §8–§12, §15, §17, §30–§31).
 * Pre-fills from the assignment; the user enters the financial details; both
 * base calculations are shown and the greater one is used. Actions: Save
 * Draft · Preview PDF · Download PDF · Send Invoice. Sending opens the
 * recipient editor and shows the templated email (no email leaves the app).
 */

export interface InvoiceContext {
  assignment: DemoPilotAssignment
  ownerType: PilotAccountType
  ownerName: string
  ownerContact: string
  actorName: string
  /** Article §16 / Nash: broker sees invoices only when they invited the pilot or the pilot invited them. */
  brokerInvitedPilot: boolean
  pilotInvitedBroker: boolean
  brokerEmail?: string
}

export function InvoiceBuilder({
  ctx,
  existing,
  onClose,
}: {
  ctx: InvoiceContext
  existing?: PilotInvoice
  onClose: () => void
}) {
  const { assignment: a } = ctx
  const { invoices, save } = useInvoices()
  const { expenses } = useExpenses()
  const { prefs, save: savePrefs } = usePaymentPrefs()
  const { append: log } = useInvoiceLog()

  const drv = demoDriver(a.pilotDriverId)
  const veh = demoVehicle(a.vehicleId)
  const shared = a.permits.filter((p) => p.shared)
  const today = new Date().toISOString().slice(0, 10)

  const [f, setF] = useState(() => ({
    invoiceDate: existing?.invoiceDate ?? today,
    dueDateKey: (existing?.dueDateKey ?? null) as DueDateKey | null,
    miles: existing?.miles ?? 0,
    ratePerMile: existing?.ratePerMile ?? 0,
    days: existing?.days ?? 0,
    dailyRate: existing?.dailyRate ?? 0,
    overnights: existing?.overnights ?? 0,
    overnightFee: existing?.overnightFee ?? 0,
    customItems: existing?.customItems ?? [],
    expenseIds:
      existing?.expenseIds ?? expenses.filter((e) => e.assignmentId === a.id && e.includeOnInvoice).map((e) => e.id),
    // Nash: pre-filled from the last invoice; editable here.
    paymentInstructions: existing?.paymentInstructions ?? prefs.paymentInstructions,
    preferredPaymentMethod: existing?.preferredPaymentMethod ?? prefs.preferredPaymentMethod,
    notes: existing?.notes ?? '',
    // Default recipient = the person who invited the pilot (Nash, 2026-09-12).
    billToContactEmail: existing?.billToContactEmail ?? inviterOf(a).email,
    serviceDates: existing?.serviceDates ?? (shared.length ? `${shared[0].effective} → ${shared[shared.length - 1].expires}` : ''),
  }))
  const [sending, setSending] = useState(false)

  const assignmentExpenses = expenses.filter((e) => e.assignmentId === a.id)
  const calc = useMemo(
    () =>
      calculateInvoice({
        miles: f.miles,
        ratePerMile: f.ratePerMile,
        days: f.days,
        dailyRate: f.dailyRate,
        overnights: f.overnights,
        overnightFee: f.overnightFee,
        expenseAmounts: assignmentExpenses.filter((e) => f.expenseIds.includes(e.id)).map((e) => e.amount),
        customAmounts: f.customItems.map((c) => c.amount),
      }),
    [f, assignmentExpenses],
  )

  function build(status: InvoiceStatus, recipients: InvoiceRecipient[] = existing?.recipients ?? []): PilotInvoice {
    const now = new Date().toISOString()
    return {
      id: existing?.id ?? newId('inv'),
      assignmentId: a.id,
      tripRef: a.ref,
      ownerType: ctx.ownerType,
      ownerName: ctx.ownerName,
      ownerContact: ctx.ownerContact,
      billToCompany: a.carrier,
      billToContactName: tripContactsOf(a).find((c) => c.email === f.billToContactEmail)?.name ?? inviterOf(a).name,
      billToContactEmail: f.billToContactEmail,
      status,
      invoiceNumber: existing?.invoiceNumber ?? nextInvoiceNumber(invoices.map((i) => i.invoiceNumber), a.ref, f.invoiceDate),
      invoiceDate: f.invoiceDate,
      dueDateKey: f.dueDateKey,
      dueDate: dueDateFor(f.invoiceDate, f.dueDateKey),
      statesCovered: [...new Set(shared.map((p) => p.state))],
      permitsCovered: shared.map((p) => p.permitNumber),
      serviceDates: f.serviceDates,
      pilotRole: a.position,
      pilotDriverName: drv?.name ?? '',
      vehicleUsed: veh ? `${veh.unitNumber} · ${veh.year} ${veh.make} ${veh.model}` : '',
      truckReference: a.truckInfo ? `${a.truck} · VIN ${a.truckInfo.vin}` : a.truck,
      miles: f.miles,
      ratePerMile: f.ratePerMile,
      days: f.days,
      dailyRate: f.dailyRate,
      overnights: f.overnights,
      overnightFee: f.overnightFee,
      customItems: f.customItems,
      expenseIds: f.expenseIds,
      calc,
      paymentInstructions: f.paymentInstructions,
      preferredPaymentMethod: f.preferredPaymentMethod,
      notes: f.notes,
      recipients,
      createdBy: ctx.actorName,
      createdAt: existing?.createdAt ?? now,
      updatedAt: now,
      sentAt: existing?.sentAt,
      paidAt: existing?.paidAt,
    }
  }

  function persistPrefs() {
    savePrefs({ paymentInstructions: f.paymentInstructions, preferredPaymentMethod: f.preferredPaymentMethod })
  }

  function saveDraft() {
    const inv = build(existing?.status === 'Sent' ? 'Sent' : 'Draft')
    save(inv)
    persistPrefs()
    toast.success(`${inv.invoiceNumber} saved as ${inv.status.toLowerCase()}`)
    onClose()
  }

  async function pdf(mode: 'view' | 'download') {
    const inv = build(existing?.status ?? 'Draft')
    const bytes = await buildInvoicePdf(inv, assignmentExpenses)
    openPdf(bytes, `${inv.invoiceNumber}.pdf`, mode)
    log({ action: mode === 'view' ? 'Invoice previewed' : 'Invoice PDF downloaded', detail: `${inv.invoiceNumber} · ${a.ref} · by ${ctx.actorName}` })
  }

  const num = (k: keyof typeof f) => (e: React.ChangeEvent<HTMLInputElement>) => setF({ ...f, [k]: parseFloat(e.target.value) || 0 })

  return (
    <div className="space-y-4">
      <div className="flex flex-wrap items-center justify-between gap-2">
        <div>
          <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-slate-body/70">{existing ? `Edit ${existing.invoiceNumber}` : 'Create Invoice'}</p>
          <p className="text-sm font-bold">{a.origin} → {a.destination} <span className="font-normal text-slate-body">· {a.ref} · {a.id}</span></p>
        </div>
        <button onClick={onClose} className="text-xs font-semibold text-slate-body hover:text-ink">← Back</button>
      </div>

      {/* Pre-filled trip details (§8, §31) */}
      <div className="grid gap-2 rounded-2xl border border-line bg-paper p-4 text-xs sm:grid-cols-2">
        <Info k="Invoice from" v={`${ctx.ownerName} · ${ctx.ownerContact}`} />
        <Info k="Invoice to" v={`${a.carrier} · ${inviterOf(a).name} (${inviterOf(a).role.toLowerCase()} — invited you)`} />
        <Info k="States covered" v={[...new Set(shared.map((p) => p.state))].join(', ') || '—'} />
        <Info k="Permits covered" v={shared.map((p) => p.permitNumber).join(', ') || '—'} />
        <Info k="Pilot role" v={a.position} />
        <Info k="Pilot driver" v={drv?.name ?? '—'} />
        <Info k="Vehicle / unit" v={veh ? `${veh.unitNumber} · ${veh.year} ${veh.make} ${veh.model}` : '—'} />
        <Info k="Truck reference" v={a.truckInfo ? `${a.truck} · VIN ${a.truckInfo.vin}` : a.truck} />
        <div className="text-xs sm:col-span-2">
          <span className="text-slate-body">Bill-to email <span className="text-slate-body/70">(defaults to whoever invited you to this trip)</span></span>
          <ContactEmailInput
            value={f.billToContactEmail}
            onChange={(v) => setF({ ...f, billToContactEmail: v })}
            contacts={tripContactsOf(a)}
            className="mt-1"
          />
        </div>
        <label className="text-xs">
          <span className="text-slate-body">Service dates</span>
          <input value={f.serviceDates} onChange={(e) => setF({ ...f, serviceDates: e.target.value })} className="mt-1 w-full rounded-lg border border-line bg-white px-2.5 py-1.5" />
        </label>
        <label className="text-xs">
          <span className="text-slate-body">Invoice date</span>
          <input type="date" value={f.invoiceDate} onChange={(e) => setF({ ...f, invoiceDate: e.target.value })} className="mt-1 w-full rounded-lg border border-line bg-white px-2.5 py-1.5" />
        </label>
        <div className="text-xs sm:col-span-2">
          <span className="text-slate-body">Due date (optional)</span>
          <div className="mt-1 flex flex-wrap gap-1.5">
            {DUE_DATE_OPTIONS.map((o) => (
              <button key={o.key} onClick={() => setF({ ...f, dueDateKey: f.dueDateKey === o.key ? null : o.key })} className={`rounded-full px-2.5 py-1 text-[11px] font-semibold ring-1 ring-inset ${f.dueDateKey === o.key ? 'bg-navy-900 text-white ring-navy-900' : 'bg-white text-slate-body ring-line'}`}>
                {o.label}
              </button>
            ))}
            {f.dueDateKey && f.dueDateKey !== 'asap' && <span className="self-center text-slate-body">→ {dueDateFor(f.invoiceDate, f.dueDateKey)}</span>}
          </div>
        </div>
      </div>

      {/* Billing inputs (§9, §31) */}
      <div className="grid gap-3 rounded-2xl border border-line bg-white p-4 sm:grid-cols-2">
        <Num label="Miles" value={f.miles} onChange={num('miles')} />
        <Num label="Rate per mile ($)" value={f.ratePerMile} onChange={num('ratePerMile')} step="0.01" />
        <Num label="Number of days" value={f.days} onChange={num('days')} />
        <Num label="Daily rate ($)" value={f.dailyRate} onChange={num('dailyRate')} step="0.01" />
        <Num label="Number of overnights" value={f.overnights} onChange={num('overnights')} />
        <Num label="Overnight fee ($)" value={f.overnightFee} onChange={num('overnightFee')} step="0.01" />
      </div>

      {/* Custom line items (§12): description, amount, notes */}
      <div className="rounded-2xl border border-line bg-white p-4">
        <div className="flex items-center justify-between">
          <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-slate-body/70">Custom line items</p>
          <button onClick={() => setF({ ...f, customItems: [...f.customItems, { id: newId('li'), description: '', amount: 0, notes: '' }] })} className="text-xs font-bold text-info hover:underline">+ Add line item</button>
        </div>
        <p className="mt-1 text-[11px] text-slate-body">Flat rate, minimum charge, deadhead, detention, high pole fee, weekend fee, night movement, emergency service, route survey, cancellation, special escort, fuel surcharge, other.</p>
        {f.customItems.map((c) => (
          <div key={c.id} className="mt-2 grid gap-2 sm:grid-cols-[2fr_1fr_2fr_auto]">
            <input placeholder="Description" value={c.description} onChange={(e) => setF({ ...f, customItems: f.customItems.map((x) => (x.id === c.id ? { ...x, description: e.target.value } : x)) })} className="rounded-lg border border-line px-2.5 py-1.5 text-xs" />
            <input type="number" step="0.01" placeholder="Amount" value={c.amount || ''} onChange={(e) => setF({ ...f, customItems: f.customItems.map((x) => (x.id === c.id ? { ...x, amount: parseFloat(e.target.value) || 0 } : x)) })} className="rounded-lg border border-line px-2.5 py-1.5 text-xs" />
            <input placeholder="Notes" value={c.notes} onChange={(e) => setF({ ...f, customItems: f.customItems.map((x) => (x.id === c.id ? { ...x, notes: e.target.value } : x)) })} className="rounded-lg border border-line px-2.5 py-1.5 text-xs" />
            <button onClick={() => setF({ ...f, customItems: f.customItems.filter((x) => x.id !== c.id) })} className="text-xs text-slate-body hover:text-danger">✕</button>
          </div>
        ))}
      </div>

      {/* Expenses to include (§13) */}
      <div className="rounded-2xl border border-line bg-white p-4">
        <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-slate-body/70">Expenses on this invoice</p>
        {assignmentExpenses.length === 0 ? (
          <p className="mt-1 text-xs text-slate-body">No expenses recorded on this assignment. Add them under Expenses first.</p>
        ) : (
          <div className="mt-2 space-y-1">
            {assignmentExpenses.map((e) => (
              <label key={e.id} className="flex items-center justify-between gap-2 text-xs">
                <span className="flex items-center gap-2">
                  <input type="checkbox" checked={f.expenseIds.includes(e.id)} onChange={(ev) => setF({ ...f, expenseIds: ev.target.checked ? [...f.expenseIds, e.id] : f.expenseIds.filter((x) => x !== e.id) })} />
                  {e.category}{e.description ? ` · ${e.description}` : ''} · {e.expenseDate}{e.billable ? '' : ' · not billable'}
                </span>
                <span className="font-semibold">{money(e.amount)}</span>
              </label>
            ))}
          </div>
        )}
      </div>

      {/* Calculation output (§10, §11, §31) */}
      <div className="rounded-2xl border border-navy-900 bg-navy-900 p-4 text-xs text-white">
        <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-amber-brand">Calculation</p>
        <div className="mt-2 grid gap-1 sm:grid-cols-2">
          <Calc k={`Mileage total · ${f.miles} mi × ${money(f.ratePerMile)}`} v={money(calc.mileageTotal)} dim={calc.selectedBaseType !== 'mileage'} />
          <Calc k={`Daily total · ${f.days} × ${money(f.dailyRate)}`} v={money(calc.dailyTotal)} dim={calc.selectedBaseType !== 'daily'} />
        </div>
        <p className="mt-2 rounded-lg bg-white/10 px-2.5 py-1.5 text-[11px]">
          Selected billing method: <span className="font-bold capitalize">{calc.selectedBaseType}</span> — {calc.explanation}
        </p>
        <div className="mt-2 grid gap-1 sm:grid-cols-2">
          <Calc k="Selected base amount" v={money(calc.selectedBaseTotal)} />
          <Calc k={`Overnight total · ${f.overnights} × ${money(f.overnightFee)}`} v={money(calc.overnightTotal)} />
          <Calc k="Expense total" v={money(calc.expenseTotal)} />
          <Calc k="Custom total" v={money(calc.customTotal)} />
        </div>
        <div className="mt-3 flex items-center justify-between border-t border-white/20 pt-2 text-base font-extrabold">
          <span>Invoice total</span><span>{money(calc.invoiceTotal)}</span>
        </div>
      </div>

      {/* Payment instructions, preferred method, notes (Nash, 2026-09-12) */}
      <div className="grid gap-3 rounded-2xl border border-line bg-white p-4">
        <label className="text-xs">
          <span className="text-slate-body">Payment instructions <span className="text-slate-body/70">(remembered from your last invoice)</span></span>
          <textarea value={f.paymentInstructions} onChange={(e) => setF({ ...f, paymentInstructions: e.target.value })} rows={3} className="mt-1 w-full rounded-lg border border-line px-2.5 py-1.5" placeholder="Bank / ACH details, check payable to, reference the invoice number…" />
        </label>
        <label className="text-xs">
          <span className="text-slate-body">Preferred payment method / memo for the recipient</span>
          <input value={f.preferredPaymentMethod} onChange={(e) => setF({ ...f, preferredPaymentMethod: e.target.value })} className="mt-1 w-full rounded-lg border border-line px-2.5 py-1.5" placeholder="e.g. ACH preferred; company check accepted; pay within terms" />
        </label>
        <label className="text-xs">
          <span className="text-slate-body">Notes</span>
          <input value={f.notes} onChange={(e) => setF({ ...f, notes: e.target.value })} className="mt-1 w-full rounded-lg border border-line px-2.5 py-1.5" />
        </label>
      </div>

      {/* Actions (§15, §31) */}
      <div className="flex flex-wrap gap-2">
        <button onClick={saveDraft} className="rounded-lg border border-line bg-white px-4 py-2 text-xs font-semibold">Save Draft</button>
        <button onClick={() => pdf('view')} className="rounded-lg border border-line bg-white px-4 py-2 text-xs font-semibold">Preview PDF</button>
        <button onClick={() => pdf('download')} className="rounded-lg border border-line bg-white px-4 py-2 text-xs font-semibold">Download PDF</button>
        <button onClick={() => setSending(true)} className="rounded-lg bg-amber-brand px-4 py-2 text-xs font-bold text-navy-950 hover:bg-amber-deep">Send Invoice</button>
      </div>

      {sending && (
        <SendInvoiceDialog
          ctx={ctx}
          invoice={build(existing?.status ?? 'Draft')}
          onClose={() => setSending(false)}
          onSent={(inv) => {
            save(inv)
            persistPrefs()
            log({ action: 'Invoice sent', detail: `${inv.invoiceNumber} · ${a.ref} · to ${inv.recipients.map((r) => r.email).join(', ')} · by ${ctx.actorName}` })
            setSending(false)
            toast.success(`${inv.invoiceNumber} marked Sent (preview — no email leaves the app)`)
            onClose()
          }}
        />
      )}
    </div>
  )
}

/**
 * Recipient editor + templated email (article §15, §33; Nash: "he can put the
 * recipient and hit send, and our system will generate a templated email…
 * with the link to the invoice"). Uses the admin-managed `pilot_invoice`
 * template so the wording shown is the wording the backend will send.
 */
function SendInvoiceDialog({
  ctx,
  invoice,
  onClose,
  onSent,
}: {
  ctx: InvoiceContext
  invoice: PilotInvoice
  onClose: () => void
  onSent: (inv: PilotInvoice) => void
}) {
  const a = ctx.assignment
  const drv = demoDriver(a.pilotDriverId)
  const brokerAllowed = brokerCanSeePilotInvoices({ pilotInvitedByBroker: ctx.brokerInvitedPilot, brokerInvitedByPilot: ctx.pilotInvitedBroker })
  const inviter = inviterOf(a)
  const contacts = tripContactsOf(a)
  const typeFor = (email: string): RecipientType =>
    email === a.carrierDispatcher.email ? 'carrier_dispatch' : email === a.carrierDriver.email ? 'carrier_driver' : email === a.broker?.email ? 'broker' : 'custom'
  const [recipients, setRecipients] = useState<InvoiceRecipient[]>(() => {
    // Default To = the person who invited the pilot (Nash, 2026-09-12); the
    // bill-to email chosen in the builder wins if it was changed.
    const to = invoice.billToContactEmail || inviter.email
    const list: InvoiceRecipient[] = [
      { id: newId('rcp'), recipientType: typeFor(to), email: to, name: contacts.find((c) => c.email === to)?.name ?? inviter.name, sentStatus: 'pending' },
    ]
    if (drv) list.push({ id: newId('rcp'), recipientType: 'pilot_driver', email: drv.email, name: `${drv.name} (CC)`, sentStatus: 'pending' })
    if (ctx.ownerType === 'pilot_company') list.push({ id: newId('rcp'), recipientType: 'pilot_company', email: 'dispatch@abcpilotcars.com', name: 'Pilot company dispatcher (CC)', sentStatus: 'pending' })
    return list
  })
  const [custom, setCustom] = useState('')

  const template = DEFAULT_TEMPLATES.find((t) => t.key === 'pilot_invoice')!
  const data: Record<string, string> = {
    ...TEMPLATE_SAMPLE_DATA,
    dispatcher_name: a.carrierDispatcher.name,
    trip_id: a.ref,
    pickup_location: a.origin,
    delivery_location: a.destination,
    pilot_name: ctx.ownerName,
    invoice_number: invoice.invoiceNumber,
    invoice_link: `${typeof window !== 'undefined' ? window.location.origin : ''}/pd-trip-workspace/${a.ref}?invoice=${invoice.invoiceNumber}`,
    assignment_id: a.id,
    assignment_states: invoice.statesCovered.join(', ') || '—',
    assignment_permits: invoice.permitsCovered.join(', ') || '—',
    amount_due: money(invoice.calc.invoiceTotal),
    due_date: invoice.dueDate ?? (invoice.dueDateKey === 'asap' ? 'ASAP' : 'Not set'),
    payment_instructions: invoice.paymentInstructions || '—',
    preferred_payment_method: invoice.preferredPaymentMethod || '—',
    pilot_contact: ctx.ownerContact,
  }
  const subject = renderTemplate(template.subject, data)
  const body = renderTemplate(template.body, data)
  void invoiceEmailSubject

  function add(type: RecipientType, email: string, name: string) {
    if (!email) return
    setRecipients((l) => [...l, { id: newId('rcp'), recipientType: type, email, name, sentStatus: 'pending' }])
  }

  return (
    <Dialog open onOpenChange={(o) => !o && onClose()}>
      <DialogContent className="flex max-h-[90vh] max-w-2xl flex-col overflow-hidden p-0">
        <DialogHeader className="border-b px-4 py-3">
          <DialogTitle>Send {invoice.invoiceNumber}</DialogTitle>
        </DialogHeader>
        <div className="min-h-0 flex-1 space-y-4 overflow-y-auto p-4 text-xs">
          <div>
            <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-slate-body/70">Recipients — edit before sending</p>
            <div className="mt-2 space-y-1.5">
              {recipients.map((r) => (
                <div key={r.id} className="flex items-center justify-between rounded-lg border border-line bg-white px-3 py-2">
                  <span><span className="font-semibold">{r.name}</span> · {r.email} <span className="text-slate-body">· {r.recipientType.replace('_', ' ')}</span></span>
                  <button onClick={() => setRecipients((l) => l.filter((x) => x.id !== r.id))} className="text-slate-body hover:text-danger">✕</button>
                </div>
              ))}
            </div>
            <div className="mt-2 flex flex-wrap gap-1.5">
              {brokerAllowed ? (
                <button onClick={() => add('broker', ctx.brokerEmail ?? 'broker@example.com', 'Broker')} className="rounded-full bg-paper px-2.5 py-1 font-semibold ring-1 ring-inset ring-line">+ Broker</button>
              ) : (
                <span className="rounded-full bg-neutral-100 px-2.5 py-1 text-slate-body ring-1 ring-inset ring-neutral-200" title="Broker sees pilot invoices only when the broker invited the pilot or the pilot invited the broker">Broker not included</span>
              )}
              <button onClick={() => add('custom', 'admin@heavyhaul.agent', 'Internal admin')} className="rounded-full bg-paper px-2.5 py-1 font-semibold ring-1 ring-inset ring-line">+ Internal admin</button>
              <ContactEmailInput
                value={custom}
                onChange={setCustom}
                contacts={contacts.filter((c) => !recipients.some((r) => r.email === c.email) && (c.role !== 'Broker' || brokerAllowed))}
                placeholder="Add an email — click to pick a trip contact"
                onPick={(c) => { add(typeFor(c.email), c.email, c.name); setCustom('') }}
              />
              <button onClick={() => { const v = custom.trim(); if (!v) return; add(typeFor(v), v, contacts.find((c) => c.email === v)?.name ?? 'Custom billing email'); setCustom('') }} className="rounded-full bg-paper px-2.5 py-1 font-semibold ring-1 ring-inset ring-line">+ Add</button>
            </div>
          </div>
          <div>
            <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-slate-body/70">Email that will be sent <span className="normal-case font-normal">(template “Pilot Assignment Invoice”, managed by admin under Email Templates)</span></p>
            <div className="mt-2 rounded-xl border border-line bg-paper p-3">
              <p className="font-semibold">Subject: {subject}</p>
              <pre className="mt-2 whitespace-pre-wrap font-sans text-[11px] text-slate-body">{body}</pre>
              <p className="mt-2 text-[11px] text-slate-body">Attachment: {invoice.invoiceNumber}.pdf</p>
            </div>
          </div>
        </div>
        <div className="flex justify-end gap-2 border-t p-3">
          <button onClick={onClose} className="rounded-lg border border-line bg-white px-4 py-2 text-xs font-semibold">Cancel</button>
          <button
            onClick={() => {
              if (recipients.length === 0) { toast.error('Add at least one recipient'); return }
              const now = new Date().toISOString()
              onSent({ ...invoice, status: 'Sent', sentAt: now, recipients: recipients.map((r) => ({ ...r, sentStatus: 'sent', sentAt: now })) })
            }}
            className="rounded-lg bg-amber-brand px-4 py-2 text-xs font-bold text-navy-950"
          >
            Send
          </button>
        </div>
      </DialogContent>
    </Dialog>
  )
}

/**
 * Email field that drops down the trip's contacts on click (Nash, 2026-09-12:
 * "when I click on the text field, you should drop down and show me the email
 * of the dispatch, email of the driver, maybe I can add the second one").
 */
function ContactEmailInput({
  value,
  onChange,
  contacts,
  onPick,
  placeholder,
  className = '',
}: {
  value: string
  onChange: (v: string) => void
  contacts: { name: string; email: string; role: string }[]
  /** When set, picking a contact calls this instead of only filling the field. */
  onPick?: (c: { name: string; email: string; role: string }) => void
  placeholder?: string
  className?: string
}) {
  const [open, setOpen] = useState(false)
  const options = contacts.filter((c) => !value || c.email.toLowerCase().includes(value.toLowerCase()) || c.name.toLowerCase().includes(value.toLowerCase()))
  return (
    <div className={`relative ${className}`}>
      <input
        value={value}
        onChange={(e) => { onChange(e.target.value); setOpen(true) }}
        onFocus={() => setOpen(true)}
        onBlur={() => setTimeout(() => setOpen(false), 150)}
        placeholder={placeholder ?? 'Click to pick a trip contact or type an email'}
        className="w-full rounded-lg border border-line bg-white px-2.5 py-1.5 text-xs"
      />
      {open && options.length > 0 && (
        <ul className="absolute left-0 right-0 z-20 mt-1 max-h-48 overflow-y-auto rounded-lg border border-line bg-white shadow-lg">
          {options.map((c) => (
            <li key={c.email}>
              <button
                type="button"
                onMouseDown={(e) => e.preventDefault()}
                onClick={() => { if (onPick) onPick(c); else onChange(c.email); setOpen(false) }}
                className="flex w-full items-center justify-between gap-2 px-2.5 py-1.5 text-left text-xs hover:bg-paper"
              >
                <span><span className="font-semibold">{c.name}</span> <span className="text-slate-body">· {c.role}</span></span>
                <span className="font-mono text-slate-body">{c.email}</span>
              </button>
            </li>
          ))}
        </ul>
      )}
    </div>
  )
}

function Info({ k, v }: { k: string; v: string }) {
  return (
    <div>
      <p className="text-[10px] font-bold uppercase tracking-wide text-slate-body/70">{k}</p>
      <p className="font-medium">{v}</p>
    </div>
  )
}

function Num({ label, value, onChange, step = '1' }: { label: string; value: number; onChange: (e: React.ChangeEvent<HTMLInputElement>) => void; step?: string }) {
  return (
    <label className="text-xs">
      <span className="text-slate-body">{label}</span>
      <input type="number" min="0" step={step} value={value || ''} onChange={onChange} className="mt-1 w-full rounded-lg border border-line px-2.5 py-1.5" />
    </label>
  )
}

function Calc({ k, v, dim }: { k: string; v: string; dim?: boolean }) {
  return (
    <div className={`flex justify-between ${dim ? 'text-white/60' : ''}`}>
      <span>{k}</span><span className="font-semibold">{v}</span>
    </div>
  )
}
