'use client'

import { useEffect, useRef, useState, useSyncExternalStore } from 'react'
import Link from 'next/link'
import { toast } from 'sonner'
import { stateName } from '@/lib/domain/states'
import { PilotPreviewBanner } from '@/components/app/pilot-preview-banner'
import { StateNotesDialog } from '@/components/app/state-notes-dialog'
import { RouteStatusLine } from '@/components/app/pilot-tools/route-status-line'
import { ChatPanel } from '@/components/app/chat-panel'
import { PilotToolsPanel } from '@/components/app/pilot-tools/pilot-tools-panel'
import { demoChatPermits, demoPilotAnswer, demoPilotChat, demoTripFor } from '@/lib/demo/pilot-agent'
import {
  computeReadiness,
  documentSlotsFor,
  onboardingTasks,
  PILOT_CAPABILITIES,
  VEHICLE_PHOTO_SIDES,
  type CapabilityStatus,
  type PilotCapability,
  type PilotDocumentStatus,
  type VehiclePhotoSide,
} from '@/lib/domain/pilot'
import { DEFAULT_TEMPLATES, renderTemplate, TEMPLATE_SAMPLE_DATA } from '@/lib/email-templates'
import {
  DEMO_PILOT_ASSIGNMENTS,
  DEMO_PILOT_COMPANY,
  DEMO_PILOT_DRIVERS,
  DEMO_PILOT_DRIVER_ME_ID,
  DEMO_TODAY,
  demoDriver,
  demoVehicle,
  scopeSummary,
  type DemoPilotAssignment,
  type DemoPilotDocument,
  type DemoPilotDriver,
  type DemoPilotVehicle,
  type DemoUnitInfo,
} from '@/lib/demo/pilot'
import { PILOT_PREVIEW_SIGNUP_KEY, type PilotPreviewSignup } from '@/app/(auth)/signup/pilot/pilot-signup-wizard'

/**
 * Pilot Driver dashboard — Phase 1 design replica.
 *
 * Article §5: "The Pilot Driver dashboard should look and function very
 * similar to the Carrier Driver dashboard." Nash, 2026-09-12: "pilot driver
 * interface, it's the same as the carrier driver with an extra tab or
 * something." So this keeps driver-view.tsx's phone frame, navy header,
 * swipeable pane track and bottom nav, and adds ONE pane — Profile & Docs.
 *
 * Onboarding after sign-in (Nash, same day): "after I logged in, if I never
 * completed those steps… on my assignments, you could show me, like, the
 * step four, what I need to do, step five… unfinished tasks. Now if I have a
 * trip assigned to me and any of these steps are not done, when I click on
 * it… I could probably view them, but also inside here is gonna tell me that
 * I need to complete those steps, somewhere on top, above the states that
 * are shared with me." `fresh` renders that just-signed-up state.
 */

/**
 * Nash, 2026-09-12 (fourth round): "my vehicle should be in the profile docs.
 * It should be merged both in one… one about me as the pilot car that has the
 * profile, docs, my vehicle and everything else. And then the carrier info
 * about this trip: who is the carrier driver, the truck, the trailer,
 * commodity, overall dimensions, maybe the carrier dispatch information also…
 * that will be used for creating invoices and record keeping."
 */
const PANES = ['My Assignments', 'Active Assignment', 'Agent', 'Carrier Info', 'My Pilot Car'] as const
const PANE_ICONS = ['🗂️', '🚨', '💬', '🚛', '🪪'] as const
const ME_PANE = 4

const BLANK_VEHICLE = { unitNumber: '', year: '', make: '', model: '', color: '', plate: '', plateState: '' }

export function PilotDriverView({ fresh = false }: { fresh?: boolean }) {
  const demoMe = demoDriver(DEMO_PILOT_DRIVER_ME_ID)!

  // Fresh account: the name/company typed in the signup replica, nothing
  // uploaded yet, no vehicle, no capabilities. Otherwise the established demo
  // driver. Read through useSyncExternalStore so the server render (no
  // storage) and the client agree without a setState-in-effect.
  const signupRaw = useSyncExternalStore(subscribeNoop, readSignupSnapshot, () => null)
  const signup = fresh && signupRaw ? parseSignup(signupRaw) : null

  const me = fresh
    ? {
        ...demoMe,
        name: signup?.name || 'New pilot driver',
        email: signup?.email || 'you@example.com',
        phone: signup?.phone || '(000) 000-0000',
        homeBase: '—',
        yearsExperience: 0,
        statesServed: [],
        serviceRadius: '—',
        linkedCompanies: [],
      }
    : demoMe
  /** Company that handles the driver's documents — approved relationship only. */
  const companyForDocs = fresh ? null : me.linkedCompanies.find((c) => c !== 'Independent direct work') ?? null
  const pendingCompany = fresh ? signup?.company ?? null : null

  const [docs, setDocs] = useState<DemoPilotDocument[]>(fresh ? [] : demoMe.documents)
  const [caps, setCaps] = useState<Partial<Record<PilotCapability, CapabilityStatus>>>(fresh ? {} : demoMe.capabilities)
  const [vehicle, setVehicle] = useState<DemoPilotVehicle | null>(fresh ? null : demoVehicle(demoMe.vehicleIds[0]) ?? null)
  const [vehicleForm, setVehicleForm] = useState(BLANK_VEHICLE)

  const mine = DEMO_PILOT_ASSIGNMENTS.filter((a) => a.pilotDriverId === me.id)
  const activeList = mine.filter((a) => a.status !== 'completed')
  const previous = mine.filter((a) => a.status === 'completed')
  const [focusId, setFocusId] = useState<string>(activeList[0]?.id ?? mine[0]?.id)
  const trip = mine.find((a) => a.id === focusId) ?? activeList[0] ?? null

  const trackRef = useRef<HTMLDivElement>(null)
  const [pane, setPane] = useState(0)
  // "View state notes" popup (Nash, 2026-09-12) — same notes the carrier driver sees.
  const [notesState, setNotesState] = useState<string | null>(null)
  // Permit-scoped agent chat, driven by the state sections' "Ask your agent" —
  // same as the carrier driver (Task 7).
  const [scopedPermitId, setScopedPermitId] = useState<string | null>(null)

  const [trackHeight, setTrackHeight] = useState<number | undefined>(undefined)
  useEffect(() => {
    const el = trackRef.current
    if (!el || typeof ResizeObserver === 'undefined') return
    const measure = () => {
      const current = el.children[pane] as HTMLElement | undefined
      if (current) setTrackHeight(current.offsetHeight)
    }
    const observer = new ResizeObserver(measure)
    for (const child of Array.from(el.children)) observer.observe(child)
    measure()
    return () => observer.disconnect()
  }, [pane])

  function goTo(i: number) {
    const el = trackRef.current
    if (!el) return
    el.scrollTo({ left: i * el.clientWidth, behavior: 'smooth' })
  }
  function onScroll() {
    const el = trackRef.current
    if (!el) return
    const i = Math.round(el.scrollLeft / el.clientWidth)
    if (i !== pane) setPane(i)
  }

  const docMap = Object.fromEntries(docs.map((d) => [d.key, d.status])) as Record<string, PilotDocumentStatus>
  const readiness = computeReadiness({
    accountType: 'pilot_driver',
    name: me.name,
    phone: me.phone,
    emailVerified: true,
    documents: docMap,
    createdAt: fresh ? DEMO_TODAY : '2026-09-05',
    today: DEMO_TODAY,
    adminVerified: !fresh && demoMe.readiness === 'Verified Pilot',
  })
  const tasks = onboardingTasks({
    accountType: 'pilot_driver',
    companyName: companyForDocs,
    documents: docMap,
    vehiclePhotos: vehicle ? vehicle.photos.length : null,
    capabilityCount: Object.keys(caps).length,
  })
  const unfinished = tasks.filter((t) => !t.done)

  function uploadDoc(key: string) {
    setDocs((list) => {
      const rest = list.filter((d) => d.key !== key)
      return [...rest, { key, status: 'Uploaded', uploadedAt: DEMO_TODAY }]
    })
    toast.success('Preview: document marked uploaded (file not stored)')
  }
  function addPhoto(side: VehiclePhotoSide) {
    setVehicle((v) => (v && !v.photos.includes(side) ? { ...v, photos: [...v.photos, side] } : v))
    toast.success(`Preview: ${side} photo uploaded`)
  }
  // Every setup step (documents, vehicle, capabilities) now lives on the one
  // "My Pilot Car" pane, so all tasks jump there.
  function goToTask() {
    goTo(ME_PANE)
  }

  const shared = trip ? trip.permits.filter((p) => p.shared) : []
  const states = [...new Set(shared.map((p) => p.state))]
  const isValidToday = (p: { effective: string; expires: string }) => p.effective <= DEMO_TODAY && p.expires >= DEMO_TODAY

  const statBox = (k: string, v: string, tone: 'ok' | 'warn' | 'muted') => (
    <div key={k} className="rounded-lg bg-white/5 px-1 py-2 ring-1 ring-white/10">
      <p className="text-navy-100/70">{k}</p>
      <p className={`mt-0.5 text-xs font-bold ${tone === 'ok' ? 'text-green-300' : tone === 'warn' ? 'text-amber-brand' : 'text-navy-100'}`}>{v}</p>
    </div>
  )

  return (
    <main className="py-2 sm:py-6">
      <div className="mx-auto mb-4 max-w-3xl px-4">
        <PilotPreviewBanner screen={fresh ? 'Pilot Driver interface — just signed up, onboarding unfinished' : 'Pilot Driver interface'} />
      </div>
      <div className="mx-auto max-w-[420px] overflow-hidden bg-paper sm:rounded-[2rem] sm:shadow-2xl sm:ring-8 sm:ring-navy-900">
        <header className="bg-navy-900 px-5 pb-5 pt-6 text-white">
          <p className="text-[11px] font-bold uppercase tracking-[0.14em] text-amber-brand">
            {trip ? (trip.status === 'completed' ? 'Previous Assignment' : 'Current Assignment') : 'Pilot driver'}
            {trip ? ` · ${trip.position}` : ''}
          </p>
          <h1 className="mt-1 text-xl font-extrabold tracking-tight">
            {trip ? `${trip.origin} → ${trip.destination}` : me.name}
          </h1>
          <p className="mt-0.5 text-xs text-navy-100">
            {trip ? `${trip.commodity} · ${trip.carrier}` : 'No active assignment'}
          </p>
          {trip && (
            <div className="mt-4 grid grid-cols-4 gap-2 text-center text-[10px] font-semibold">
              {statBox('Shared', shared.length > 0 ? `${shared.length} ✓` : 'None', shared.length > 0 ? 'ok' : 'warn')}
              {statBox('Valid today', `${shared.filter(isValidToday).length}/${shared.length}`, shared.some(isValidToday) ? 'ok' : 'warn')}
              {statBox('States', states.join(' ') || '—', 'muted')}
              {statBox('Setup', unfinished.length === 0 ? 'Complete' : `${unfinished.length} to do`, unfinished.length === 0 ? 'ok' : 'warn')}
            </div>
          )}
        </header>

        <div
          ref={trackRef}
          onScroll={onScroll}
          style={trackHeight ? { height: trackHeight } : undefined}
          className="flex snap-x snap-mandatory overflow-x-auto overflow-y-hidden scroll-smooth [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
        >
          {/* Pane 1: My Assignments — unfinished setup first, then the list */}
          <section className="w-full shrink-0 snap-center space-y-3 px-4 py-5 pb-8">
            {fresh && (
              <Card>
                <p className="text-sm font-bold">Welcome, {me.name.split(' ')[0]} — you&apos;re in.</p>
                <p className="mt-1 text-xs text-slate-body">Email validated. {pendingCompany ? `Your request to connect with ${pendingCompany} is pending their approval.` : 'You signed up as an independent pilot driver.'}</p>
              </Card>
            )}
            {unfinished.length > 0 && (
              <OnboardingTasksCard tasks={tasks} pendingCompany={pendingCompany} onGo={() => goToTask()} />
            )}
            <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-slate-body/70">Active</p>
            {activeList.length === 0 && (
              <div className="rounded-2xl border border-dashed border-line bg-white p-8 text-center text-xs text-slate-body">
                No active assignments. When a carrier, broker or your pilot company shares a trip with you, it appears here.
              </div>
            )}
            {activeList.map((a) => (
              <AssignmentCard key={a.id} a={a} highlighted={a.id === trip?.id} onOpen={() => { setFocusId(a.id); goTo(1) }} />
            ))}
            {previous.length > 0 && (
              <>
                <p className="pt-2 text-[10px] font-bold uppercase tracking-[0.14em] text-slate-body/70">History</p>
                {previous.map((a) => (
                  <AssignmentCard key={a.id} a={a} highlighted={a.id === trip?.id} onOpen={() => { setFocusId(a.id); goTo(1) }} />
                ))}
              </>
            )}
          </section>

          {/* Pane 2: Active Assignment — reminder above the shared states, permits still viewable */}
          <section className="w-full shrink-0 snap-center space-y-4 px-4 py-5 pb-8">
            {!trip ? (
              <Card><p className="text-xs text-slate-body">Pick an assignment from My Assignments.</p></Card>
            ) : (
              <>
                {unfinished.length > 0 && (
                  <Card tone="warn">
                    <CardHead label="Finish your setup" />
                    <p className="mt-1 text-xs text-slate-body">You can view what was shared with you, but these steps are still open:</p>
                    <ul className="mt-1.5 space-y-1 text-xs">
                      {unfinished.map((t) => (
                        <li key={t.step} className="flex items-center justify-between gap-2">
                          <span><span className="font-semibold">Step {t.step} · {t.title}</span> — {t.missing.join(', ')}</span>
                          <button onClick={() => goToTask()} className="shrink-0 rounded-lg bg-navy-900 px-2 py-1 text-[10px] font-bold text-white">Do it</button>
                        </li>
                      ))}
                    </ul>
                  </Card>
                )}

                <Card>
                  <CardHead label="Shared with you" />
                  <p className="mt-1 text-sm font-semibold">{scopeSummary(trip.scopes)}</p>
                  <p className="mt-1 text-xs text-slate-body">
                    {trip.scopes[0]?.type === 'state'
                      ? 'State access — every permit for this state, including ones the carrier uploads later, shows up here automatically.'
                      : trip.scopes[0]?.type === 'permit'
                        ? 'Permit access — only this permit. New permits are not shared unless the carrier adds them.'
                        : 'Full trip access — the whole operational trip. The rate confirmation is never included.'}
                  </p>
                  <p className="mt-2 text-xs">
                    Status: <span className="font-semibold capitalize">{trip.status}</span>
                    {trip.carrierApprovalRequired && !trip.driverApprovedByCarrier && <span className="ml-2 font-semibold text-warn">· awaiting carrier approval of you as the driver</span>}
                  </p>
                  {trip.status === 'invited' && (
                    <button onClick={() => toast.success('Preview: assignment accepted')} className="mt-3 w-full rounded-lg bg-amber-brand py-2 text-xs font-bold text-navy-950">Accept assignment</button>
                  )}
                  <Link href={`/pc-trip-workspace/${trip.ref}`} className="mt-2 block w-full rounded-lg border border-line bg-white py-2 text-center text-xs font-semibold text-slate-body hover:text-ink">Open trip workspace →</Link>
                </Card>

                {shared.length === 0 && (
                  <Card>
                    <CardHead label="No permits shared yet" />
                    <p className="mt-1 text-xs text-slate-body">The carrier chose “decide later”. You will see permits here as soon as they share states, permits or the full trip.</p>
                  </Card>
                )}

                {states.map((s) => {
                  const permits = shared.filter((p) => p.state === s)
                  return (
                    <Card key={s}>
                      <CardHead label={`${stateName(s) || s} (${s})`} />
                      {permits.map((p) => (
                        <div key={p.id} className="mt-3 space-y-2 border-t border-line pt-3 first:mt-2 first:border-0 first:pt-0">
                          <div className="flex items-center justify-between text-xs">
                            <span className="font-semibold">{p.permitNumber}</span>
                            <span className={`rounded-full px-2 py-0.5 text-[10px] font-bold ring-1 ring-inset ${isValidToday(p) ? 'bg-ok-bg text-ok ring-green-200' : 'bg-warn-bg text-warn ring-amber-200'}`}>
                              {isValidToday(p) ? 'Valid today' : `Valid ${p.effective} → ${p.expires}`}
                            </span>
                          </div>
                          <Row k="Curfew" v={p.curfew} />
                          <Row k="Pilot cars / escorts" v={p.escort} />
                          {/* View permit · view provisions · view state notes — the same
                              three links the carrier driver has (Nash, 2026-09-12). */}
                          <div className="flex flex-wrap items-center gap-x-3 gap-y-1.5 border-t border-line/70 pt-2 text-[11px]">
                            <button onClick={() => toast.success('Preview: permit PDF would open here')} className="font-bold text-info hover:underline">View permit</button>
                            <button onClick={() => toast.info('Provisions come from Synchron Permits — available once the connection is live.')} className="font-bold text-slate-body/60 hover:text-slate-body">View provisions</button>
                            <button onClick={() => setNotesState(p.state)} className="font-bold text-info hover:underline">View state notes</button>
                            <button onClick={() => { setScopedPermitId(p.id); goTo(2) }} className="ml-auto rounded-lg bg-navy-900 px-2.5 py-1.5 font-bold text-white">💬 Ask your agent</button>
                          </div>
                          {/* Nash, 2026-09-13: "the route is ready, I should be able
                              to see the GPX file, the Hummer, and the Google Maps
                              links" — the delivered formats, open by default. */}
                          <div className="text-[11px]">
                            <RouteStatusLine route={p.route ?? null} />
                          </div>
                        </div>
                      ))}
                    </Card>
                  )
                })}

                {trip.permits.some((p) => !p.shared) && (
                  <Card>
                    <CardHead label="Not shared with you" />
                    <p className="mt-1 text-xs text-slate-body">
                      {trip.permits.filter((p) => !p.shared).map((p) => p.state).join(', ')} — {trip.permits.filter((p) => !p.shared).length} permit(s) on this trip are outside your access. Ask the carrier dispatcher if you need them.
                    </p>
                  </Card>
                )}

                {trip.scopes.some((s) => s.type === 'full_trip') && (
                  <Card>
                    <CardHead label="Trip overview" />
                    <Row k="Carrier dispatcher" v={`${trip.carrierDispatcher.name} · ${trip.carrierDispatcher.phone}`} />
                    <Row k="Carrier driver" v={`${trip.carrierDriver.name} · ${trip.carrierDriver.phone}`} />
                    <Row k="Truck / trailer" v={`${trip.truck} · ${trip.trailer}`} />
                    <Row k="Overall dimensions" v={trip.overall} />
                    <Row k="Weight" v={trip.weight} />
                  </Card>
                )}

                <Card tone="warn">
                  <CardHead label="Pilot assignment chat" />
                  <p className="mt-1 text-xs text-slate-body">Carrier dispatcher, carrier driver, your pilot company and you. The broker/carrier trip chat is separate.</p>
                  <div className="mt-2 space-y-1.5 text-xs">
                    <p><span className="font-semibold">{trip.carrierDispatcher.name}:</span> Meet at the Pilot truck stop, exit 110, 6:30 AM.</p>
                    <p><span className="font-semibold">You:</span> Copy. PC-01 lead, high pole on PC-02.</p>
                  </div>
                </Card>

                {/* Nash, 2026-09-13: "Add pilot dispatch" lists my active
                    dispatchers or takes an email; "Add pilot" lists pilots linked
                    through my companies or takes an email. Both get exactly my
                    access. Invitees get the admin-managed template emails
                    (Pilot Dispatch Invited to Trip / Additional Pilot Invited to
                    Trip) — not sent in this phase. */}
                <AddToTripCard kind="dispatch" trip={trip} me={me} />
                <AddToTripCard kind="pilot" trip={trip} me={me} />

                <p className="px-1 text-[11px] text-slate-body">Hidden from pilot accounts on every assignment: rate confirmation, pricing, billing, private notes, unshared permits and states.</p>
              </>
            )}
          </section>

          {/* Pane 3: Agent — the carrier driver's ChatPanel, reused (Nash,
              2026-09-12: "the same ability… voice first… change the languages
              and all the same tools"). Offline replica: the state selector
              offers only the states shared with this pilot ("Whole trip" only
              on full-trip access), answers stay inside that scope, and the
              share-my-questions choice works the same way. */}
          <section className="w-full shrink-0 snap-center px-4 py-5 pb-8">
            <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-slate-body/70">
              Ask your agent{trip ? ` — ${scopeSummary(trip.scopes)}` : ''}
            </p>
            <p className="mt-1 text-xs text-slate-body">
              {trip && trip.scopes.some((s) => s.type === 'full_trip')
                ? 'Full trip access — ask about the whole trip or one state.'
                : 'You can ask about the states shared with you only; the whole-trip option is not available.'}
            </p>
            {trip ? (
              <div className="mt-3">
                <ChatPanel
                  key={trip.id}
                  trip={demoTripFor(trip)}
                  chat={demoPilotChat(trip, me.id, me.name)}
                  permits={demoChatPermits(trip)}
                  myRole="pilot"
                  myUserId={me.id}
                  participants={[]}
                  scopedPermit={demoChatPermits(trip).find((p) => p.id === scopedPermitId) ?? null}
                  onExitScope={() => setScopedPermitId(null)}
                  suggestions={['Can I move right now?', 'Do I need escorts here?', 'What are my curfews?', 'Is my permit valid today?']}
                  shareChat
                  compact
                  offline={{ answer: demoPilotAnswer(trip), wholeTrip: trip.scopes.some((s) => s.type === 'full_trip') }}
                />
              </div>
            ) : (
              <Card><p className="mt-3 text-xs text-slate-body">Pick an assignment from My Assignments.</p></Card>
            )}
          </section>

          {/* Pane 4: Carrier Info — the other parties on this trip, kept for
              record keeping and future invoicing. Shown on every assignment;
              permit scope limits permits, not who the pilot is working with. */}
          <section className="w-full shrink-0 snap-center space-y-4 px-4 py-5 pb-8">
            <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-slate-body/70">Carrier info — this trip</p>
            {!trip ? (
              <Card><p className="text-xs text-slate-body">Pick an assignment from My Assignments.</p></Card>
            ) : (
              <>
                <Card>
                  <CardHead label="Carrier" />
                  <p className="mt-1 text-sm font-bold">{trip.carrier}</p>
                  <p className="text-xs text-slate-body">Assignment {trip.ref} · {trip.origin} → {trip.destination}</p>
                </Card>
                <ContactCard label="Carrier dispatcher" person={trip.carrierDispatcher} />
                <ContactCard label="Carrier driver" person={trip.carrierDriver} />
                <UnitCard label="Truck" summary={trip.truck} unit={trip.truckInfo} />
                <UnitCard label="Trailer" summary={trip.trailer} unit={trip.trailerInfo} />
                <Card>
                  <CardHead label="Load" />
                  <Row k="Commodity" v={trip.commodity} />
                  <Row k="Overall dimensions" v={trip.overall} />
                  <Row k="Weight" v={trip.weight} />
                </Card>
                <p className="px-1 text-[11px] text-slate-body">Kept with the assignment in your history — who the driver and dispatch were, which truck and trailer, what commodity and overall dimensions — for your records and invoicing.</p>
              </>
            )}
          </section>

          {/* Pane 5: My Pilot Car — everything about me: profile, documents
              (step 4), my vehicle (step 5), capabilities (step 6), companies */}
          <section className="w-full shrink-0 snap-center space-y-4 px-4 py-5 pb-8">
            <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-slate-body/70">My Pilot Car — profile</p>
            <Card>
              <p className="font-bold">{me.name}</p>
              <p className="text-xs text-slate-body">{me.phone} · {me.email} <span className="text-ok">✓ validated</span></p>
              <p className="mt-1 text-xs text-slate-body">Home base {me.homeBase} · {me.yearsExperience} yrs · radius {me.serviceRadius}</p>
              <p className="text-xs text-slate-body">States served: <span className="font-mono text-ink">{me.statesServed.join(' ') || '—'}</span></p>
              <p className="mt-2"><span className={`rounded-full px-2 py-0.5 text-[10px] font-bold ring-1 ring-inset ${readiness === 'Verified Pilot' || readiness === 'Ready for Assignment' ? 'bg-ok-bg text-ok ring-green-200' : 'bg-warn-bg text-warn ring-amber-200'}`}>{readiness}</span></p>
            </Card>

            <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-slate-body/70">My Vehicle · step 5</p>
            {vehicle ? (
              <Card>
                <div className="flex items-start justify-between">
                  <div>
                    <p className="font-bold">{vehicle.unitNumber} · {vehicle.year} {vehicle.make} {vehicle.model}</p>
                    <p className="text-xs text-slate-body">{vehicle.color} · Plate {vehicle.plate} ({vehicle.plateState}){vehicle.equipmentType ? ` · ${vehicle.equipmentType}` : ''}</p>
                    <p className="text-xs text-slate-body">Owner: {vehicle.ownerLabel}</p>
                  </div>
                  <span className="rounded-full bg-ok-bg px-2 py-0.5 text-[10px] font-bold text-ok ring-1 ring-inset ring-green-200">{vehicle.status}</span>
                </div>
                <div className="mt-3 grid grid-cols-4 gap-2">
                  {VEHICLE_PHOTO_SIDES.map((side) => {
                    const has = vehicle.photos.includes(side)
                    return (
                      <button key={side} onClick={() => !has && addPhoto(side)} className={`aspect-[4/3] rounded-lg text-center text-[10px] font-semibold ring-1 ring-inset ${has ? 'bg-navy-100 text-navy-900 ring-navy-100' : 'bg-white text-slate-body ring-dashed ring-line hover:text-ink'}`}>
                        {has ? '📷 ' : '+ '}{side}
                      </button>
                    )
                  })}
                </div>
                <p className="mt-2 text-[11px] text-slate-body">
                  {vehicle.photos.length < 4 ? `${4 - vehicle.photos.length} of 4 required photos missing. ` : 'All four photos in. '}
                  Carriers and brokers see these when you are assigned.
                </p>
              </Card>
            ) : (
              <Card>
                <p className="text-sm font-bold">Add your vehicle</p>
                <p className="mt-1 text-xs text-slate-body">Only you manage your own vehicle. Four photos are required after the details.</p>
                <div className="mt-3 grid grid-cols-2 gap-2">
                  {([
                    ['unitNumber', 'Nickname / unit #'], ['year', 'Year'], ['make', 'Make'], ['model', 'Model'], ['color', 'Color'], ['plate', 'License plate'], ['plateState', 'Plate state'],
                  ] as const).map(([k, label]) => (
                    <input key={k} value={vehicleForm[k]} onChange={(e) => setVehicleForm({ ...vehicleForm, [k]: e.target.value })} placeholder={label} className="rounded-lg border border-line px-2.5 py-1.5 text-xs" />
                  ))}
                </div>
                <button
                  onClick={() => {
                    if (!vehicleForm.unitNumber || !vehicleForm.make || !vehicleForm.model || !vehicleForm.plate) { toast.error('Unit number, make, model and plate are required'); return }
                    setVehicle({ id: 'veh-new', ...vehicleForm, equipmentType: '', ownerType: 'pilot_driver', ownerLabel: `${me.name} (own vehicle)`, assignedDriverId: me.id, status: 'active', photos: [] })
                    toast.success('Preview: vehicle added — now the four photos')
                  }}
                  className="mt-3 w-full rounded-lg bg-navy-900 py-2 text-xs font-bold text-white"
                >
                  Save vehicle
                </button>
              </Card>
            )}

            <Card>
              <CardHead label="Documents · step 4" />
              <p className="mt-1 text-[11px] text-slate-body">
                {companyForDocs
                  ? `You or ${companyForDocs} can upload these. `
                  : pendingCompany
                    ? `Once ${pendingCompany} approves your request they can upload these for you; until then, you can. `
                    : 'You are independent — only you can upload these. '}
                Visible to your approved pilot companies, the carrier on your assignments and HeavyHaul Agent admins. Brokers cannot see them, and a carrier dispatcher can never upload to your profile.
              </p>
              <div className="mt-2 space-y-1.5 text-xs">
                {documentSlotsFor('pilot_driver').map((s) => {
                  const doc = docs.find((d) => d.key === s.key)
                  const st: PilotDocumentStatus = doc?.status ?? 'Not Uploaded'
                  return (
                    <div key={s.key} className="flex items-center justify-between gap-2">
                      <span>{s.label}{s.required && <span className="ml-1 text-[9px] font-bold uppercase text-danger">req</span>}</span>
                      <span className="flex items-center gap-1.5">
                        {doc?.expirationDate && <span className="text-slate-body">exp {doc.expirationDate}</span>}
                        {st === 'Not Uploaded' ? (
                          <button onClick={() => uploadDoc(s.key)} className="rounded-lg border border-line bg-white px-2 py-0.5 text-[10px] font-semibold hover:text-ink">Upload</button>
                        ) : (
                          <span className={`rounded-full px-2 py-0.5 text-[10px] font-semibold ring-1 ring-inset ${st === 'Approved' ? 'bg-ok-bg text-ok ring-green-200' : st === 'Expired' || st === 'Rejected' ? 'bg-danger-bg text-danger ring-red-200' : 'bg-info-bg text-info ring-blue-200'}`}>{st}</span>
                        )}
                      </span>
                    </div>
                  )
                })}
              </div>
            </Card>

            <Card>
              <CardHead label="Capabilities · step 6" />
              <p className="mt-1 text-[11px] text-slate-body">Tap what you can do. Each starts as self-declared.</p>
              <div className="mt-2 flex flex-wrap gap-1 text-[11px]">
                {PILOT_CAPABILITIES.map((c) => {
                  const st = caps[c]
                  return (
                    <button
                      key={c}
                      onClick={() => {
                        setCaps((prev) => {
                          const next = { ...prev }
                          if (next[c]) delete next[c]
                          else next[c] = 'Self-declared'
                          return next
                        })
                      }}
                      className={`rounded-full px-2 py-0.5 ring-1 ring-inset ${st ? 'bg-navy-100 text-navy-900 ring-navy-100' : 'bg-white text-slate-body/60 ring-line hover:text-ink'}`}
                    >
                      {c}{st ? ` · ${st}` : ''}
                    </button>
                  )
                })}
              </div>
            </Card>

            {/* Invoices & expenses for the current assignment (Pro Tools article;
                Nash: "for the pilot driver… My pilot car information is gonna
                have the ability for those actions"). Owner rule: a driver under
                an approved pilot company sees the company's records; an
                independent driver owns and creates them. */}
            {trip && (
              <Card>
                <CardHead label={`Invoices & expenses — ${trip.ref}`} />
                <div className="mt-2">
                  <PilotToolsPanel assignment={trip} actor="pilot_driver" independentDriver={fresh ? !pendingCompany : !companyForDocs} compact />
                </div>
              </Card>
            )}

            <Card>
              <CardHead label="Pilot companies" />
              <div className="mt-2 space-y-1.5 text-xs">
                {me.linkedCompanies.map((c) => (
                  <div key={c} className="flex items-center justify-between"><span>{c}</span><span className="rounded-full bg-ok-bg px-2 py-0.5 text-[10px] font-bold text-ok ring-1 ring-inset ring-green-200">Approved</span></div>
                ))}
                {pendingCompany && (
                  <div className="flex items-center justify-between"><span>{pendingCompany}</span><span className="rounded-full bg-warn-bg px-2 py-0.5 text-[10px] font-bold text-warn ring-1 ring-inset ring-amber-200">Pending · you asked</span></div>
                )}
                {!fresh && (
                  <div className="flex items-center justify-between"><span>Elite Escort Services</span><span className="rounded-full bg-warn-bg px-2 py-0.5 text-[10px] font-bold text-warn ring-1 ring-inset ring-amber-200">Pending · they asked</span></div>
                )}
                {fresh && !pendingCompany && <p className="text-slate-body">Independent — no company linked.</p>}
              </div>
              {!fresh && (
                <div className="mt-2 flex gap-1.5">
                  <button onClick={() => toast.success('Preview: relationship approved')} className="flex-1 rounded-lg bg-navy-900 py-1.5 text-[11px] font-bold text-white">Approve</button>
                  <button onClick={() => toast.success('Preview: relationship denied')} className="flex-1 rounded-lg border border-line bg-white py-1.5 text-[11px] font-semibold">Deny</button>
                  <button onClick={() => toast.success('Preview: asked for more information')} className="flex-1 rounded-lg border border-line bg-white py-1.5 text-[11px] font-semibold">More info</button>
                </div>
              )}
              <button onClick={() => toast.success('Preview: connection request sent to the company')} className="mt-2 w-full rounded-lg border border-dashed border-line bg-white py-1.5 text-[11px] font-semibold text-slate-body">+ Request to connect with a pilot company</button>
            </Card>
          </section>
        </div>

        <StateNotesDialog code={notesState} onClose={() => setNotesState(null)} />

        <nav className="sticky bottom-0 grid grid-cols-5 border-t border-line bg-white py-2 text-center text-[10px] font-semibold text-slate-body">
          {PANES.map((label, i) => (
            <button key={label} onClick={() => goTo(i)} className={`relative ${pane === i ? 'text-amber-deep' : 'hover:text-ink'}`}>
              <span className="block text-lg">{PANE_ICONS[i]}</span>
              {label}
              {unfinished.length > 0 && i === ME_PANE && (
                <span className="absolute right-2 top-0 h-2 w-2 rounded-full bg-warn" />
              )}
            </button>
          ))}
        </nav>
      </div>
    </main>
  )
}

const subscribeNoop = () => () => {}
function readSignupSnapshot(): string | null {
  try {
    return sessionStorage.getItem(PILOT_PREVIEW_SIGNUP_KEY)
  } catch {
    return null
  }
}
function parseSignup(raw: string): PilotPreviewSignup | null {
  try {
    return JSON.parse(raw) as PilotPreviewSignup
  } catch {
    return null
  }
}

/**
 * Nash: "on my assignments, you could show me, like, the step four, what I
 * need to do, step five, what I need to do, like, to complete them, and
 * unfinished tasks."
 */
function OnboardingTasksCard({
  tasks,
  pendingCompany,
  onGo,
}: {
  tasks: ReturnType<typeof onboardingTasks>
  pendingCompany: string | null
  onGo: (step: 4 | 5 | 6) => void
}) {
  const left = tasks.filter((t) => !t.done).length
  return (
    <Card tone="warn">
      <div className="flex items-center justify-between">
        <CardHead label="Unfinished setup" />
        <span className="text-[11px] font-bold text-warn">{left} of {tasks.length} to do</span>
      </div>
      <ul className="mt-2 space-y-2">
        {tasks.map((t) => (
          <li key={t.step} className={`rounded-xl border p-2.5 text-xs ${t.done ? 'border-line bg-white/60 text-slate-body' : 'border-line bg-white'}`}>
            <div className="flex items-center justify-between gap-2">
              <p className="font-semibold">{t.done ? '✓ ' : ''}Step {t.step} · {t.title}</p>
              {!t.done && <button onClick={() => onGo(t.step)} className="shrink-0 rounded-lg bg-navy-900 px-2.5 py-1 text-[10px] font-bold text-white">Do it</button>}
            </div>
            {!t.done && <p className="mt-0.5 text-slate-body">{t.missing.join(' · ')}</p>}
            <p className="mt-0.5 text-[10px] text-slate-body/80">
              Who: {t.owner}
              {t.step === 4 && pendingCompany ? ` (or ${pendingCompany}, once they approve your request)` : ''}
            </p>
          </li>
        ))}
      </ul>
    </Card>
  )
}

/**
 * "Add pilot dispatch" / "Add pilot" on the Active Assignment (Nash,
 * 2026-09-13): pick from my active dispatchers (or pilots linked through my
 * companies), or invite by email. The invitee gets a templated email to
 * create their account and join this trip with exactly my access.
 */
function AddToTripCard({ kind, trip, me }: { kind: 'dispatch' | 'pilot'; trip: DemoPilotAssignment; me: DemoPilotDriver }) {
  const [open, setOpen] = useState(false)
  const [email, setEmail] = useState('')
  const [invited, setInvited] = useState<{ name: string; email: string; via: 'list' | 'email' }[]>([])

  const myCompanies = me.linkedCompanies.filter((c) => c !== 'Independent direct work')
  const options: { name: string; email: string; sub: string }[] =
    kind === 'dispatch'
      ? myCompanies.map((c) =>
          c === DEMO_PILOT_COMPANY.name
            ? { name: c, email: DEMO_PILOT_COMPANY.email, sub: `${DEMO_PILOT_COMPANY.mainContact} · ${DEMO_PILOT_COMPANY.phone}` }
            : { name: c, email: `dispatch@${c.toLowerCase().replace(/[^a-z]/g, '')}.example`, sub: 'Approved relationship' },
        )
      : DEMO_PILOT_DRIVERS.filter(
          (d) => d.id !== me.id && d.relationship === 'Approved' && d.linkedCompanies.some((c) => myCompanies.includes(c)),
        ).map((d) => ({ name: d.name, email: d.email, sub: `${d.homeBase} · ${d.linkedCompanies.filter((c) => myCompanies.includes(c)).join(', ')}` }))

  const template = DEFAULT_TEMPLATES.find((t) => t.key === (kind === 'dispatch' ? 'pilot_dispatch_trip_invite' : 'pilot_additional_trip_invite'))!
  const subjectFor = (name: string) =>
    renderTemplate(template.subject, { ...TEMPLATE_SAMPLE_DATA, pilot_driver_name: me.name, invitee_name: name, trip_id: trip.ref })

  function invite(name: string, addr: string, via: 'list' | 'email') {
    if (!addr) { toast.error('Enter an email'); return }
    setInvited((l) => [...l, { name, email: addr, via }])
    setEmail('')
    toast.success(`Invitation queued — email "${subjectFor(name)}" (not sent in this phase)`)
  }

  const label = kind === 'dispatch' ? 'pilot dispatch' : 'pilot'
  return (
    <Card>
      <CardHead label={kind === 'dispatch' ? 'Add my pilot dispatch' : 'Add another pilot'} />
      <p className="mt-1 text-xs text-slate-body">
        {kind === 'dispatch' ? 'Your pilot dispatch joins this trip' : 'An additional pilot car joins this trip'} with exactly your access — <span className="font-semibold text-ink">{scopeSummary(trip.scopes)}</span> — never more.
      </p>
      {invited.length > 0 && (
        <div className="mt-2 space-y-1">
          {invited.map((i, n) => (
            <p key={n} className="flex items-center justify-between rounded-lg bg-paper px-2.5 py-1.5 text-[11px]">
              <span><span className="font-semibold">{i.name}</span> · {i.email}</span>
              <span className="font-semibold text-warn">○ Invited{i.via === 'email' ? ' · account setup email' : ''}</span>
            </p>
          ))}
        </div>
      )}
      {!open ? (
        <button onClick={() => setOpen(true)} className="mt-2 w-full rounded-lg border border-line bg-white py-2 text-xs font-semibold">+ Add {label}</button>
      ) : (
        <div className="mt-2 space-y-2">
          <p className="text-[10px] font-bold uppercase tracking-wide text-slate-body/70">
            {kind === 'dispatch' ? 'My active dispatchers' : 'Pilots linked through my companies'}
          </p>
          {options.length === 0 && <p className="text-[11px] text-slate-body">None yet — invite by email below.</p>}
          {options.map((o) => (
            <button key={o.email} onClick={() => invite(o.name, o.email, 'list')} className="flex w-full items-center justify-between rounded-lg border border-line bg-white px-2.5 py-2 text-left text-xs hover:bg-paper">
              <span><span className="font-semibold">{o.name}</span><span className="block text-[11px] text-slate-body">{o.sub}</span></span>
              <span className="text-[11px] font-bold text-info">Add</span>
            </button>
          ))}
          <p className="pt-1 text-[10px] font-bold uppercase tracking-wide text-slate-body/70">Or invite by email</p>
          <div className="flex gap-1.5">
            <input value={email} onChange={(e) => setEmail(e.target.value)} placeholder={kind === 'dispatch' ? 'dispatcher@company.com' : 'pilot@example.com'} className="min-w-0 flex-1 rounded-lg border border-line px-2.5 py-1.5 text-xs" />
            <button onClick={() => invite(email.trim(), email.trim(), 'email')} className="rounded-lg bg-navy-900 px-3 py-1.5 text-xs font-bold text-white">Invite</button>
          </div>
          <p className="text-[11px] text-slate-body">
            They receive the “{template.name}” email (managed by admin under Email Templates) with a link to create their {label} account and join this trip.
          </p>
          <button onClick={() => setOpen(false)} className="text-[11px] font-semibold text-slate-body">Close</button>
        </div>
      )}
    </Card>
  )
}

function AssignmentCard({ a, highlighted, onOpen }: { a: DemoPilotAssignment; highlighted: boolean; onOpen: () => void }) {
  return (
    <button onClick={onOpen} className={`w-full rounded-2xl border bg-white p-4 text-left shadow-sm ${highlighted ? 'border-amber-brand' : 'border-line'}`}>
      <div className="flex items-start justify-between gap-2">
        <div className="min-w-0">
          <p className="truncate font-bold">{a.origin} → {a.destination}</p>
          <p className="truncate text-xs text-slate-body">{a.commodity} · {a.carrier}</p>
        </div>
        <span className="shrink-0 rounded-full bg-paper px-2 py-0.5 text-[10px] font-bold capitalize ring-1 ring-inset ring-line">{a.status}</span>
      </div>
      <p className="mt-2 text-[11px] text-slate-body">{a.position} · {scopeSummary(a.scopes)} · {a.permits.filter((p) => p.shared).length} permit(s) shared</p>
    </button>
  )
}

/**
 * Truck / trailer identification — make, model, year, VIN, plate and
 * registration state. Nash: "if somebody's not paying the bill, then he can go
 * back and find the information who owns that truck and trailer."
 */
function UnitCard({ label, summary, unit }: { label: string; summary: string; unit: DemoUnitInfo | null }) {
  return (
    <Card>
      <CardHead label={label} />
      {!unit ? (
        <p className="mt-1 text-xs text-slate-body">{summary === '—' ? 'Not assigned yet by the carrier.' : summary}</p>
      ) : (
        <>
          {/* Nash, 2026-09-12: "unit number first, year make model… remove
              registration state since it's already included in the plate." */}
          <p className="mt-1 text-sm font-bold">Unit {unit.unitNumber}</p>
          <p className="text-xs text-slate-body">{unit.year} {unit.make} {unit.model}</p>
          <div className="mt-1.5 space-y-1">
            <Row k="VIN" v={unit.vin} />
            <Row k="Plate" v={`${unit.plateState} ${unit.plate}`} />
          </div>
        </>
      )}
    </Card>
  )
}

function ContactCard({ label, person }: { label: string; person: { name: string; phone: string; email: string } }) {
  const reachable = person.phone !== '—'
  return (
    <Card>
      <CardHead label={label} />
      <p className="mt-1 text-sm font-bold">{person.name}</p>
      <p className="text-xs text-slate-body">{person.phone} · {person.email}</p>
      {reachable && (
        <div className="mt-2 flex gap-1.5">
          <a href={`tel:${person.phone.replace(/[^\d+]/g, '')}`} className="flex-1 rounded-lg border border-line bg-white py-1.5 text-center text-[11px] font-semibold">📞 Call</a>
          <a href={`mailto:${person.email}`} className="flex-1 rounded-lg border border-line bg-white py-1.5 text-center text-[11px] font-semibold">✉️ Email</a>
        </div>
      )}
    </Card>
  )
}

function Row({ k, v }: { k: string; v: string }) {
  return (
    <div className="flex justify-between gap-3 text-xs">
      <span className="shrink-0 text-slate-body">{k}</span>
      <span className="text-right font-medium">{v}</span>
    </div>
  )
}

function Card({ children, tone }: { children: React.ReactNode; tone?: 'warn' }) {
  return <section className={`rounded-2xl border p-4 shadow-sm ${tone === 'warn' ? 'border-warn/30 bg-warn-bg' : 'border-line bg-white'}`}>{children}</section>
}

function CardHead({ label }: { label: string }) {
  return <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-slate-body/70">{label}</p>
}
