"use client";

import * as React from "react";
import { PlusIcon, Trash2Icon } from "lucide-react";

import { RecordDrawer } from "@/components/medora/drawer";
import { CsvImportReview, downloadText, FileUpload, reviewCsv, type CsvColumn, type CsvReviewResult } from "@/components/medora/file-upload";
import { kes } from "@/components/medora/payroll";
import { poTotals } from "@/components/medora/purchasing";
import { ListTable } from "@/components/medora/record-lists";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select";
import { count, addDays, formatDate, formatPhone } from "@/lib/format";
import { cn } from "@/lib/utils";

/*
 * Registers: the customer, supplier and employee lists (CU-02, SU-02, HR-01) with search, filters, CSV
 * import and export; insurance and medical schemes (CU-09); the quotation form in Accounts (AC-15); and the
 * asset form (AC-18). Lists show key columns only; the rest is on each record's own page.
 */

const csvCell = (v: string | number) => (/[",\n]/.test(String(v)) ? `"${String(v).replace(/"/g, '""')}"` : String(v));
const toCsv = (head: string[], rows: (string | number)[][]) => [head.join(","), ...rows.map((r) => r.map(csvCell).join(","))].join("\n");

/**
 * Import for the registers, in a drawer opened from the page header's More (page header spec): a CSV checked row by
 * row before anything is added. Export is the table toolbar's Export menu (data table spec §1.8).
 */
function ImportDrawer({ noun, columns, template, open, onOpenChange, onImport }: { noun: string; columns: CsvColumn[]; template: string; open: boolean; onOpenChange: (open: boolean) => void; onImport: (rows: Record<string, string>[]) => void }) {
  const [csv, setCsv] = React.useState<CsvReviewResult | null>(null);
  const close = () => {
    setCsv(null);
    onOpenChange(false);
  };
  return (
    <RecordDrawer open={open} onOpenChange={(o) => (o ? onOpenChange(true) : close())} title={`Import ${noun} from CSV`} subtitle="Every row is checked before anything is added.">
      {csv ? (
        <CsvImportReview
          result={csv}
          noun={noun}
          onChooseAnother={() => setCsv(null)}
          onImport={() => {
            onImport(csv.valid);
            close();
          }}
        />
      ) : (
        <FileUpload
          label={`Import ${noun} (CSV)`}
          hint={`Columns: ${columns.map((c) => c.header).join(", ")}. Every row is checked before anything is added.`}
          kind="csv"
          accept={[".csv"]}
          maxBytes={2 * 1024 * 1024}
          onTemplate={() => downloadText(`${noun}-template.csv`, template)}
          upload={async (file, prog) => {
            prog(100);
            setCsv(reviewCsv(await file.text(), columns, columns[0].key));
          }}
        />
      )}
    </RecordDrawer>
  );
}

/** The toolbar's Export menu for a register: CSV of the rows on screen. */
const csvExport = <T,>(noun: string, head: string[], row: (r: T) => (string | number)[]) => [{ label: "CSV", onSelect: (shown: T[]) => downloadText(`${noun}.csv`, toCsv(head, shown.map(row))) }];

const phoneOk = (v: string) => (/^(\+?254|0)[17]\d{8}$/.test(v.replace(/\s/g, "")) ? undefined : "Not a mobile number.");

/* ------------------------------------ CU-02 Customers ------------------------------------ */

export type CustomerListRow = { id: number; name: string; kind: "Individual" | "Company"; group?: string; phone: string; balance: number; creditLimit: number; lastVisit: string };

export function CustomersList({ rows, groups, onOpen, onImport, importOpen = false, onImportOpenChange }: { rows: CustomerListRow[]; groups: string[]; onOpen: (id: number) => void; onImport: (rows: Record<string, string>[]) => void; importOpen?: boolean; onImportOpenChange?: (open: boolean) => void }) {
  return (
    <div className="space-y-3">
      <ImportDrawer
        open={importOpen}
        onOpenChange={(o) => onImportOpenChange?.(o)}
        noun="customers"
        columns={[
          { key: "phone", header: "Phone", required: true, validate: (v) => phoneOk(v) ?? (rows.some((r) => r.phone.replace(/\D/g, "").endsWith(v.replace(/\D/g, "").slice(-9))) ? "A customer with this number exists." : undefined) },
          { key: "name", header: "Name", required: true, validate: (v) => (v.trim() ? undefined : "Name is empty.") },
          { key: "email", header: "Email", validate: (v) => (!v || /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(v) ? undefined : "Not an email address.") },
          { key: "group", header: "Group", validate: (v) => (!v || groups.includes(v.trim()) ? undefined : `Not a customer group: ${groups.join(", ")}.`) },
        ]}
        template={"Phone,Name,Email,Group\n0712345678,Jane Doe,,Loyalty\n"}
        onImport={onImport}
      />
      <ListTable
        rows={rows}
        exports={csvExport<CustomerListRow>("customers", ["Name", "Type", "Group", "Phone", "Balance", "Credit limit", "Last visit"], (r) => [r.name, r.kind, r.group ?? "", r.phone, r.balance.toFixed(2), r.creditLimit.toFixed(2), r.lastVisit])}
        rowKey={(r) => String(r.id)}
        search={{ placeholder: "Name or phone", text: (r) => `${r.name} ${r.phone}` }}
        filters={[
          { label: "Group", all: "All groups", value: (r) => r.group ?? "No group" },
          { label: "Type", all: "Individuals and companies", value: (r) => r.kind },
        ]}
        cols={[
          { key: "n", header: "Customer", cell: (r) => (<button type="button" className="cursor-pointer text-left font-medium text-primary underline-offset-4 hover:underline" onClick={() => onOpen(r.id)}>{r.name}<span className="block text-xs font-normal text-muted-foreground">{r.kind}{r.group ? ` · ${r.group}` : ""}</span></button>) },
          { key: "p", header: "Phone", cell: (r) => <span className="tabular-nums">{r.phone}</span> },
          { key: "b", header: "Owes", numeric: true, cell: (r) => (r.balance ? <span className={cn(r.creditLimit && r.balance > r.creditLimit && "font-medium text-status-error-text")}>{kes(r.balance)}</span> : "–"), total: (s) => kes(s.reduce((t, r) => t + r.balance, 0)) },
          { key: "l", header: "Limit", numeric: true, cell: (r) => (r.creditLimit ? kes(r.creditLimit) : "Cash only") },
          { key: "v", header: "Last visit", cell: (r) => r.lastVisit },
        ]}
        totalsLabel={(s) => count(s.length, "customer")}
      />
    </div>
  );
}

/* ------------------------------------ SU-02 Suppliers ------------------------------------ */

export type SupplierListRow = { id: number; name: string; kraPin: string; contact: string; phone: string; owed: number; termsDays: number; overdue: number };

export function SuppliersList({ rows, onOpen, onStatement, onImport, importOpen = false, onImportOpenChange }: { rows: SupplierListRow[]; onOpen: (id: number) => void; onStatement: (id: number) => void; onImport: (rows: Record<string, string>[]) => void; importOpen?: boolean; onImportOpenChange?: (open: boolean) => void }) {
  return (
    <div className="space-y-3">
      <ImportDrawer
        open={importOpen}
        onOpenChange={(o) => onImportOpenChange?.(o)}
        noun="suppliers"
        columns={[
          { key: "kraPin", header: "KRA PIN", required: true, validate: (v) => (/^[AP]\d{9}[A-Z]$/.test(v.trim().toUpperCase()) ? (rows.some((r) => r.kraPin === v.trim().toUpperCase()) ? "A supplier with this PIN exists." : undefined) : "Not a KRA PIN.") },
          { key: "name", header: "Name", required: true, validate: (v) => (v.trim() ? undefined : "Name is empty.") },
          { key: "phone", header: "Phone" },
          { key: "terms", header: "Terms days", validate: (v) => (!v || (/^\d+$/.test(v) && Number(v) <= 180) ? undefined : "0 to 180 days.") },
        ]}
        template={"KRA PIN,Name,Phone,Terms days\nP051234567K,Example Ltd,020 444 5000,30\n"}
        onImport={onImport}
      />
      <ListTable
        rows={rows}
        exports={csvExport<SupplierListRow>("suppliers", ["Name", "KRA PIN", "Contact", "Phone", "We owe", "Terms (days)"], (r) => [r.name, r.kraPin, r.contact, r.phone, r.owed.toFixed(2), r.termsDays])}
        rowKey={(r) => String(r.id)}
        search={{ placeholder: "Name, PIN or contact", text: (r) => `${r.name} ${r.kraPin} ${r.contact}` }}
        cols={[
          { key: "n", header: "Supplier", cell: (r) => (<button type="button" className="cursor-pointer text-left font-medium text-primary underline-offset-4 hover:underline" onClick={() => onOpen(r.id)}>{r.name}<span className="block font-mono text-xs font-normal text-muted-foreground">{r.kraPin}</span></button>) },
          { key: "c", header: "Contact", cell: (r) => (<>{r.contact}<span className="block text-xs text-muted-foreground tabular-nums">{formatPhone(r.phone)}</span></>) },
          { key: "t", header: "Terms", cell: (r) => (r.termsDays ? `${r.termsDays} days` : "On delivery") },
          { key: "o", header: "We owe", numeric: true, cell: (r) => (<>{kes(r.owed)}{r.overdue ? <span className="block text-xs font-medium text-status-error-text">{kes(r.overdue)} overdue</span> : null}</>), total: (s) => kes(s.reduce((t, r) => t + r.owed, 0)) },
          { key: "s", header: "", cell: (r) => <Button size="sm" variant="ghost" onClick={() => onStatement(r.id)}>Statement</Button> },
        ]}
        totalsLabel={(s) => count(s.length, "supplier")}
      />
    </div>
  );
}

/* ------------------------------------ HR-01 Employees ------------------------------------ */

export type EmployeeListRow = { id: string; number: string; name: string; role: string; type: "Permanent" | "Contract" | "Casual" | "Piece rate"; branch: string; pay: string; active: boolean };

export function EmployeesList({ rows, onOpen, onToggleActive, onImport, importOpen = false, onImportOpenChange }: { rows: EmployeeListRow[]; onOpen: (id: string) => void; onToggleActive: (id: string) => void; onImport: (rows: Record<string, string>[]) => void; importOpen?: boolean; onImportOpenChange?: (open: boolean) => void }) {
  return (
    <div className="space-y-3">
      <ImportDrawer
        open={importOpen}
        onOpenChange={(o) => onImportOpenChange?.(o)}
        noun="employees"
        columns={[
          { key: "number", header: "Staff number", required: true, validate: (v) => (rows.some((r) => r.number === v.trim()) ? "This staff number exists." : v.trim() ? undefined : "Empty.") },
          { key: "name", header: "Name", required: true, validate: (v) => (v.trim() ? undefined : "Name is empty.") },
          { key: "kraPin", header: "KRA PIN", required: true, validate: (v) => (/^A\d{9}[A-Z]$/.test(v.trim().toUpperCase()) ? undefined : "An individual's KRA PIN starts with A.") },
          { key: "type", header: "Type", required: true, validate: (v) => (["Permanent", "Contract", "Casual", "Piece rate"].includes(v.trim()) ? undefined : "Permanent, Contract, Casual or Piece rate.") },
        ]}
        template={"Staff number,Name,KRA PIN,Type\nEMP-010,Jane Doe,A012345678Z,Permanent\n"}
        onImport={onImport}
      />
      <ListTable
        rows={rows}
        exports={csvExport<EmployeeListRow>("employees", ["Staff number", "Name", "Role", "Type", "Branch", "Pay", "Status"], (r) => [r.number, r.name, r.role, r.type, r.branch, r.pay, r.active ? "Active" : "Deactivated"])}
        rowKey={(r) => r.id}
        search={{ placeholder: "Name or staff number", text: (r) => `${r.name} ${r.number}` }}
        filters={[
          { label: "Branch", all: "All branches", value: (r) => r.branch },
          { label: "Type", all: "All types", value: (r) => r.type },
          { label: "Status", all: "Active and deactivated", value: (r) => (r.active ? "Active" : "Deactivated") },
        ]}
        cols={[
          { key: "n", header: "Employee", cell: (r) => (<button type="button" className={cn("cursor-pointer text-left font-medium underline-offset-4 hover:underline", r.active ? "text-primary" : "text-muted-foreground")} onClick={() => onOpen(r.id)}>{r.name}<span className="block font-mono text-xs font-normal text-muted-foreground">{r.number}</span></button>) },
          { key: "r", header: "Role and type", cell: (r) => (<>{r.role}<span className="block text-xs text-muted-foreground">{r.type}</span></>) },
          { key: "b", header: "Branch", cell: (r) => r.branch },
          { key: "p", header: "Pay", cell: (r) => <span className="text-xs">{r.pay}</span> },
          { key: "s", header: "Status", cell: (r) => <span className={cn("rounded px-1.5 py-0.5 text-[11px] font-medium", r.active ? "bg-status-success-bg text-status-success-text" : "bg-muted text-muted-foreground")}>{r.active ? "Active" : "Deactivated"}</span> },
          { key: "a", header: "", cell: (r) => <Button size="sm" variant="ghost" onClick={() => onToggleActive(r.id)}>{r.active ? "Deactivate" : "Reactivate"}</Button> },
        ]}
      />
    </div>
  );
}

/* ------------------------------------ CU-09 Schemes ------------------------------------ */

export type Scheme = { id: string; name: string; kind: "Insurance" | "Medical scheme" | "Corporate"; copayPct: string; defaultLimit: string; claimWithinDays: string; active: boolean; members: number };

export function schemeProblems(s: Scheme, all: Scheme[]) {
  const p: string[] = [];
  if (!s.name.trim()) p.push("Name the scheme.");
  else if (all.some((x) => x.id !== s.id && x.name.trim().toLowerCase() === s.name.trim().toLowerCase())) p.push("Another scheme has this name.");
  if (!/^\d+(\.\d+)?$/.test(s.copayPct) || Number(s.copayPct) > 100) p.push("Co-pay is 0 to 100%.");
  if (s.defaultLimit && !/^\d+(\.\d{1,2})?$/.test(s.defaultLimit.replace(/,/g, ""))) p.push("Limit is an amount.");
  if (!/^\d+$/.test(s.claimWithinDays) || Number(s.claimWithinDays) < 1) p.push("Claim deadline in days, at least 1.");
  return p;
}

/**
 * CU-09: the schemes customers can belong to. Co-pay is what the member pays at the till; the default limit
 * pre-fills each new member's cover; the claim deadline drives the "submit before" date on claims (AC-13).
 * A scheme with members can be deactivated (no new members or sales on it) but not deleted.
 */
export function SchemesManager({ schemes, onChange }: { schemes: Scheme[]; onChange: (s: Scheme[]) => void }) {
  const set = (id: string, patch: Partial<Scheme>) => onChange(schemes.map((s) => (s.id === id ? { ...s, ...patch } : s)));
  return (
    <div className="space-y-3">
      <div className="overflow-x-auto rounded-md border border-[var(--color-border-panel)] bg-card">
        <table className="w-full min-w-[820px] text-sm">
          <thead className="bg-[var(--color-bg-surface-subtle)] text-left text-xs text-muted-foreground">
            <tr>
              <th className="px-2 py-2 font-medium">Scheme</th>
              <th className="w-40 px-2 py-2 font-medium">Kind</th>
              <th className="w-24 px-2 py-2 text-right font-medium">Co-pay %</th>
              <th className="w-32 px-2 py-2 text-right font-medium">Default limit</th>
              <th className="w-28 px-2 py-2 text-right font-medium">Claim within (days)</th>
              <th className="w-28 px-2 py-2 font-medium">Members</th>
              <th className="w-24" />
            </tr>
          </thead>
          <tbody className="divide-y divide-[var(--color-border-subtle)]">
            {schemes.map((s) => {
              const pr = schemeProblems(s, schemes);
              return (
                <tr key={s.id} className={cn("align-top", !s.active && "text-muted-foreground")}>
                  <td className="px-2 py-1.5">
                    <Input aria-label="Scheme name" value={s.name} onChange={(e) => set(s.id, { name: e.target.value })} aria-invalid={pr.length > 0} />
                    {pr.length ? <span className="mt-0.5 block text-xs text-status-error-text">{pr.join(" ")}</span> : null}
                  </td>
                  <td className="px-2 py-1.5">
                    <NativeSelect aria-label={`${s.name} kind`} value={s.kind} onChange={(e) => set(s.id, { kind: e.target.value as Scheme["kind"] })}>
                      <NativeSelectOption>Insurance</NativeSelectOption>
                      <NativeSelectOption>Medical scheme</NativeSelectOption>
                      <NativeSelectOption>Corporate</NativeSelectOption>
                    </NativeSelect>
                  </td>
                  <td className="px-2 py-1.5">
                    <Input aria-label={`${s.name} co-pay`} className="text-right tabular-nums" inputMode="decimal" value={s.copayPct} onChange={(e) => set(s.id, { copayPct: e.target.value })} />
                  </td>
                  <td className="px-2 py-1.5">
                    <Input aria-label={`${s.name} default limit`} className="text-right tabular-nums" inputMode="decimal" placeholder="No limit" value={s.defaultLimit} onChange={(e) => set(s.id, { defaultLimit: e.target.value })} />
                  </td>
                  <td className="px-2 py-1.5">
                    <Input aria-label={`${s.name} claim deadline`} className="text-right tabular-nums" inputMode="numeric" value={s.claimWithinDays} onChange={(e) => set(s.id, { claimWithinDays: e.target.value })} />
                  </td>
                  <td className="px-2 py-2 text-xs">
                    {s.members.toLocaleString("en-US")} members
                    {!s.active ? <span className="block">Deactivated</span> : null}
                  </td>
                  <td className="px-1 py-1.5 text-right">
                    {s.members ? (
                      <Button size="sm" variant="ghost" onClick={() => set(s.id, { active: !s.active })}>
                        {s.active ? "Deactivate" : "Reactivate"}
                      </Button>
                    ) : (
                      <Button size="icon-sm" variant="ghost" aria-label={`Delete ${s.name}`} onClick={() => onChange(schemes.filter((x) => x.id !== s.id))}>
                        <Trash2Icon />
                      </Button>
                    )}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
      <Button size="sm" variant="outline" onClick={() => onChange([...schemes, { id: `s${Date.now()}`, name: "", kind: "Insurance", copayPct: "0", defaultLimit: "", claimWithinDays: "30", active: true, members: 0 }])}>
        <PlusIcon data-icon="inline-start" />
        Add scheme
      </Button>
    </div>
  );
}

/* ------------------------------------ AC-15 Quotation form ------------------------------------ */

export type QuoteLine = { id: number; product: string; qty: string; price: string; vat: 0 | 16 };
export type QuoteDraft = { customer: string; date: string; validDays: "7" | "14" | "30"; lines: QuoteLine[]; note: string };

export function quoteProblems(d: QuoteDraft) {
  const p: string[] = [];
  if (!d.customer.trim()) p.push("Who is the quotation for? A customer, or a name for a walk-in.");
  if (!d.lines.length) p.push("Add at least one item.");
  d.lines.forEach((l, i) => {
    if (!l.product.trim()) p.push(`Line ${i + 1}: choose the item.`);
    if (!/^[1-9]\d*$/.test(l.qty)) p.push(`Line ${i + 1}: quantity is a whole number above 0.`);
    if (!/^\d+(\.\d{1,2})?$/.test(l.price.replace(/,/g, "")) || Number(l.price.replace(/,/g, "")) <= 0) p.push(`Line ${i + 1}: enter the price.`);
  });
  return p;
}

/** AC-15: a quotation raised in Accounts (the till can also save one). It reserves no stock and takes no payment. */
export function QuotationForm({ d, onChange, customers, prices }: { d: QuoteDraft; onChange: (d: QuoteDraft) => void; customers: string[]; prices: Record<string, { price: number; vat: 0 | 16 }> }) {
  const set = <K extends keyof QuoteDraft>(k: K, v: QuoteDraft[K]) => onChange({ ...d, [k]: v });
  const setLine = (id: number, patch: Partial<QuoteLine>) => set("lines", d.lines.map((l) => (l.id === id ? { ...l, ...patch } : l)));
  const t = poTotals(d.lines.map((l) => ({ qty: l.qty, unitCost: l.price, vat: l.vat })));
  return (
    <div className="space-y-3">
      <div className="grid gap-3 sm:grid-cols-3">
        <div className="space-y-1">
          <label htmlFor="qf-cust" className="text-sm font-medium">
            Customer
          </label>
          <Input id="qf-cust" list="qf-customers" value={d.customer} onChange={(e) => set("customer", e.target.value)} placeholder="Customer or walk-in name" />
          <datalist id="qf-customers">
            {customers.map((c) => (
              <option key={c} value={c} />
            ))}
          </datalist>
        </div>
        <div className="space-y-1">
          <label htmlFor="qf-date" className="text-sm font-medium">
            Date
          </label>
          <Input id="qf-date" type="date" value={d.date} onChange={(e) => set("date", e.target.value)} />
        </div>
        <div className="space-y-1">
          <label htmlFor="qf-valid" className="text-sm font-medium">
            Valid for
          </label>
          <NativeSelect id="qf-valid" value={d.validDays} onChange={(e) => set("validDays", e.target.value as QuoteDraft["validDays"])}>
            <NativeSelectOption value="7">7 days</NativeSelectOption>
            <NativeSelectOption value="14">14 days</NativeSelectOption>
            <NativeSelectOption value="30">30 days</NativeSelectOption>
          </NativeSelect>
          <p className="text-xs text-muted-foreground">Until {d.date ? formatDate(addDays(d.date, Number(d.validDays))) : "–"}; then it expires by itself.</p>
        </div>
      </div>
      <div className="overflow-x-auto rounded-md border border-[var(--color-border-panel)] bg-card">
        <table className="w-full min-w-[600px] text-sm">
          <thead className="bg-[var(--color-bg-surface-subtle)] text-left text-xs text-muted-foreground">
            <tr>
              <th className="px-2 py-2 font-medium">Item</th>
              <th className="w-20 px-2 py-2 text-right font-medium">Qty</th>
              <th className="w-28 px-2 py-2 text-right font-medium">Price</th>
              <th className="w-20 px-2 py-2 font-medium">VAT</th>
              <th className="w-28 px-2 py-2 text-right font-medium">Total</th>
              <th className="w-10" />
            </tr>
          </thead>
          <tbody className="divide-y divide-[var(--color-border-subtle)]">
            {d.lines.map((l, i) => (
              <tr key={l.id}>
                <td className="px-2 py-1.5">
                  <Input
                    aria-label={`Line ${i + 1} item`}
                    list="qf-items"
                    value={l.product}
                    onChange={(e) => {
                      const known = prices[e.target.value];
                      setLine(l.id, known ? { product: e.target.value, price: String(known.price), vat: known.vat } : { product: e.target.value });
                    }}
                  />
                </td>
                <td className="px-2 py-1.5">
                  <Input aria-label={`Line ${i + 1} quantity`} className="text-right tabular-nums" inputMode="numeric" value={l.qty} onChange={(e) => setLine(l.id, { qty: e.target.value })} />
                </td>
                <td className="px-2 py-1.5">
                  <Input aria-label={`Line ${i + 1} price`} className="text-right tabular-nums" inputMode="decimal" value={l.price} onChange={(e) => setLine(l.id, { price: e.target.value })} />
                </td>
                <td className="px-2 py-2 text-xs">{l.vat ? "16%" : "Exempt"}</td>
                <td className="px-2 py-2 text-right tabular-nums">{kes((Number(l.qty) || 0) * (Number(l.price.replace(/,/g, "")) || 0) * (1 + l.vat / 100))}</td>
                <td className="px-1 py-1.5">
                  <Button size="icon-sm" variant="ghost" aria-label={`Remove line ${i + 1}`} onClick={() => set("lines", d.lines.filter((x) => x.id !== l.id))}>
                    <Trash2Icon />
                  </Button>
                </td>
              </tr>
            ))}
          </tbody>
          <tfoot className="border-t-2 border-[var(--color-border-panel)]">
            <tr>
              <td colSpan={2} className="px-2 py-1.5">
                <Button size="sm" variant="ghost" onClick={() => set("lines", [...d.lines, { id: Math.max(0, ...d.lines.map((x) => x.id)) + 1, product: "", qty: "1", price: "", vat: 0 }])}>
                  <PlusIcon data-icon="inline-start" />
                  Add item
                </Button>
              </td>
              <td colSpan={2} className="px-2 py-1.5 text-right text-xs text-muted-foreground">
                Before VAT {kes(t.subtotal)} · VAT {kes(t.vat)}
              </td>
              <td className="px-2 py-1.5 text-right font-semibold tabular-nums">{kes(t.total)}</td>
              <td />
            </tr>
          </tfoot>
        </table>
        <datalist id="qf-items">
          {Object.keys(prices).map((p) => (
            <option key={p} value={p} />
          ))}
        </datalist>
      </div>
      <div className="space-y-1">
        <label htmlFor="qf-note" className="text-sm font-medium">
          Note on the quotation (optional)
        </label>
        <Input id="qf-note" value={d.note} onChange={(e) => set("note", e.target.value)} placeholder="e.g. Prices include delivery within Nairobi" />
      </div>
    </div>
  );
}

/* ------------------------------------ AC-18 Asset form ------------------------------------ */

export type AssetDraft = { code: string; name: string; category: string; location: string; qty: string; model: string; serial: string; bought: string; price: string; purchaseType: "Bought outright" | "Hire purchase" | "Leased" | "Donated"; ratePct: string };

export function assetProblems(a: AssetDraft, codes: string[], today: string) {
  const p: Partial<Record<keyof AssetDraft, string>> = {};
  if (!a.code.trim()) p.code = "Every asset needs a tag code.";
  else if (codes.includes(a.code.trim().toUpperCase())) p.code = "Another asset has this code.";
  if (!a.name.trim()) p.name = "Name the asset.";
  if (!a.category) p.category = "Choose a category.";
  if (!a.location) p.location = "Where is it kept?";
  if (!/^[1-9]\d*$/.test(a.qty)) p.qty = "A whole number, at least 1.";
  if (Number(a.qty) > 1 && a.serial.trim()) p.serial = "A serial number belongs to one item. Record identical items without one, or add them one by one.";
  if (!a.bought) p.bought = "Enter the purchase date.";
  else if (a.bought > today) p.bought = "The purchase date is in the future.";
  if (!/^\d+(\.\d{1,2})?$/.test(a.price.replace(/,/g, ""))) p.price = a.purchaseType === "Donated" ? "Enter its fair value." : "Enter the price paid.";
  if (!/^\d+(\.\d+)?$/.test(a.ratePct) || Number(a.ratePct) > 100) p.ratePct = "Yearly depreciation is 0 to 100%.";
  return p;
}

/** AC-18: an asset's register entry. The preview shows what depreciation will post to the ledger each month. */
export function AssetForm({ a, onChange, categories, locations, problems, show }: { a: AssetDraft; onChange: (a: AssetDraft) => void; categories: { name: string; rate: number }[]; locations: string[]; problems: Partial<Record<keyof AssetDraft, string>>; show: boolean }) {
  const P = show ? problems : {};
  const set = <K extends keyof AssetDraft>(k: K, v: AssetDraft[K]) => onChange({ ...a, [k]: v });
  const f = (k: keyof AssetDraft, label: string, node: React.ReactNode, hint?: string) => (
    <div className="space-y-1" data-invalid={!!P[k] || undefined}>
      <label htmlFor={`as-${k}`} className="text-sm font-medium">
        {label}
      </label>
      {node}
      {P[k] ? <p className="text-xs text-status-error-text">{P[k]}</p> : hint ? <p className="text-xs text-muted-foreground">{hint}</p> : null}
    </div>
  );
  const input = (k: keyof AssetDraft, extra?: React.ComponentProps<typeof Input>) => <Input id={`as-${k}`} value={String(a[k])} onChange={(e) => set(k, e.target.value as never)} aria-invalid={!!P[k]} {...extra} />;
  const cost = (Number(a.price.replace(/,/g, "")) || 0) * (Number(a.qty) || 0);
  const monthly = Math.round(((cost * (Number(a.ratePct) || 0)) / 100 / 12) * 100) / 100;
  return (
    <div className="space-y-4">
      <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
        {f("code", "Tag code", input("code", { className: "font-mono uppercase", onChange: (e) => set("code", e.target.value.toUpperCase()) }), "Printed on the asset tag.")}
        {f("name", "Name", input("name"))}
        {f(
          "category",
          "Category",
          <NativeSelect
            id="as-category"
            value={a.category}
            onChange={(e) => {
              const c = categories.find((x) => x.name === e.target.value);
              onChange({ ...a, category: e.target.value, ratePct: c ? String(c.rate) : a.ratePct });
            }}
            aria-invalid={!!P.category}
          >
            <NativeSelectOption value="">Choose…</NativeSelectOption>
            {categories.map((c) => (
              <NativeSelectOption key={c.name}>{c.name}</NativeSelectOption>
            ))}
          </NativeSelect>,
          "Sets the usual depreciation rate.",
        )}
        {f(
          "location",
          "Location",
          <NativeSelect id="as-location" value={a.location} onChange={(e) => set("location", e.target.value)} aria-invalid={!!P.location}>
            <NativeSelectOption value="">Choose…</NativeSelectOption>
            {locations.map((l) => (
              <NativeSelectOption key={l}>{l}</NativeSelectOption>
            ))}
          </NativeSelect>,
        )}
        {f("qty", "Quantity", input("qty", { inputMode: "numeric", className: "tabular-nums" }))}
        {f("model", "Model (optional)", input("model"))}
        {f("serial", "Serial number (optional)", input("serial", { className: "font-mono" }))}
        {f(
          "purchaseType",
          "How it was acquired",
          <NativeSelect id="as-purchaseType" value={a.purchaseType} onChange={(e) => set("purchaseType", e.target.value as AssetDraft["purchaseType"])}>
            <NativeSelectOption>Bought outright</NativeSelectOption>
            <NativeSelectOption>Hire purchase</NativeSelectOption>
            <NativeSelectOption>Leased</NativeSelectOption>
            <NativeSelectOption>Donated</NativeSelectOption>
          </NativeSelect>,
        )}
        {f("bought", "Purchase date", input("bought", { type: "date" }))}
        {f("price", a.purchaseType === "Donated" ? "Fair value, each" : "Price paid, each", input("price", { inputMode: "decimal", className: "tabular-nums" }))}
        {f("ratePct", "Depreciation, % a year", input("ratePct", { inputMode: "decimal", className: "tabular-nums" }), "Straight line on cost.")}
      </div>
      <p className="rounded-md border border-[var(--color-border-panel)] bg-muted/30 px-3 py-2 text-sm">
        {cost > 0 && Number(a.ratePct) > 0 ? (
          <>
            Cost <strong className="tabular-nums">{kes(cost)}</strong>. Depreciation posts <strong className="tabular-nums">{kes(monthly)}</strong> a month to the ledger, fully written off in {Math.ceil(100 / Number(a.ratePct))} years.
          </>
        ) : (
          "Enter the price and rate to see the monthly depreciation."
        )}
      </p>
    </div>
  );
}
