'use client'

import { PDFDocument, StandardFonts, rgb } from 'pdf-lib'
import { money } from '@/lib/domain/invoicing'
import type { PilotExpense, PilotInvoice } from '@/lib/demo/invoicing-store'

/**
 * Invoice PDF — generated in the browser with pdf-lib (a library, not an API).
 * Nash, 2026-09-12: "when he generates an invoice, that file creates a PDF.
 * He can view it… and he can share that PDF via email."
 *
 * Layout follows article §17: number, dates, from/to, trip and assignment
 * references, states, permits, service dates, role, both calculations, the
 * selected base, overnight, expenses, custom items, total, payment
 * instructions, notes. The pilot company logo is added when the company
 * profile has one (Phase 2 — no logo field yet).
 */
export async function buildInvoicePdf(inv: PilotInvoice, expenses: PilotExpense[]): Promise<Uint8Array> {
  const doc = await PDFDocument.create()
  const bold = await doc.embedFont(StandardFonts.HelveticaBold)
  const font = await doc.embedFont(StandardFonts.Helvetica)
  let page = doc.addPage([612, 792])
  const navy = rgb(0.06, 0.11, 0.18)
  const grey = rgb(0.35, 0.4, 0.47)
  const line = rgb(0.85, 0.87, 0.9)
  let y = 750

  const text = (s: string, x: number, size = 10, f = font, color = navy) => {
    page.drawText(s, { x, y, size, font: f, color })
  }
  const row = (label: string, value: string, x = 48, w = 516) => {
    ensure(16)
    text(label, x, 9, font, grey)
    const width = font.widthOfTextAtSize(value, 10)
    page.drawText(value, { x: x + w - width, y, size: 10, font, color: navy })
    y -= 15
  }
  const heading = (s: string) => {
    ensure(28)
    y -= 6
    text(s.toUpperCase(), 48, 8, bold, grey)
    y -= 14
  }
  const rule = () => {
    page.drawLine({ start: { x: 48, y: y + 4 }, end: { x: 564, y: y + 4 }, thickness: 0.6, color: line })
    y -= 8
  }
  const ensure = (need: number) => {
    if (y - need < 60) {
      page = doc.addPage([612, 792])
      y = 750
    }
  }
  const wrap = (s: string, max = 92): string[] => {
    const words = s.split(/\s+/)
    const out: string[] = []
    let cur = ''
    for (const w of words) {
      if ((cur + ' ' + w).trim().length > max) {
        out.push(cur.trim())
        cur = w
      } else cur = `${cur} ${w}`
    }
    if (cur.trim()) out.push(cur.trim())
    return out
  }

  // Header
  text('INVOICE', 48, 22, bold)
  text(inv.invoiceNumber, 48, 10, font, grey)
  y -= 4
  page.drawText('HeavyHaul Agent', { x: 460, y: 750, size: 10, font: bold, color: navy })
  page.drawText('Pilot assignment invoice', { x: 460, y: 737, size: 8, font, color: grey })
  y -= 30
  rule()

  // From / To
  text('From', 48, 8, bold, grey)
  text('Bill to', 320, 8, bold, grey)
  y -= 14
  text(inv.ownerName, 48, 11, bold)
  text(inv.billToCompany, 320, 11, bold)
  y -= 14
  text(inv.ownerContact, 48, 9, font, grey)
  text(`${inv.billToContactName} · ${inv.billToContactEmail}`, 320, 9, font, grey)
  y -= 20

  row('Invoice date', inv.invoiceDate)
  row('Due date', inv.dueDate ?? (inv.dueDateKey === 'asap' ? 'ASAP' : 'Not set'))
  row('Status', inv.status)

  heading('Trip & assignment')
  row('Trip reference', inv.tripRef)
  row('Assignment reference', inv.assignmentId)
  row('States covered', inv.statesCovered.join(', ') || '—')
  row('Permits covered', inv.permitsCovered.join(', ') || '—')
  row('Service dates', inv.serviceDates || '—')
  row('Pilot role', inv.pilotRole)
  row('Pilot driver', inv.pilotDriverName || '—')
  row('Vehicle / unit', inv.vehicleUsed || '—')
  row('Truck reference', inv.truckReference || '—')

  heading('Base charge — both calculated, greater one used')
  row(`Mileage: ${inv.miles} mi × ${money(inv.ratePerMile)}`, money(inv.calc.mileageTotal))
  row(`Daily: ${inv.days} day(s) × ${money(inv.dailyRate)}`, money(inv.calc.dailyTotal))
  ensure(16)
  text(inv.calc.explanation, 48, 9, font, grey)
  y -= 15
  row(`Selected base (${inv.calc.selectedBaseType})`, money(inv.calc.selectedBaseTotal))
  row(`Overnight: ${inv.overnights} × ${money(inv.overnightFee)}`, money(inv.calc.overnightTotal))

  const included = expenses.filter((e) => inv.expenseIds.includes(e.id))
  if (included.length > 0) {
    heading('Expenses')
    for (const e of included) row(`${e.category} · ${e.description || e.expenseDate}`, money(e.amount))
    row('Expense total', money(inv.calc.expenseTotal))
  }
  if (inv.customItems.length > 0) {
    heading('Custom line items')
    for (const c of inv.customItems) row(c.description || 'Item', money(c.amount))
    row('Custom total', money(inv.calc.customTotal))
  }

  y -= 6
  rule()
  ensure(24)
  text('TOTAL AMOUNT DUE', 48, 11, bold)
  const total = money(inv.calc.invoiceTotal)
  page.drawText(total, { x: 564 - bold.widthOfTextAtSize(total, 14), y: y - 2, size: 14, font: bold, color: navy })
  y -= 26

  if (inv.paymentInstructions || inv.preferredPaymentMethod) {
    heading('Payment instructions')
    for (const l of wrap(inv.paymentInstructions)) {
      ensure(14)
      text(l, 48, 9)
      y -= 13
    }
    if (inv.preferredPaymentMethod) {
      ensure(14)
      text(`Preferred payment method: ${inv.preferredPaymentMethod}`, 48, 9, font, grey)
      y -= 13
    }
  }
  if (inv.notes) {
    heading('Notes')
    for (const l of wrap(inv.notes)) {
      ensure(14)
      text(l, 48, 9)
      y -= 13
    }
  }

  return doc.save()
}

/**
 * Pilot paperwork PDF for the carrier's "My Pilot" tab (Nash, 2026-09-13:
 * "they all have a PDF icon where they can click"). The replica has no
 * uploaded files, so the PDF carries the document's record — owner, status,
 * dates, trip — until the documents backend serves the real upload.
 */
export async function buildPaperworkPdf(input: {
  label: string
  owner: string
  ownerKind: string
  status: string
  expirationDate?: string
  uploadedAt?: string
  tripRef: string
}): Promise<Uint8Array> {
  const doc = await PDFDocument.create()
  const page = doc.addPage([612, 792])
  const bold = await doc.embedFont(StandardFonts.HelveticaBold)
  const font = await doc.embedFont(StandardFonts.Helvetica)
  let y = 740
  page.drawText(input.label, { x: 48, y, size: 20, font: bold, color: rgb(0.06, 0.11, 0.18) })
  y -= 26
  page.drawText(`${input.owner} - ${input.ownerKind}`, { x: 48, y, size: 12, font })
  y -= 30
  const rows: Array<[string, string]> = [
    ['Status', input.status],
    ['Expiration date', input.expirationDate ?? 'Does not expire'],
    ['Uploaded', input.uploadedAt ?? '-'],
    ['Trip', input.tripRef],
  ]
  for (const [k, v] of rows) {
    page.drawText(`${k}:`, { x: 48, y, size: 11, font: bold })
    page.drawText(v, { x: 180, y, size: 11, font })
    y -= 18
  }
  y -= 20
  page.drawText('Design preview - the uploaded file is served here once the documents backend exists.', { x: 48, y, size: 9, font, color: rgb(0.45, 0.45, 0.45) })
  return doc.save()
}

/** Open the PDF in a new tab (view) or trigger a download. */
export function openPdf(bytes: Uint8Array, fileName: string, mode: 'view' | 'download') {
  const blob = new Blob([bytes as BlobPart], { type: 'application/pdf' })
  const url = URL.createObjectURL(blob)
  if (mode === 'view') {
    window.open(url, '_blank', 'noopener')
  } else {
    const a = document.createElement('a')
    a.href = url
    a.download = fileName
    a.click()
  }
  setTimeout(() => URL.revokeObjectURL(url), 60_000)
}
