"use client";

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

import { kraPinOk } from "@/components/medora/catalog-ops";
import { kes } from "@/components/medora/payroll";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select";
import { Textarea } from "@/components/ui/textarea";
import { addDays, daysBetween, formatDate } from "@/lib/format";
import { cn } from "@/lib/utils";

/*
 * Purchasing chain, first half: the supplier record (SU-01, SU-07), the purchase order with its approval
 * (IN-14) and what is already on order (IN-15). Receiving, GRNs and supplier bills are in goods-in.tsx.
 */

function Field({ id, label, problem, hint, wide, children }: { id: string; label: string; problem?: string; hint?: React.ReactNode; wide?: boolean; children: React.ReactNode }) {
  return (
    <div className={cn("space-y-1", wide && "sm:col-span-2")} data-invalid={!!problem || undefined}>
      <label htmlFor={id} className="text-sm font-medium">
        {label}
      </label>
      {children}
      {problem ? <p className="text-xs text-status-error-text">{problem}</p> : hint ? <p className="text-xs text-muted-foreground">{hint}</p> : null}
    </div>
  );
}

const money = (s: string) => Number(s.replace(/,/g, ""));
const isMoney = (s: string) => /^\d+(\.\d{1,2})?$/.test(s.replace(/,/g, ""));

/* ------------------------------------ Supplier record ------------------------------------ */

export type SupplierDraft = {
  name: string;
  kraPin: string;
  contact: string;
  phone: string;
  email: string;
  postal: string;
  address: string;
  city: string;
  country: string;
  bankName: string;
  bankBranch: string;
  accountNo: string;
  wht: boolean;
  creditLimit: string;
  termsDays: string;
  discount: string;
  leadDays: string;
};

export function supplierProblems(d: SupplierDraft, otherPins: string[]): Partial<Record<keyof SupplierDraft, string>> {
  const p: Partial<Record<keyof SupplierDraft, string>> = {};
  if (!d.name.trim()) p.name = "Enter the company name.";
  if (!d.kraPin) p.kraPin = "Suppliers need a KRA PIN: it's on every bill and the purchase VAT claim.";
  else if (!kraPinOk(d.kraPin)) p.kraPin = "A KRA PIN is A or P, 9 digits and a letter, e.g. P051234567K.";
  else if (otherPins.includes(d.kraPin)) p.kraPin = "Another supplier has this PIN. Open that record instead of adding a second one.";
  if (!d.contact.trim()) p.contact = "Who do we order from there?";
  if (!/^(\+?254|0)[17]\d{8}$/.test(d.phone.replace(/\s/g, "")) && !/^0[2-6]\d{7,8}$/.test(d.phone.replace(/\s/g, ""))) p.phone = "Enter a phone number, e.g. 0712 345 678 or 020 444 5000.";
  if (d.email && !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(d.email)) p.email = "This isn't an email address.";
  if (d.accountNo && !d.bankName.trim()) p.bankName = "Which bank is the account with?";
  if (d.accountNo && !/^\d{6,20}$/.test(d.accountNo.replace(/\s/g, ""))) p.accountNo = "Account numbers are 6 to 20 digits.";
  if (d.creditLimit && !isMoney(d.creditLimit)) p.creditLimit = "Enter an amount, e.g. 250000.";
  if (!/^\d+$/.test(d.termsDays) || Number(d.termsDays) > 180) p.termsDays = "Payment terms are 0 to 180 days (0 means pay on delivery).";
  if (d.discount && (!/^\d+(\.\d+)?$/.test(d.discount) || Number(d.discount) >= 100)) p.discount = "A percentage under 100.";
  if (d.leadDays && (!/^\d+$/.test(d.leadDays) || Number(d.leadDays) > 120)) p.leadDays = "Whole days, up to 120.";
  return p;
}

const SUPPLIER_SECTIONS: { title: string; keys: (keyof SupplierDraft)[] }[] = [
  { title: "Company", keys: ["name", "kraPin", "postal", "address", "city", "country"] },
  { title: "Contact", keys: ["contact", "phone", "email"] },
  { title: "Bank and tax", keys: ["bankName", "bankBranch", "accountNo", "wht"] },
  { title: "Terms", keys: ["creditLimit", "termsDays", "discount", "leadDays"] },
];

/** SU-01 and SU-07. Sections, each counting its problems, so a long form says where to look. */
export function SupplierForm({ d, onChange, problems, today }: { d: SupplierDraft; onChange: (d: SupplierDraft) => void; problems: Partial<Record<keyof SupplierDraft, string>>; today: string }) {
  const set = <K extends keyof SupplierDraft>(k: K, v: SupplierDraft[K]) => onChange({ ...d, [k]: v });
  const input = (k: keyof SupplierDraft, extra?: React.ComponentProps<typeof Input>) => <Input id={`sf-${k}`} value={String(d[k])} onChange={(e) => set(k, e.target.value as never)} aria-invalid={!!problems[k]} {...extra} />;
  const f = (k: keyof SupplierDraft, label: string, node: React.ReactNode, hint?: React.ReactNode, wide?: boolean) => (
    <Field id={`sf-${k}`} label={label} problem={problems[k]} hint={hint} wide={wide}>
      {node}
    </Field>
  );
  const terms = Number(d.termsDays);
  const count = (keys: (keyof SupplierDraft)[]) => keys.filter((k) => problems[k]).length;
  return (
    <div className="space-y-6">
      {SUPPLIER_SECTIONS.map((s) => (
        <fieldset key={s.title} className="space-y-3">
          <legend className="flex items-center gap-2 text-sm font-semibold">
            {s.title}
            {count(s.keys) ? <span className="rounded bg-status-error-bg px-1.5 text-xs font-medium text-status-error-text">{count(s.keys)} to fix</span> : null}
          </legend>
          <div className="grid gap-4 sm:grid-cols-2">
            {s.title === "Company" ? (
              <>
                {f("name", "Company name", input("name"))}
                {f("kraPin", "KRA PIN", input("kraPin", { className: "font-mono uppercase", onChange: (e) => set("kraPin", e.target.value.toUpperCase().replace(/\s/g, "")) }), "Printed on their bills; needed to claim purchase VAT.")}
                {f("postal", "Postal address", input("postal"))}
                {f("address", "Physical address", input("address"))}
                {f("city", "Town or city", input("city"))}
                {f("country", "Country", input("country"))}
              </>
            ) : s.title === "Contact" ? (
              <>
                {f("contact", "Contact person", input("contact"))}
                {f("phone", "Phone", input("phone", { inputMode: "tel" }))}
                {f("email", "Email for orders", input("email", { type: "email" }), "Approved purchase orders are emailed here.", true)}
              </>
            ) : s.title === "Bank and tax" ? (
              <>
                {f("bankName", "Bank", input("bankName"))}
                {f("bankBranch", "Branch", input("bankBranch"))}
                {f("accountNo", "Account number", input("accountNo", { inputMode: "numeric", className: "font-mono" }), "Payments go to this account; changing it later needs approval.")}
                <div className="flex items-start gap-2 self-end pb-1">
                  <Checkbox id="sf-wht" checked={d.wht} onCheckedChange={(v) => set("wht", !!v)} />
                  <label htmlFor="sf-wht" className="text-sm">
                    Deduct withholding tax
                    <span className="block text-xs text-muted-foreground">For services they bill. The tax is kept back from each payment and remitted to KRA.</span>
                  </label>
                </div>
              </>
            ) : (
              <>
                {f("creditLimit", "Credit limit (KES)", input("creditLimit", { inputMode: "decimal", className: "tabular-nums" }), "Most we may owe them at once. Blank for no limit.")}
                {f("termsDays", "Payment terms (days)", input("termsDays", { inputMode: "numeric", className: "tabular-nums" }), Number.isFinite(terms) && /^\d+$/.test(d.termsDays) ? (terms === 0 ? "Pay on delivery." : `A bill dated ${formatDate(today)} falls due ${formatDate(addDays(today, terms))}.`) : undefined)}
                {f("discount", "Agreed discount (%)", input("discount", { inputMode: "decimal", className: "tabular-nums" }), "Applied to new order lines; can be changed per line.")}
                {f("leadDays", "Delivery lead time (days)", input("leadDays", { inputMode: "numeric", className: "tabular-nums" }), "Used by reorder suggestions to order early enough.")}
              </>
            )}
          </div>
        </fieldset>
      ))}
    </div>
  );
}

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

export type PoDraftLine = { id: number; product: string; qty: string; unitCost: string; vat: 0 | 16 };
export type PoDraft = { supplier: string; supplierRef: string; orderDate: string; deadline: string; deliverTo: string; notes: string; lines: PoDraftLine[] };

export function poTotals(lines: { qty: number | string; unitCost: number | string; vat: number }[]) {
  let sub = 0;
  let vat = 0;
  for (const l of lines) {
    const q = Number(l.qty) || 0;
    const c = Number(String(l.unitCost).replace(/,/g, "")) || 0;
    sub += q * c;
    vat += (q * c * l.vat) / 100;
  }
  const r = (n: number) => Math.round(n * 100) / 100;
  return { subtotal: r(sub), vat: r(vat), total: r(sub + vat) };
}

export function poProblems(d: PoDraft): string[] {
  const p: string[] = [];
  if (!d.supplier) p.push("Choose the supplier.");
  if (!d.deliverTo) p.push("Choose where the goods are to be delivered.");
  if (!d.deadline) p.push("Set the date the goods are needed by.");
  else if (d.deadline < d.orderDate) p.push(`The needed-by date is before the order date (${formatDate(d.orderDate)}).`);
  if (!d.lines.length) p.push("Add at least one product.");
  const seen = new Set<string>();
  d.lines.forEach((l, i) => {
    const n = `Line ${i + 1}`;
    if (!l.product.trim()) p.push(`${n}: choose a product.`);
    else if (seen.has(l.product.trim().toLowerCase())) p.push(`${n}: ${l.product} is already on this order; change the quantity on the first line instead.`);
    seen.add(l.product.trim().toLowerCase());
    if (!/^[1-9]\d*$/.test(l.qty)) p.push(`${n}: quantity is a whole number above 0.`);
    if (!isMoney(l.unitCost) || money(l.unitCost) <= 0) p.push(`${n}: enter the unit cost.`);
  });
  return p;
}

/** IN-14: header and lines. The number is assigned when saved, never typed, so it can't clash. */
/** `products`: names offered as each line is typed (a line must name a product exactly). */
export function PurchaseOrderForm({ d, onChange, suppliers, locations, lastCosts, tried, products = [] }: { d: PoDraft; onChange: (d: PoDraft) => void; suppliers: { name: string; leadDays: number }[]; locations: string[]; lastCosts: Record<string, number>; tried: boolean; products?: string[] }) {
  const set = <K extends keyof PoDraft>(k: K, v: PoDraft[K]) => onChange({ ...d, [k]: v });
  const setLine = (id: number, patch: Partial<PoDraftLine>) => set("lines", d.lines.map((l) => (l.id === id ? { ...l, ...patch } : l)));
  const t = poTotals(d.lines.map((l) => ({ qty: l.qty, unitCost: l.unitCost, vat: l.vat })));
  const sup = suppliers.find((s) => s.name === d.supplier);
  const lead = sup && d.deadline ? daysBetween(d.orderDate, d.deadline) : null;
  return (
    <div className="space-y-4">
      {products.length ? (
        <datalist id="po-products">
          {products.map((p) => (
            <option key={p} value={p} />
          ))}
        </datalist>
      ) : null}
      <div className="grid gap-4">
        <Field id="po-no" label="Order number">
          <Input id="po-no" value="Assigned when saved" disabled />
        </Field>
        <Field id="po-supplier" label="Supplier">
          <NativeSelect id="po-supplier" value={d.supplier} onChange={(e) => set("supplier", e.target.value)} aria-invalid={tried && !d.supplier}>
            <NativeSelectOption value="">Choose…</NativeSelectOption>
            {suppliers.map((s) => (
              <NativeSelectOption key={s.name}>{s.name}</NativeSelectOption>
            ))}
          </NativeSelect>
        </Field>
        <Field id="po-ref" label="Supplier's reference (optional)" hint="Their quote or proforma number.">
          <Input id="po-ref" value={d.supplierRef} onChange={(e) => set("supplierRef", e.target.value)} />
        </Field>
        <Field id="po-date" label="Order date">
          <Input id="po-date" type="date" value={d.orderDate} onChange={(e) => set("orderDate", e.target.value)} />
        </Field>
        <Field
          id="po-deadline"
          label="Needed by"
          hint={sup && sup.leadDays > 0 ? (lead != null && lead < sup.leadDays ? <span className="text-status-warning-text">{d.supplier} usually takes {sup.leadDays} days; this allows {lead}.</span> : `${d.supplier} usually delivers in ${sup.leadDays} days.`) : undefined /* no lead time recorded: say nothing rather than "0 days" */}
        >
          <Input id="po-deadline" type="date" value={d.deadline} min={d.orderDate} onChange={(e) => set("deadline", e.target.value)} aria-invalid={tried && (!d.deadline || d.deadline < d.orderDate)} />
        </Field>
        <Field id="po-deliver" label="Deliver to">
          <NativeSelect id="po-deliver" value={d.deliverTo} onChange={(e) => set("deliverTo", e.target.value)} aria-invalid={tried && !d.deliverTo}>
            <NativeSelectOption value="">Choose…</NativeSelectOption>
            {locations.map((l) => (
              <NativeSelectOption key={l}>{l}</NativeSelectOption>
            ))}
          </NativeSelect>
        </Field>
      </div>

      <div className="overflow-x-auto rounded-md border border-[var(--color-border-panel)] bg-card">
        <table className="w-full min-w-[640px] 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">Product</th>
              <th className="w-24 px-2 py-2 text-right font-medium">Quantity</th>
              <th className="w-32 px-2 py-2 text-right font-medium">Unit cost</th>
              <th className="w-24 px-2 py-2 font-medium">VAT</th>
              <th className="w-32 px-2 py-2 text-right font-medium">Line total</th>
              <th className="w-10" />
            </tr>
          </thead>
          <tbody className="divide-y divide-[var(--color-border-subtle)]">
            {d.lines.map((l, i) => {
              const last = lastCosts[l.product];
              const cost = money(l.unitCost);
              const up = last && cost && cost > last * 1.1;
              return (
                <tr key={l.id}>
                  <td className="px-2 py-1.5">
                    <Input aria-label={`Line ${i + 1} product`} list={products.length ? "po-products" : undefined} value={l.product} onChange={(e) => setLine(l.id, { 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} unit cost`} className="text-right tabular-nums" inputMode="decimal" value={l.unitCost} onChange={(e) => setLine(l.id, { unitCost: e.target.value })} />
                    {last ? <span className={cn("block text-right text-[11px]", up ? "text-status-warning-text" : "text-muted-foreground")}>{up ? `Up from ${kes(last)} last time` : `Last ${kes(last)}`}</span> : null}
                  </td>
                  <td className="px-2 py-1.5">
                    <NativeSelect aria-label={`Line ${i + 1} VAT`} value={String(l.vat)} onChange={(e) => setLine(l.id, { vat: Number(e.target.value) as 0 | 16 })}>
                      <NativeSelectOption value="16">16%</NativeSelectOption>
                      <NativeSelectOption value="0">Exempt</NativeSelectOption>
                    </NativeSelect>
                  </td>
                  <td className="px-2 py-1.5 text-right tabular-nums">{kes((Number(l.qty) || 0) * (cost || 0))}</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)] text-sm">
            <tr>
              <td 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: "", unitCost: "", vat: 16 }])}>
                  <PlusIcon data-icon="inline-start" />
                  Add product
                </Button>
              </td>
              <td colSpan={3} className="px-2 py-1.5 text-right 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>
      </div>
      <Field id="po-notes" label="Note to the supplier (optional)">
        <Textarea id="po-notes" rows={2} value={d.notes} onChange={(e) => set("notes", e.target.value)} />
      </Field>
    </div>
  );
}

/* ------------------------------------ Approval (IN-14) ------------------------------------ */

export type PoStatus = "Draft" | "Awaiting approval" | "Approved" | "Sent" | "Partly received" | "Received" | "Rejected" | "Cancelled";

const STATUS_TONE: Record<PoStatus, string> = {
  Draft: "bg-muted text-muted-foreground",
  "Awaiting approval": "bg-status-warning-bg text-status-warning-text",
  Approved: "bg-status-success-bg text-status-success-text",
  Sent: "bg-status-info-bg text-status-info-text",
  "Partly received": "bg-status-warning-bg text-status-warning-text",
  Received: "bg-status-success-bg text-status-success-text",
  Rejected: "bg-status-error-bg text-status-error-text",
  Cancelled: "bg-muted text-muted-foreground",
};

export function PoStatusBadge({ status }: { status: PoStatus }) {
  return <span className={cn("rounded px-1.5 py-0.5 text-[11px] font-medium whitespace-nowrap", STATUS_TONE[status])}>{status}</span>;
}

/**
 * Orders must be approved before they go to the supplier. Nobody approves their own order, and an order
 * above the approver's limit says who must approve it instead. Rejecting needs a reason, which goes back
 * to whoever raised it.
 */
export function PoApproval({ number, supplier, total, raisedBy, raisedAt, viewer, viewerLimit, onDecide }: { number: string; supplier: string; total: number; raisedBy: string; raisedAt: string; viewer: string; viewerLimit: number; onDecide: (d: { approved: boolean; reason?: string }) => void }) {
  const [rejecting, setRejecting] = React.useState(false);
  const [reason, setReason] = React.useState("");
  const [tried, setTried] = React.useState(false);
  const own = viewer === raisedBy;
  const over = total > viewerLimit;
  const block = own ? `You raised this order, so someone else must approve it.` : over ? `This order is ${kes(total)}, above your approval limit of ${kes(viewerLimit)}. An Admin must approve it.` : null;
  return (
    <div className="space-y-3 rounded-md border border-[var(--color-border-panel)] p-4 bg-card">
      <div className="flex flex-wrap items-start justify-between gap-2">
        <div>
          <p className="font-medium">
            {number} · {supplier}
          </p>
          <p className="text-xs text-muted-foreground">
            Raised by {raisedBy}, {raisedAt}
          </p>
        </div>
        <div className="text-right">
          <PoStatusBadge status="Awaiting approval" />
          <p className="mt-1 font-semibold tabular-nums">{kes(total)}</p>
        </div>
      </div>
      {block ? <p className="rounded-md bg-muted px-3 py-2 text-sm">{block}</p> : null}
      {rejecting ? (
        <div className="space-y-2">
          <label htmlFor="po-reject" className="text-sm font-medium">
            Why is it rejected?
          </label>
          <Textarea id="po-reject" rows={2} value={reason} onChange={(e) => setReason(e.target.value)} aria-invalid={tried && !reason.trim()} placeholder="e.g. Order the 100s pack instead; cheaper per tablet" />
          {tried && !reason.trim() ? <p className="text-xs text-status-error-text">Say why, so {raisedBy} can fix and resubmit it.</p> : null}
          <div className="flex gap-2">
            <Button
              size="sm"
              variant="destructive"
              onClick={() => {
                setTried(true);
                if (reason.trim()) onDecide({ approved: false, reason: reason.trim() });
              }}
            >
              Reject order
            </Button>
            <Button size="sm" variant="ghost" onClick={() => setRejecting(false)}>
              Back
            </Button>
          </div>
        </div>
      ) : (
        <div className="flex flex-wrap gap-2">
          <Button size="sm" disabled={!!block} onClick={() => onDecide({ approved: true })}>
            Approve and send to {supplier}
          </Button>
          <Button size="sm" variant="outline" disabled={own} onClick={() => setRejecting(true)}>
            Reject…
          </Button>
        </div>
      )}
    </div>
  );
}

/* ------------------------------------ Pending orders (IN-15) ------------------------------------ */

export type OpenOrder = { number: string; supplier: string; status: PoStatus; deadline: string; lines: { product: string; ordered: number; received: number; unitCost: number }[] };

export const onOrder = (orders: OpenOrder[]) => {
  const m: Record<string, { qty: number; orders: string[] }> = {};
  for (const o of orders) {
    if (!["Approved", "Sent", "Partly received", "Awaiting approval"].includes(o.status)) continue;
    for (const l of o.lines) {
      const left = l.ordered - l.received;
      if (left <= 0) continue;
      m[l.product] ??= { qty: 0, orders: [] };
      m[l.product].qty += left;
      m[l.product].orders.push(o.number);
    }
  }
  return m;
};

/** IN-15: what's already on order, by order or by product, so nobody reorders what is on its way. */
export function PendingOrders({ orders, today }: { orders: OpenOrder[]; today: string }) {
  const [by, setBy] = React.useState<"order" | "product">("order");
  const open = orders.filter((o) => ["Awaiting approval", "Approved", "Sent", "Partly received"].includes(o.status));
  const products = Object.entries(onOrder(open)).sort((a, b) => a[0].localeCompare(b[0]));
  return (
    <div className="space-y-3">
      <div role="radiogroup" aria-label="Group by" className="inline-flex overflow-hidden rounded-md border border-[var(--color-border-panel)] text-sm bg-card">
        {(["order", "product"] as const).map((k) => (
          <button key={k} type="button" role="radio" aria-checked={by === k} onClick={() => setBy(k)} className={cn("cursor-pointer px-3 py-1.5", by === k ? "bg-[var(--color-bg-selected)] font-medium" : "text-muted-foreground hover:bg-muted")}>
            By {k}
          </button>
        ))}
      </div>
      <div className="overflow-x-auto rounded-md border border-[var(--color-border-panel)] bg-card">
        {by === "order" ? (
          <table className="w-full min-w-[620px] text-sm">
            <thead className="bg-[var(--color-bg-surface-subtle)] text-left text-xs text-muted-foreground">
              <tr>
                <th className="px-3 py-2 font-medium">Order</th>
                <th className="px-3 py-2 font-medium">Status</th>
                <th className="px-3 py-2 font-medium">Needed by</th>
                <th className="px-3 py-2 text-right font-medium">Lines outstanding</th>
                <th className="px-3 py-2 text-right font-medium">Still to come</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-[var(--color-border-subtle)]">
              {open.map((o) => {
                const left = o.lines.filter((l) => l.received < l.ordered);
                const value = left.reduce((s, l) => s + (l.ordered - l.received) * l.unitCost, 0);
                const late = o.deadline < today && o.status !== "Awaiting approval";
                return (
                  <tr key={o.number}>
                    <td className="px-3 py-2">
                      <span className="font-mono text-xs">{o.number}</span>
                      <span className="block text-xs text-muted-foreground">{o.supplier}</span>
                    </td>
                    <td className="px-3 py-2">
                      <PoStatusBadge status={o.status} />
                    </td>
                    <td className="px-3 py-2 whitespace-nowrap">
                      {formatDate(o.deadline)}
                      {late ? <span className="block text-xs font-medium text-status-error-text">{daysBetween(o.deadline, today)} {daysBetween(o.deadline, today) === 1 ? "day" : "days"} late</span> : null}
                    </td>
                    <td className="px-3 py-2 text-right tabular-nums">
                      {left.length} of {o.lines.length}
                    </td>
                    <td className="px-3 py-2 text-right tabular-nums">{kes(value)}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        ) : (
          <table className="w-full min-w-[480px] text-sm">
            <thead className="bg-[var(--color-bg-surface-subtle)] text-left text-xs text-muted-foreground">
              <tr>
                <th className="px-3 py-2 font-medium">Product</th>
                <th className="px-3 py-2 text-right font-medium">On order</th>
                <th className="px-3 py-2 font-medium">On orders</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-[var(--color-border-subtle)]">
              {products.map(([p, v]) => (
                <tr key={p}>
                  <td className="px-3 py-2">{p}</td>
                  <td className="px-3 py-2 text-right tabular-nums">{v.qty.toLocaleString("en-US")}</td>
                  <td className="px-3 py-2 font-mono text-xs">{v.orders.join(", ")}</td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>
    </div>
  );
}
