"use client";

import { useId, useState, type ReactNode } from "react";
import { CheckIcon, MailIcon, PhoneIcon, PlusIcon, Trash2Icon } from "lucide-react";

import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { formatDate, formatKES, initials } from "@/lib/format";
import { cn } from "@/lib/utils";
import { RecordStatusBadge, type StatusLabel } from "./status";

const money = "text-right tabular-nums";

/* ------------------------------------------------- Customer / supplier header */

function PartyHeader({
  name,
  meta,
  contacts,
  actions,
  badge,
}: {
  name: string;
  meta: ReactNode;
  contacts: { icon: ReactNode; text: string }[];
  actions?: ReactNode;
  badge?: ReactNode;
}) {
  return (
    <div className="flex flex-wrap items-start justify-between gap-3 rounded-lg border border-border bg-card p-4">
      <div className="flex min-w-0 items-start gap-3">
        <Avatar className="size-10 rounded-lg after:rounded-lg">
          <AvatarFallback className="rounded-lg bg-accent text-sm font-medium text-accent-foreground">{initials(name)}</AvatarFallback>
        </Avatar>
        <div className="min-w-0">
          <div className="flex flex-wrap items-center gap-2">
            <h3 className="text-base font-semibold text-foreground">{name}</h3>
            {badge}
          </div>
          <p className="text-xs text-muted-foreground">{meta}</p>
          <ul className="mt-2 flex flex-wrap gap-x-4 gap-y-1 text-xs text-muted-foreground">
            {contacts.map((c) => (
              <li key={c.text} className="flex items-center gap-1.5">
                {c.icon}
                {c.text}
              </li>
            ))}
          </ul>
        </div>
      </div>
      {actions ? <div className="flex gap-2">{actions}</div> : null}
    </div>
  );
}

export function CustomerHeader({
  name,
  phone,
  email,
  lastVisit,
  visits,
  totalSpend,
  onAccount,
  actions,
}: {
  name: string;
  phone: string;
  email: string;
  lastVisit: string;
  visits: number;
  totalSpend: number;
  /** True when the customer has a credit limit and can buy on account. */
  onAccount?: boolean;
  actions?: ReactNode;
}) {
  return (
    <PartyHeader
      name={name}
      badge={onAccount ? <RecordStatusBadge domain="sale" status="Credit" /> : null}
      meta={
        <span className="tabular-nums">
          {visits} visits, {formatKES(totalSpend)} lifetime, last visit {formatDate(lastVisit)}
        </span>
      }
      contacts={[
        { icon: <PhoneIcon className="size-3.5" aria-hidden />, text: phone },
        { icon: <MailIcon className="size-3.5" aria-hidden />, text: email },
      ]}
      actions={actions}
    />
  );
}

export function SupplierHeader({
  name,
  contact,
  phone,
  town,
  leadDays,
  actions,
}: {
  name: string;
  contact: string;
  phone: string;
  town?: string | null;
  /** Null when not recorded (suppliers added before SU-07): the header says so instead of "about 0 days". */
  leadDays: number | null;
  actions?: ReactNode;
}) {
  return (
    <PartyHeader
      name={name}
      meta={
        <span className="tabular-nums">
          {[town, leadDays != null ? `delivers in about ${leadDays} days` : "lead time not recorded"].filter(Boolean).join(", ").replace(/^./, (c) => c.toUpperCase())}
        </span>
      }
      contacts={[{ icon: <PhoneIcon className="size-3.5" aria-hidden />, text: `${contact}, ${phone}` }]}
      actions={actions}
    />
  );
}

/* -------------------------------------------------------- Status timeline */

export type TimelineStep = { label: string; at?: string; state: "done" | "current" | "todo" | "failed" };

export function StatusTimeline({ steps, className }: { steps: TimelineStep[]; className?: string }) {
  return (
    <ol className={cn("flex items-start", className)}>
      {steps.map((s, i) => (
        <li key={s.label} className="relative flex flex-1 flex-col items-start gap-1 first:pl-0">
          <div className="flex w-full items-center">
            <span
              className={cn(
                "flex size-6 shrink-0 items-center justify-center rounded-full border text-xs font-medium tabular-nums",
                s.state === "done" && "border-primary bg-primary text-primary-foreground",
                s.state === "current" && "border-primary bg-card text-primary",
                s.state === "todo" && "border-border bg-card text-muted-foreground",
                s.state === "failed" && "border-status-error-border bg-status-error-bg text-status-error-text",
              )}
              aria-current={s.state === "current" ? "step" : undefined}
            >
              {s.state === "done" ? <CheckIcon className="size-3" aria-hidden /> : i + 1}
            </span>
            {i < steps.length - 1 ? <span className={cn("mx-1 h-px flex-1", s.state === "done" ? "bg-primary" : "bg-border")} /> : null}
          </div>
          <span className={cn("text-xs", s.state === "todo" ? "text-muted-foreground" : "font-medium text-foreground")}>{s.label}</span>
          {s.at ? <span className="text-xs tabular-nums text-muted-foreground">{s.at}</span> : null}
        </li>
      ))}
    </ol>
  );
}

/* ------------------------------------------------------- Prescription card */

export type RxStatus = StatusLabel<"prescription">;
export type RxItem = { name: string; dose: string; quantity: number };

function rxSteps(status: RxStatus, date: string): TimelineStep[] {
  const received: TimelineStep = { label: "Received", at: formatDate(date, { short: true }), state: "done" };
  if (status === "Cancelled" || status === "Expired")
    return [received, { label: "Verified", state: "todo" }, { label: status, state: "failed" }];
  const verified = status !== "Pending";
  const done = status === "Dispensed";
  return [
    received,
    { label: "Verified", state: verified ? "done" : "current" },
    { label: status === "Partially" ? "Partly dispensed" : "Dispensed", state: done ? "done" : verified ? "current" : "todo" },
  ];
}

export function PrescriptionCard({
  reference,
  patient,
  prescriber,
  facility,
  date,
  items,
  status,
  actions,
}: {
  reference: string;
  patient: string;
  prescriber: string;
  facility: string;
  date: string;
  items: RxItem[];
  status: RxStatus;
  actions?: ReactNode;
}) {
  return (
    <div className="rounded-lg border border-border bg-card">
      <div className="flex items-start justify-between gap-3 border-b border-border p-3">
        <div>
          <p className="font-mono text-xs text-muted-foreground">{reference}</p>
          <h3 className="text-sm font-semibold text-foreground">{patient}</h3>
          <p className="text-xs text-muted-foreground">
            {prescriber}, {facility}
          </p>
        </div>
        <RecordStatusBadge domain="prescription" status={status} />
      </div>
      <ul className="divide-y divide-border">
        {items.map((it) => (
          <li key={it.name} className="flex items-baseline justify-between gap-3 px-3 py-2 text-sm">
            <span>
              <span className="font-medium text-foreground">{it.name}</span>
              <span className="block text-xs text-muted-foreground">{it.dose}</span>
            </span>
            <span className="tabular-nums text-muted-foreground">x {it.quantity}</span>
          </li>
        ))}
      </ul>
      <div className="border-t border-border p-3">
        <StatusTimeline steps={rxSteps(status, date)} />
      </div>
      {actions ? <div className="flex justify-end gap-2 border-t border-border p-3">{actions}</div> : null}
    </div>
  );
}

/* --------------------------------------------------------- Dispense checklist */

export type DispenseItem = { name: string; quantity: number; batch: string; expiry: string };

export function DispenseChecklist({
  items,
  disabled,
  onSignOff,
}: {
  items: DispenseItem[];
  disabled?: boolean;
  onSignOff?: () => void;
}) {
  const uid = useId();
  const [verified, setVerified] = useState<Record<string, boolean>>({});
  const [counselled, setCounselled] = useState(false);
  const [signed, setSigned] = useState(false);
  const allVerified = items.every((i) => verified[i.name]);
  const ready = allVerified && counselled;
  const stages = [allVerified, counselled, signed];
  return (
    <div className="max-w-xl rounded-lg border border-border bg-card">
      <div className="flex items-center justify-between border-b border-border px-3 py-2">
        <h3 className="text-sm font-semibold text-foreground">Dispense checklist</h3>
        <span className="text-xs tabular-nums text-muted-foreground">{stages.filter(Boolean).length} of 3 stages</span>
      </div>
      <fieldset disabled={disabled || signed} className="m-0 min-w-0 border-0 p-0">
        <legend className="sr-only">Dispense checklist</legend>
        <div className="border-b border-border px-3 py-2">
          <p className="mb-1.5 text-xs font-medium text-muted-foreground">1. Verify items and pick batch (earliest expiry first)</p>
          <ul className="space-y-1.5">
            {items.map((it) => (
              <li key={it.name} className="flex items-center gap-2 text-sm">
                <Checkbox
                  id={`${uid}-${it.name}`}
                  checked={!!verified[it.name]}
                  onCheckedChange={(v) => setVerified((s) => ({ ...s, [it.name]: !!v }))}
                  disabled={disabled || signed}
                />
                <Label htmlFor={`${uid}-${it.name}`} className="flex flex-1 items-baseline justify-between gap-2 font-normal">
                  <span>
                    {it.name} <span className="tabular-nums text-muted-foreground">x {it.quantity}</span>
                  </span>
                  <span className="font-mono text-xs text-muted-foreground">
                    {it.batch}, exp {it.expiry}
                  </span>
                </Label>
              </li>
            ))}
          </ul>
        </div>
        <div className="flex items-center gap-2 border-b border-border px-3 py-2 text-sm">
          <Checkbox id={`${uid}-counsel`} checked={counselled} onCheckedChange={(v) => setCounselled(!!v)} disabled={disabled || signed} />
          <Label htmlFor={`${uid}-counsel`} className="font-normal">
            2. Counselled the patient on dose, timing and side effects
          </Label>
        </div>
      </fieldset>
      <div className="flex items-center justify-between gap-2 px-3 py-2">
        <p className="text-xs text-muted-foreground">{signed ? "Signed off. Stock deducted from the picked batches." : "3. Sign-off is enabled once stages 1 and 2 are complete."}</p>
        <Button
          size="sm"
          disabled={disabled || !ready || signed}
          onClick={() => {
            setSigned(true);
            onSignOff?.();
          }}
        >
          {signed ? "Signed off" : "Sign off and dispense"}
        </Button>
      </div>
    </div>
  );
}

/* ---------------------------------------------------- Purchase order lines */

export type PoLine = { id: number; product: string; quantity: number; unitCost: number; received: number };

export function PoLinesEditor({
  initial,
  mode = "draft",
  disabled,
}: {
  initial: PoLine[];
  /** draft: edit qty and cost. receiving: edit received qty only. readonly: nothing editable. */
  mode?: "draft" | "receiving" | "readonly";
  disabled?: boolean;
}) {
  const [lines, setLines] = useState(initial);
  const [nextId, setNextId] = useState(100);
  const patch = (id: number, p: Partial<PoLine>) => setLines((ls) => ls.map((l) => (l.id === id ? { ...l, ...p } : l)));
  const num = (v: string) => Math.max(0, Number(v) || 0);
  const total = lines.reduce((s, l) => s + l.quantity * l.unitCost, 0);
  const receivedValue = lines.reduce((s, l) => s + l.received * l.unitCost, 0);
  const editDraft = mode === "draft" && !disabled;
  const editRecv = mode === "receiving" && !disabled;
  const cell = "h-7 w-20 text-right tabular-nums";
  return (
    <div className="rounded-lg border border-border bg-card">
      <Table>
        <TableHeader>
          <TableRow>
            <TableHead>Product</TableHead>
            <TableHead className={money}>Ordered</TableHead>
            <TableHead className={money}>Unit cost</TableHead>
            <TableHead className={money}>Line total</TableHead>
            <TableHead className={money}>Received</TableHead>
            <TableHead className="w-8" />
          </TableRow>
        </TableHeader>
        <TableBody>
          {lines.length === 0 ? (
            <TableRow>
              <TableCell colSpan={6} className="py-6 text-center text-muted-foreground">
                No lines yet. Add a product to start the order.
              </TableCell>
            </TableRow>
          ) : null}
          {lines.map((l) => (
            <TableRow key={l.id}>
              <TableCell>
                {editDraft && l.id >= 100 ? (
                  <Input aria-label="Product" className="h-7" value={l.product} placeholder="Product name" onChange={(e) => patch(l.id, { product: e.target.value })} />
                ) : (
                  l.product || <span className="text-muted-foreground">Unnamed product</span>
                )}
              </TableCell>
              <TableCell className={money}>
                {editDraft ? <Input aria-label={`Ordered quantity, ${l.product}`} className={cell} inputMode="numeric" value={l.quantity} onChange={(e) => patch(l.id, { quantity: num(e.target.value) })} /> : l.quantity}
              </TableCell>
              <TableCell className={money}>
                {editDraft ? <Input aria-label={`Unit cost, ${l.product}`} className={cell} inputMode="decimal" value={l.unitCost} onChange={(e) => patch(l.id, { unitCost: num(e.target.value) })} /> : formatKES(l.unitCost, { decimals: true })}
              </TableCell>
              <TableCell className={money}>{formatKES(l.quantity * l.unitCost)}</TableCell>
              <TableCell className={money}>
                {editRecv ? (
                  <Input aria-label={`Received quantity, ${l.product}`} className={cell} inputMode="numeric" value={l.received} onChange={(e) => patch(l.id, { received: Math.min(l.quantity, num(e.target.value)) })} />
                ) : (
                  <span className={l.received < l.quantity && mode !== "draft" ? "text-status-warning-text" : ""}>{mode === "draft" ? "" : l.received}</span>
                )}
              </TableCell>
              <TableCell>
                {editDraft ? (
                  <Button variant="ghost" size="icon-xs" aria-label={`Remove ${l.product || "line"}`} onClick={() => setLines((ls) => ls.filter((x) => x.id !== l.id))}>
                    <Trash2Icon />
                  </Button>
                ) : null}
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
        <TableFooter>
          <TableRow>
            <TableCell colSpan={3} className="font-medium">
              Order total
            </TableCell>
            <TableCell className={cn(money, "font-semibold")}>{formatKES(total)}</TableCell>
            <TableCell className={cn(money, "text-muted-foreground")}>{mode === "draft" ? "" : formatKES(receivedValue)}</TableCell>
            <TableCell />
          </TableRow>
        </TableFooter>
      </Table>
      {editDraft ? (
        <div className="border-t border-border p-2">
          <Button
            variant="outline"
            size="sm"
            onClick={() => {
              setLines((ls) => [...ls, { id: nextId, product: "", quantity: 1, unitCost: 0, received: 0 }]);
              setNextId((n) => n + 1);
            }}
          >
            <PlusIcon data-icon="inline-start" />
            Add line
          </Button>
        </div>
      ) : null}
    </div>
  );
}

/* ----------------------------------------------------- Goods received stepper */

const PO_STEPS = ["Draft", "Ordered", "Partly received", "Received"] as const;
export type PoStage = (typeof PO_STEPS)[number];

export function GoodsReceivedStepper({ stage, cancelled }: { stage: PoStage; cancelled?: boolean }) {
  const current = PO_STEPS.indexOf(stage);
  const steps: TimelineStep[] = PO_STEPS.map((label, i) => ({
    label,
    state: cancelled && i === current ? "failed" : i < current || (i === current && stage === "Received") ? "done" : i === current ? "current" : "todo",
  }));
  return (
    <div className="rounded-lg border border-border bg-card p-3">
      <StatusTimeline steps={steps} />
      {cancelled ? <p className="mt-2 text-xs text-status-error-text">Cancelled at stage: {stage}.</p> : null}
    </div>
  );
}
