'use client'

import { useState } from 'react'
import { FileText, AlertTriangle, Share2, UserMinus } from 'lucide-react'
import { toast } from 'sonner'
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { PilotAccessChooser } from '@/components/app/pilot-access-chooser'
import { money, PAPERWORK_PURPOSE, PAPERWORK_TRIAL_DAYS, PLAN_NAMES_FOR_PREVIEW, pilotPaperworkAccess, type PaperworkAccess, type PlanName } from '@/lib/domain/invoicing'
import { describePilotAccess, paperworkAlerts, parsePilotAccessLine, shareableWithin, type PilotInviteAccess, type PilotPaperworkDoc } from '@/lib/domain/pilot'
import type { PilotInvoice } from '@/lib/demo/invoicing-store'
import { useSignupAgePreview, useViewerPlanPreview } from '@/lib/demo/invoicing-store'
import { localToday } from '@/lib/format'
import { StatusPill } from './pilot-tools-panel'
import { LockedProFeature } from './locked-pro'

/**
 * "My Pilot" tab — the carrier's and the broker's view of the pilot cars on a
 * trip (Nash, 2026-09-12).
 *
 * Carrier dispatch: "who is involved… which states they have… the pilot's car,
 * the phone number, the contact information, the dispatch of the pilot… and
 * in there you can see the invoice that was generated for this trip by that
 * pilot car."
 * Broker: "all he's gonna see is the pilot name, phone number, and email…
 * what state was he hired for." Invoices only when the broker invited the
 * pilot or the pilot invited the broker.
 *
 * One component for the real trip workspace (real participants) and the
 * pilot workspace preview (demo data) so the two views cannot drift.
 */

export interface MyPilotEntry {
  name: string
  kind: 'Pilot dispatch' | 'Pilot driver'
  phone: string
  email: string
  /** e.g. "OH (state)", "Full trip", "Nothing shared yet — carrier will decide" */
  access: string
  states: string[]
  status: string
  /** Carrier-only detail. */
  car?: string
  dispatch?: string
  position?: string
  invitedBy?: string
  /**
   * Nash, 2026-09-13: a pilot "assigned by the dispatcher" — the broker sees
   * that a pilot is attached (and for which states) but not the contact info.
   * Set by the page for the broker viewer when the broker did not invite the pilot.
   */
  contactHidden?: boolean
  /**
   * Nash, 2026-09-13: the pilot's paperwork (COI, licenses, certifications —
   * everything, each with a PDF to open) for brokers and carriers. Undefined
   * for a real pilot who has no documents on file yet.
   */
  documents?: PilotPaperworkDoc[]
  /** trip_participants.id — the pilot the share is written against. */
  participantId?: string
  /**
   * May the VIEWER share permits with this pilot? True for the person who
   * invited them and for any admin (Nash, 2026-09-17). The server enforces
   * the same rule; this only decides whether the button is drawn.
   */
  canManageAccess?: boolean
  /**
   * May the VIEWER see this pilot's paperwork? Whoever started the
   * invitation chain (carrier dispatch → pilot dispatch → driver) and admin;
   * a broker who did not bring the pilot company in may not (Nash,
   * 2026-09-17). Undefined → visible (older callers).
   */
  paperworkVisible?: boolean
  /** May the VIEWER ask this pilot for paperwork? The inviter or admin only. */
  canRequestPaperwork?: boolean
  /** ISO timestamp of the newest paperwork request, from the trip history. */
  paperworkRequestedAt?: string
}

export function MyPilotTab({
  viewer,
  pilots,
  invoices,
  showInvoices,
  invoicesNote,
  onViewInvoice,
  paperwork,
  paperworkPlan = 'Free',
  onViewDocument,
  permits,
  viewerAccess,
  onShareAccess,
  onRequestPaperwork,
  onRemovePilot,
}: {
  viewer: 'carrier' | 'broker'
  pilots: MyPilotEntry[]
  invoices: PilotInvoice[]
  showInvoices: boolean
  invoicesNote?: string
  onViewInvoice?: (inv: PilotInvoice) => void
  /** Brokers and carriers (Nash, 2026-09-13). Omitted → no paperwork block. */
  paperwork?: PaperworkAccess
  /** The viewer's plan, for the locked card. */
  paperworkPlan?: PlanName
  onViewDocument?: (entry: MyPilotEntry, doc: PilotPaperworkDoc) => void
  /** The trip's permits — what can be shared. Omitted → no share control. */
  permits?: { id: string; state_code: string; permit_number: string | null }[]
  /**
   * The VIEWER's own pilot access when the viewer is themselves a pilot, so
   * they cannot hand out more than they hold (Nash, 2026-09-17). Null for a
   * broker, dispatcher, carrier driver or admin sharing from the trip itself.
   */
  viewerAccess?: PilotInviteAccess | null
  /** Persist a new access choice. Resolve to re-read the trip. */
  onShareAccess?: (entry: MyPilotEntry, access: PilotInviteAccess) => Promise<void>
  /**
   * Ask the pilot for their paperwork. Resolves with how the email went:
   * `sent` (delivered) or `recorded` (email delivery not configured yet).
   */
  onRequestPaperwork?: (entry: MyPilotEntry) => Promise<'sent' | 'recorded'>
  /**
   * Remove this pilot from the trip — the inviter's (or admin's) call, even
   * after permits were shared (Nash, 2026-09-17). Resolve to re-read the trip.
   */
  onRemovePilot?: (entry: MyPilotEntry) => Promise<void>
}) {
  const isCarrier = viewer === 'carrier'
  const showPaperwork = paperwork?.mode === 'included' || paperwork?.mode === 'trial'
  const [sharing, setSharing] = useState<MyPilotEntry | null>(null)
  const [removing, setRemoving] = useState<MyPilotEntry | null>(null)
  return (
    <div className="space-y-4 pt-4">
      <p className="text-xs text-neutral-500">
        {isCarrier
          ? 'Pilot cars attached to this trip — who is involved, for which states, their unit and contacts, and the invoices they generated for this trip.'
          : 'Pilot cars used on this trip and the states they were hired for. Contact details show only for a pilot you invited yourself.'}
      </p>

      {paperwork && pilots.length > 0 && (
        <p className="rounded-lg bg-neutral-100 px-3 py-2 text-[11px] text-neutral-700">
          <span className="font-semibold">Pilot paperwork.</span> {PAPERWORK_PURPOSE}
          {paperwork.mode === 'trial' && (
            <span className="ml-1 font-semibold text-amber-800">Free for your first {PAPERWORK_TRIAL_DAYS} days · {paperwork.daysLeft} day{paperwork.daysLeft === 1 ? '' : 's'} left.</span>
          )}
          {paperwork.mode === 'included' && <span className="ml-1 text-neutral-500">Included in your plan.</span>}
        </p>
      )}

      {pilots.length === 0 && (
        <p className="rounded-xl border border-dashed p-8 text-center text-sm text-neutral-500">No pilot car is attached to this trip.</p>
      )}

      <div className="space-y-2">
        {pilots.map((p, i) => (
          <div key={i} className="rounded-xl border bg-white p-3 text-sm">
            <div className="flex flex-wrap items-start justify-between gap-2">
              <div>
                <p className="font-semibold">{p.name} <span className="ml-1 rounded-full bg-neutral-100 px-2 py-0.5 text-[10px] font-bold uppercase text-neutral-600">{p.kind}</span></p>
                {p.contactHidden ? (
                  <p className="text-xs text-neutral-500">Hired by the carrier dispatcher — contact details stay with the carrier.</p>
                ) : (
                  <p className="text-xs text-neutral-500">{p.phone} · {p.email}</p>
                )}
              </div>
              <span className={`text-[11px] font-semibold ${p.status === 'Joined' || p.status === 'in progress' || p.status === 'accepted' ? 'text-green-700' : 'text-amber-700'}`}>
                {p.status === 'Joined' ? '● Joined' : p.status === 'Invited' || p.status === 'invited' ? '○ Invited' : p.status}
              </span>
            </div>
            <div className="mt-2 grid gap-1 text-xs sm:grid-cols-2">
              <p><span className="text-neutral-500">{isCarrier ? 'Access / states' : 'Hired for'}:</span> <span className="font-mono font-semibold">{p.states.length ? p.states.join(', ') : p.access}</span></p>
              {isCarrier && p.position && <p><span className="text-neutral-500">Position:</span> {p.position}</p>}
              {isCarrier && p.car && <p><span className="text-neutral-500">Pilot car:</span> {p.car}</p>}
              {isCarrier && p.dispatch && <p><span className="text-neutral-500">Pilot dispatch:</span> {p.dispatch}</p>}
              {isCarrier && p.invitedBy && <p><span className="text-neutral-500">Invited by:</span> {p.invitedBy}</p>}
            </div>
            {p.canManageAccess && p.participantId && permits && onShareAccess && (
              <div className="mt-2.5 flex flex-wrap items-center gap-2 border-t pt-2.5">
                <button
                  type="button"
                  onClick={() => setSharing(p)}
                  className="inline-flex items-center gap-1.5 rounded-lg border border-[#0f1b2d] px-2.5 py-1 text-[11px] font-bold text-[#0f1b2d] transition hover:bg-[#0f1b2d] hover:text-white"
                >
                  <Share2 className="size-3.5" />
                  Share permits
                </button>
                <span className="text-[11px] text-neutral-500">
                  {p.access === 'Decide later' ? 'Nothing shared yet — choose what this pilot can open.' : `Currently: ${p.access}`}
                </span>
                {onRemovePilot && (
                  <button
                    type="button"
                    onClick={() => setRemoving(p)}
                    className="ml-auto inline-flex items-center gap-1.5 rounded-lg border border-red-200 px-2.5 py-1 text-[11px] font-bold text-red-700 transition hover:bg-red-600 hover:text-white"
                  >
                    <UserMinus className="size-3.5" />
                    Remove from trip
                  </button>
                )}
              </div>
            )}
            {showPaperwork && p.paperworkVisible !== false && (
              <PaperworkBlock entry={p} onView={onViewDocument} onRequest={p.canRequestPaperwork && p.participantId && onRequestPaperwork ? onRequestPaperwork : undefined} />
            )}
            {showPaperwork && p.paperworkVisible === false && (
              <p className="mt-3 border-t pt-3 text-[11px] text-neutral-500">Paperwork is visible to the person who arranged this pilot.</p>
            )}
          </div>
        ))}
      </div>

      {removing && onRemovePilot && (
        <RemovePilotDialog entry={removing} onClose={() => setRemoving(null)} onConfirm={onRemovePilot} />
      )}

      {sharing && permits && onShareAccess && (
        <SharePermitsDialog
          entry={sharing}
          permits={permits}
          viewerAccess={viewerAccess}
          onClose={() => setSharing(null)}
          onSave={onShareAccess}
        />
      )}

      {paperwork?.mode === 'locked' && pilots.length > 0 && <LockedProFeature plan={paperworkPlan} feature="paperwork" />}

      {showInvoices ? (
        <div>
          <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-neutral-500">Pilot invoices for this trip · {invoices.length}</p>
          {invoicesNote && <p className="mt-1 text-[11px] text-amber-800">{invoicesNote}</p>}
          {invoices.length === 0 ? (
            <p className="mt-2 rounded-xl border border-dashed p-6 text-center text-xs text-neutral-500">No invoices generated by the pilot for this trip yet.</p>
          ) : (
            <div className="mt-2 divide-y rounded-xl border bg-white">
              {invoices.map((inv) => (
                <div key={inv.id} className="flex flex-wrap items-center justify-between gap-2 px-3 py-2.5 text-xs">
                  <div>
                    <p className="font-semibold">{inv.invoiceNumber} <StatusPill status={inv.status} /></p>
                    <p className="text-neutral-500">{inv.ownerName} · {inv.invoiceDate} · due {inv.dueDate ?? (inv.dueDateKey === 'asap' ? 'ASAP' : 'not set')} · {inv.calc.selectedBaseType} base</p>
                  </div>
                  <div className="flex items-center gap-2">
                    <span className="font-bold">{money(inv.calc.invoiceTotal)}</span>
                    {onViewInvoice && <button onClick={() => onViewInvoice(inv)} className="rounded-lg border px-2 py-1 text-[11px] font-semibold">View PDF</button>}
                  </div>
                </div>
              ))}
            </div>
          )}
          <p className="mt-1.5 text-[11px] text-neutral-500">{isCarrier ? 'The carrier can receive and view pilot invoices but cannot edit them.' : 'Shown because the broker arranged this pilot.'}</p>
        </div>
      ) : (
        viewer === 'broker' && (
          <p className="text-[11px] text-neutral-500">Pilot invoices are between the pilot and the carrier. They appear here only when the broker invited the pilot or the pilot invited the broker.</p>
        )
      )}
    </div>
  )
}

const DOC_STATUS_CLASS: Record<PilotPaperworkDoc['status'], string> = {
  Approved: 'bg-green-100 text-green-800',
  Uploaded: 'bg-blue-100 text-blue-800',
  'Pending Review': 'bg-blue-100 text-blue-800',
  'Expiring Soon': 'bg-amber-100 text-amber-800',
  Expired: 'bg-red-100 text-red-800',
  Rejected: 'bg-red-100 text-red-800',
  'Not Uploaded': 'bg-neutral-100 text-neutral-600',
}

/**
 * The paperwork block on one pilot entry (brokers and carriers, Starter or
 * higher / first 90 days): missing-paperwork alert first, then every
 * document with a PDF icon. Also used on the carrier driver's state cards.
 */
export function PaperworkBlock({
  entry,
  onView,
  onRequest,
}: {
  entry: MyPilotEntry
  onView?: (entry: MyPilotEntry, doc: PilotPaperworkDoc) => void
  /** Present only for the person who invited this pilot (or admin) on a plan that includes paperwork. */
  onRequest?: (entry: MyPilotEntry) => Promise<'sent' | 'recorded'>
}) {
  const docs = entry.documents ?? []
  const alerts = paperworkAlerts(docs)
  const [requesting, setRequesting] = useState(false)
  async function request() {
    if (!onRequest) return
    setRequesting(true)
    try {
      const how = await onRequest(entry)
      toast.success(
        how === 'sent'
          ? `Paperwork requested — ${entry.name} has been emailed.`
          : `Paperwork request recorded for ${entry.name}. Email delivery is not switched on yet, so nothing was sent.`,
      )
    } catch (e) {
      toast.error(e instanceof Error ? e.message : 'Could not request paperwork.')
    } finally {
      setRequesting(false)
    }
  }
  return (
    <div className="mt-3 border-t pt-3">
      <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-neutral-500">Paperwork</p>
      {docs.length === 0 ? (
        <div className="mt-1.5 flex flex-wrap items-center gap-2">
          <p className="text-xs text-neutral-500">No paperwork on file yet.</p>
          {onRequest && (
            <button
              type="button"
              onClick={request}
              disabled={requesting}
              className="inline-flex items-center gap-1.5 rounded-lg border border-[#0f1b2d] px-2.5 py-1 text-[11px] font-bold text-[#0f1b2d] transition hover:bg-[#0f1b2d] hover:text-white disabled:opacity-50"
            >
              <FileText className="size-3.5" />
              {requesting ? 'Requesting…' : entry.paperworkRequestedAt ? 'Request again' : 'Request paperwork'}
            </button>
          )}
          {entry.paperworkRequestedAt && (
            <span className="text-[11px] text-neutral-500">Requested {new Date(entry.paperworkRequestedAt).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}</span>
          )}
        </div>
      ) : (
        <>
          {alerts.length > 0 && (
            <p className="mt-1.5 flex items-start gap-1.5 rounded-lg bg-red-50 px-2.5 py-1.5 text-[11px] font-semibold text-red-800">
              <AlertTriangle className="mt-0.5 size-3.5 shrink-0" />
              <span>Missing paperwork: {alerts.join(' · ')}</span>
            </p>
          )}
          <ul className="mt-1.5 divide-y rounded-lg border">
            {docs.map((d) => {
              const has = d.status !== 'Not Uploaded'
              return (
                <li key={d.key} className="flex flex-wrap items-center gap-2 px-2.5 py-1.5 text-xs">
                  <button
                    type="button"
                    disabled={!has || !onView}
                    onClick={() => onView?.(entry, d)}
                    title={has ? `Open ${d.label} (PDF)` : 'Not uploaded'}
                    aria-label={has ? `Open ${d.label} PDF` : `${d.label} not uploaded`}
                    className={`grid size-7 shrink-0 place-items-center rounded-md ${has ? 'bg-red-50 text-red-700 hover:bg-red-100' : 'bg-neutral-100 text-neutral-400'}`}
                  >
                    <FileText className="size-4" />
                  </button>
                  <span className="min-w-0 flex-1 font-semibold">{d.label}{!d.required && <span className="ml-1 font-normal text-neutral-500">(optional)</span>}</span>
                  <span className={`rounded-full px-2 py-0.5 text-[10px] font-bold ${DOC_STATUS_CLASS[d.status]}`}>{d.status}</span>
                  {d.expirationDate && <span className="text-neutral-500">{d.status === 'Expired' ? 'expired' : 'exp.'} {d.expirationDate}</span>}
                </li>
              )
            })}
          </ul>
        </>
      )}
    </div>
  )
}

/**
 * Admin-only switches next to the tab: the viewer's plan and the days since
 * sign-up, so included / free-window / locked can all be reviewed.
 */
export function PaperworkPreviewSwitch({ signedUpAt }: { signedUpAt?: string }) {
  const { plan, setPlan } = useViewerPlanPreview('Free')
  const { days, setDays } = useSignupAgePreview(daysSince(signedUpAt))
  return (
    <div className="flex flex-wrap items-center gap-x-3 gap-y-1 rounded-lg border border-dashed border-amber-300 bg-amber-50/60 px-2.5 py-1.5 text-[11px]">
      <span className="font-semibold text-amber-900">Design preview</span>
      <label className="flex items-center gap-1">Your plan
        <select value={plan} onChange={(e) => setPlan(e.target.value as PlanName)} className="rounded border bg-white px-1 py-0.5 text-[11px]">
          {PLAN_NAMES_FOR_PREVIEW.map((n) => <option key={n} value={n}>{n}</option>)}
        </select>
      </label>
      <label className="flex items-center gap-1">Signed up
        <select value={String(days)} onChange={(e) => setDays(Number(e.target.value))} className="rounded border bg-white px-1 py-0.5 text-[11px]">
          {[...new Set([days, 5, 60, 89, 90, 200])].sort((a, b) => a - b).map((d) => <option key={d} value={d}>{d} day{d === 1 ? '' : 's'} ago</option>)}
        </select>
      </label>
    </div>
  )
}

function daysSince(iso?: string): number {
  if (!iso) return 10
  const ms = new Date(localToday()).getTime() - new Date(iso.slice(0, 10)).getTime()
  return Math.max(0, Math.floor(ms / 86_400_000))
}

/**
 * Paperwork access for the viewing broker / carrier account: the real
 * sign-up date drives the 90-day window; admin preview switches override.
 */
export function useViewerPaperworkAccess(signedUpAt?: string): { access: PaperworkAccess; plan: PlanName } {
  const { plan } = useViewerPlanPreview('Free')
  const { days } = useSignupAgePreview(daysSince(signedUpAt))
  const today = localToday()
  const signedUp = new Date(new Date(today).getTime() - days * 86_400_000).toISOString().slice(0, 10)
  return { access: pilotPaperworkAccess({ plan, signedUpAt: signedUp, today }), plan }
}

/**
 * "Share permits" — the inviter (or an admin) choosing what this pilot can
 * open (Nash, 2026-09-17): "he can share a specific state, a specific permit,
 * or the entire trip, or multiple permits or multiple states."
 *
 * Opens on what the pilot holds today. When the sharer is themselves a pilot,
 * the list is narrowed to their own grant — "a pilot dispatch given two or
 * three permits has the power to assign out of those two or three permits".
 */
function SharePermitsDialog({
  entry,
  permits,
  viewerAccess,
  onClose,
  onSave,
}: {
  entry: MyPilotEntry
  permits: { id: string; state_code: string; permit_number: string | null }[]
  viewerAccess?: PilotInviteAccess | null
  onClose: () => void
  onSave: (entry: MyPilotEntry, access: PilotInviteAccess) => Promise<void>
}) {
  const bound = shareableWithin(viewerAccess, permits)
  const offerable = permits.filter((p) => bound.permits.some((b) => b.id === p.id))
  const [access, setAccess] = useState<PilotInviteAccess>(() => parsePilotAccessLine(entry.access, permits))
  const [busy, setBusy] = useState(false)

  const empty =
    (access.type === 'states' && access.states.length === 0) ||
    (access.type === 'permits' && access.permit_ids.length === 0)

  async function save() {
    if (empty) {
      toast.error('Pick at least one state or permit, or choose “Decide later”.')
      return
    }
    setBusy(true)
    try {
      await onSave(entry, access)
      toast.success(`${entry.name}: ${describePilotAccess(access)}`)
      onClose()
    } catch (e) {
      toast.error(e instanceof Error ? e.message : 'Could not share permits.')
    } finally {
      setBusy(false)
    }
  }

  return (
    <Dialog open onOpenChange={(o) => !o && onClose()}>
      <DialogContent className="sm:max-w-lg">
        <DialogHeader>
          <DialogTitle>Share permits with {entry.name}</DialogTitle>
        </DialogHeader>
        <div className="space-y-3">
          <p className="text-xs text-neutral-500">
            {entry.kind} · {entry.email}
            {!bound.fullTrip && (
              <span className="mt-1 block text-amber-800">
                You can share only what was shared with you{bound.permits.length === 0 ? ' — nothing yet' : ''}.
              </span>
            )}
          </p>
          <PilotAccessChooser permits={offerable} value={access} onChange={setAccess} />
          <div className="flex justify-end gap-2">
            <button type="button" onClick={onClose} className="rounded-lg border px-3 py-1.5 text-sm font-semibold">
              Cancel
            </button>
            <button
              type="button"
              onClick={save}
              disabled={busy}
              className="rounded-lg bg-[#0f1b2d] px-3 py-1.5 text-sm font-bold text-white disabled:opacity-50"
            >
              {busy ? 'Sharing…' : 'Share'}
            </button>
          </div>
        </div>
      </DialogContent>
    </Dialog>
  )
}

/**
 * "Remove from trip" — confirmation, because it ends the pilot's access
 * outright (Nash, 2026-09-17): "he has the full power to remove the relation
 * between this pilot and him." Their open invitation link dies with it.
 */
function RemovePilotDialog({
  entry,
  onClose,
  onConfirm,
}: {
  entry: MyPilotEntry
  onClose: () => void
  onConfirm: (entry: MyPilotEntry) => Promise<void>
}) {
  const [busy, setBusy] = useState(false)
  async function confirm() {
    setBusy(true)
    try {
      await onConfirm(entry)
      toast.success(`${entry.name} was removed from this trip.`)
      onClose()
    } catch (e) {
      toast.error(e instanceof Error ? e.message : 'Could not remove the pilot.')
    } finally {
      setBusy(false)
    }
  }
  const pending = entry.status === 'Invited' || entry.status === 'invited'
  return (
    <Dialog open onOpenChange={(o) => !o && onClose()}>
      <DialogContent className="sm:max-w-md">
        <DialogHeader>
          <DialogTitle>Remove {entry.name} from this trip?</DialogTitle>
        </DialogHeader>
        <div className="space-y-3 text-sm">
          <p className="text-neutral-600">
            {pending
              ? 'They have not accepted yet. Their invitation link will stop working and they will not be able to join this trip.'
              : 'They will lose access to this trip and everything that was shared with them. Nothing already on the trip is deleted.'}
          </p>
          <p className="text-xs text-neutral-500">{entry.kind} · {entry.email}{entry.access !== 'Decide later' ? ` · had: ${entry.access}` : ''}</p>
          <div className="flex justify-end gap-2">
            <button type="button" onClick={onClose} className="rounded-lg border px-3 py-1.5 text-sm font-semibold">
              Keep
            </button>
            <button
              type="button"
              onClick={confirm}
              disabled={busy}
              className="rounded-lg bg-red-600 px-3 py-1.5 text-sm font-bold text-white disabled:opacity-50"
            >
              {busy ? 'Removing…' : 'Remove'}
            </button>
          </div>
        </div>
      </DialogContent>
    </Dialog>
  )
}
