"use client";

import * as React from "react";
import { ChevronRightIcon } from "lucide-react";

import { kes } from "@/components/medora/payroll";
import { PrintLogo } from "@/components/medora/print";
import { VIZ_SEQ } from "@/components/medora/viz";
import { Button } from "@/components/ui/button";
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select";
import { count } from "@/lib/format";
import { cn } from "@/lib/utils";
import { Surface } from "./surface";

const n = (v: number) => v.toLocaleString("en-US");
const th = "px-3 py-2 font-medium";
const thR = "px-3 py-2 text-right font-medium";
const td = "px-3 py-2";
const tdR = "px-3 py-2 text-right tabular-nums";

/** One white container (data table spec §1); `toolbar` puts filters inside it, above the table. */
function Frame({ minWidth, toolbar, body, children }: { minWidth: string; toolbar?: React.ReactNode; body?: React.ReactNode; children: React.ReactNode }) {
  return (
    <div className="overflow-hidden rounded-md border border-[var(--color-border-panel)] bg-card">
      {toolbar ? <div className="flex flex-wrap items-center gap-2 border-b border-[var(--color-border-subtle)] p-3">{toolbar}</div> : null}
      {body ?? (
        <div className="overflow-x-auto">
          <table className={cn("w-full text-sm", minWidth)}>{children}</table>
        </div>
      )}
    </div>
  );
}

function Flag({ tone, children }: { tone: "error" | "warning" | "neutral"; children: React.ReactNode }) {
  return (
    <span className={cn("rounded px-1.5 py-0.5 text-[11px] font-medium whitespace-nowrap", tone === "error" ? "bg-status-error-bg text-status-error-text" : tone === "warning" ? "bg-status-warning-bg text-status-warning-text" : "bg-muted text-muted-foreground")}>
      {children}
    </span>
  );
}

/* --------------------------------- Branch comparison (RP-04) --------------------------------- */

export type CompareRow = { item: string; unit: string; reorder: number; soldInPeriod: number; qty: Record<string, number> };

/**
 * RP-04: each item's stock per branch, the total and the average across branches. A branch below the
 * item's reorder level is flagged in its own cell; an item with no sales anywhere in the period is dead
 * stock, flagged on the row. Flags are words, not colour alone.
 */
export function BranchComparison({ branches, rows, period }: { branches: string[]; rows: CompareRow[]; period: string }) {
  const [only, setOnly] = React.useState<"" | "low" | "dead">("");
  const isDead = (r: CompareRow) => r.soldInPeriod === 0 && Object.values(r.qty).some((q) => q > 0);
  const lowAt = (r: CompareRow) => branches.filter((b) => (r.qty[b] ?? 0) < r.reorder);
  const shown = rows.filter((r) => (only === "low" ? lowAt(r).length : only === "dead" ? isDead(r) : true));
  return (
    <div className="space-y-3">
      <Surface className="flex flex-wrap items-center justify-between gap-2">
        <p className="text-xs text-muted-foreground">
          Sales period for dead stock: {period}. {rows.filter(isDead).length} dead-stock items, {rows.filter((r) => lowAt(r).length).length} items low somewhere.
        </p>
        <NativeSelect aria-label="Show" value={only} onChange={(e) => setOnly(e.target.value as typeof only)}>
          <NativeSelectOption value="">All items</NativeSelectOption>
          <NativeSelectOption value="low">Low at a branch</NativeSelectOption>
          <NativeSelectOption value="dead">Dead stock</NativeSelectOption>
        </NativeSelect>
      </Surface>
      <Frame minWidth="min-w-[720px]">
        <thead className="bg-[var(--color-bg-surface-subtle)] text-left text-xs text-muted-foreground">
          <tr>
            <th className={th}>Item</th>
            {branches.map((b) => (
              <th key={b} className={thR}>
                {b}
              </th>
            ))}
            <th className={thR}>Total</th>
            <th className={thR}>Average</th>
          </tr>
        </thead>
        <tbody className="divide-y divide-[var(--color-border-subtle)]">
          {shown.map((r) => {
            const total = branches.reduce((s, b) => s + (r.qty[b] ?? 0), 0);
            return (
              <tr key={r.item}>
                <td className={td}>
                  <span className="font-medium">{r.item}</span>
                  <span className="mt-0.5 flex flex-wrap items-center gap-1.5 text-xs text-muted-foreground">
                    Reorder at {n(r.reorder)} {r.unit} · sold {n(r.soldInPeriod)}
                    {isDead(r) ? <Flag tone="warning">Dead stock</Flag> : null}
                  </span>
                </td>
                {branches.map((b) => {
                  const q = r.qty[b] ?? 0;
                  return (
                    <td key={b} className={tdR}>
                      <span className={cn(q < 0 && "text-status-error-text")}>{n(q)}</span>
                      {q <= 0 ? (
                        <span className="block">
                          <Flag tone="error">{q < 0 ? "Negative" : "Out"}</Flag>
                        </span>
                      ) : q < r.reorder ? (
                        <span className="block">
                          <Flag tone="warning">Low</Flag>
                        </span>
                      ) : null}
                    </td>
                  );
                })}
                <td className={cn(tdR, "font-semibold")}>{n(total)}</td>
                <td className={tdR}>{(total / branches.length).toLocaleString("en-US", { maximumFractionDigits: 1 })}</td>
              </tr>
            );
          })}
          {!shown.length ? (
            <tr>
              <td colSpan={branches.length + 3} className="px-3 py-8 text-center text-muted-foreground">
                No items match.
              </td>
            </tr>
          ) : null}
        </tbody>
      </Frame>
    </div>
  );
}

/* --------------------------------- Internal issues (IN-23) --------------------------------- */

export type IssueRecord = { no: string; date: string; from: string; to: string; staff: string; reference?: string; items: { name: string; qty: number; unitCost: number }[] };
const issueValue = (i: IssueRecord) => i.items.reduce((s, x) => s + x.qty * x.unitCost, 0);

/** IN-23: stock issued for internal use, filterable by source and destination; a row opens its items. */
export function InternalIssueReport({ issues }: { issues: IssueRecord[] }) {
  const [from, setFrom] = React.useState("");
  const [to, setTo] = React.useState("");
  const [open, setOpen] = React.useState<string | null>(null);
  const froms = [...new Set(issues.map((i) => i.from))];
  const tos = [...new Set(issues.map((i) => i.to))];
  const shown = issues.filter((i) => (!from || i.from === from) && (!to || i.to === to));
  return (
    <div className="space-y-3">
      <Frame
        minWidth="min-w-[640px]"
        toolbar={
          <>
              <NativeSelect aria-label="From location" value={from} onChange={(e) => setFrom(e.target.value)}>
                <NativeSelectOption value="">From any location</NativeSelectOption>
                {froms.map((f) => (
                  <NativeSelectOption key={f} value={f}>
                    {f}
                  </NativeSelectOption>
                ))}
              </NativeSelect>
              <NativeSelect aria-label="To" value={to} onChange={(e) => setTo(e.target.value)}>
                <NativeSelectOption value="">To anywhere</NativeSelectOption>
                {tos.map((f) => (
                  <NativeSelectOption key={f} value={f}>
                    {f}
                  </NativeSelectOption>
                ))}
              </NativeSelect>
          </>
        }
      >
        <thead className="bg-[var(--color-bg-surface-subtle)] text-left text-xs text-muted-foreground">
          <tr>
            <th className="w-8" />
            <th className={th}>Issue</th>
            <th className={th}>From → to</th>
            <th className={th}>Issued by</th>
            <th className={thR}>Items</th>
            <th className={thR}>Value at cost</th>
          </tr>
        </thead>
        {shown.map((i) => (
          <tbody key={i.no} className="border-t border-[var(--color-border-subtle)]">
            <tr className={cn(open === i.no && "bg-muted/30")}>
              <td className="px-2 py-2">
                <Button size="icon-sm" variant="ghost" aria-expanded={open === i.no} aria-label={`${open === i.no ? "Hide" : "Show"} items on ${i.no}`} onClick={() => setOpen(open === i.no ? null : i.no)}>
                  <ChevronRightIcon className={cn("transition-transform", open === i.no && "rotate-90")} />
                </Button>
              </td>
              <td className={td}>
                <span className="font-mono text-xs">{i.no}</span>
                <span className="block text-xs text-muted-foreground">
                  {i.date}
                  {i.reference ? ` · ${i.reference}` : ""}
                </span>
              </td>
              <td className={td}>
                {i.from} → {i.to}
              </td>
              <td className={td}>{i.staff}</td>
              <td className={tdR}>{i.items.length}</td>
              <td className={tdR}>{kes(issueValue(i))}</td>
            </tr>
            {open === i.no ? (
              <tr>
                <td />
                <td colSpan={5} className="px-3 pb-3">
                  <ul className="space-y-1 text-xs">
                    {i.items.map((x) => (
                      <li key={x.name} className="flex justify-between gap-3">
                        <span>
                          {x.qty} × {x.name} <span className="text-muted-foreground">at {kes(x.unitCost)}</span>
                        </span>
                        <span className="tabular-nums">{kes(x.qty * x.unitCost)}</span>
                      </li>
                    ))}
                  </ul>
                </td>
              </tr>
            ) : null}
          </tbody>
        ))}
        <tfoot className="border-t-2 border-[var(--color-border-panel)] bg-muted/30 font-semibold">
          <tr>
            <td colSpan={5} className={td}>
              {count(shown.length, "issue")} (not sales: no revenue, cost only)
            </td>
            <td className={tdR}>{kes(shown.reduce((s, i) => s + issueValue(i), 0))}</td>
          </tr>
        </tfoot>
      </Frame>
    </div>
  );
}

/* ------------------------------------ Transfers (IN-25) ------------------------------------ */

export type TransferLine = { item: string; unit: string; sent: number; received?: number; unitCost: number };
export type TransferRecord = {
  ref: string;
  date: string;
  from: string;
  to: string;
  sentBy: string;
  receivedBy?: string;
  receivedOn?: string;
  note?: string;
  shortNote?: string;
  lines: TransferLine[];
};

export const transferState = (t: TransferRecord) => (!t.receivedOn ? "In transit" : t.lines.some((l) => (l.received ?? 0) < l.sent) ? "Received short" : "Received");
const lostQty = (l: TransferLine) => (l.received == null ? 0 : Math.max(0, l.sent - l.received));
const sentValue = (t: TransferRecord) => t.lines.reduce((s, l) => s + l.sent * l.unitCost, 0);
const lostValue = (t: TransferRecord) => t.lines.reduce((s, l) => s + lostQty(l) * l.unitCost, 0);

/**
 * IN-25: the three transfer reports in one place. All transfers; Receivable (in transit to this branch,
 * waiting to be accepted); Lost (short receipts: what left one branch and never arrived, at cost).
 */
export function TransferReports({ transfers, branch, onPrint, toolbar, body }: { transfers: TransferRecord[]; branch: string; onPrint?: (ref: string) => void; toolbar?: React.ReactNode; body?: React.ReactNode }) {
  const [tab, setTab] = React.useState<"all" | "receivable" | "lost">("all");
  const receivable = transfers.filter((t) => t.to === branch && !t.receivedOn);
  const lost = transfers.filter((t) => lostValue(t) > 0);
  const rows = tab === "all" ? transfers : tab === "receivable" ? receivable : lost;
  const tabs = [
    { id: "all" as const, label: `All transfers (${transfers.length})` },
    { id: "receivable" as const, label: `Receivable at ${branch} (${receivable.length})` },
    { id: "lost" as const, label: `Lost in transit (${lost.length})` },
  ];
  return (
    <div className="space-y-3">
      <div role="tablist" aria-label="Transfer report" className="flex flex-wrap gap-1 border-b border-border">
        {tabs.map((t) => (
          <button
            key={t.id}
            type="button"
            role="tab"
            aria-selected={tab === t.id}
            className={cn("-mb-px cursor-pointer border-b-2 px-3 py-1.5 text-sm", tab === t.id ? "border-primary font-medium text-foreground" : "border-transparent text-muted-foreground hover:text-foreground")}
            onClick={() => setTab(t.id)}
          >
            {t.label}
          </button>
        ))}
      </div>
      <Frame minWidth="min-w-[700px]" toolbar={toolbar} body={body}>
        <thead className="bg-[var(--color-bg-surface-subtle)] text-left text-xs text-muted-foreground">
          <tr>
            <th className={th}>Transfer</th>
            <th className={th}>From → to</th>
            <th className={th}>Status</th>
            {tab === "lost" ? <th className={th}>What went missing</th> : <th className={th}>Lines</th>}
            <th className={thR}>{tab === "lost" ? "Lost at cost" : "Sent at cost"}</th>
            <th className="w-20" />
          </tr>
        </thead>
        <tbody className="divide-y divide-[var(--color-border-subtle)]">
          {rows.map((t) => {
            const st = transferState(t);
            return (
              <tr key={t.ref}>
                <td className={td}>
                  <span className="font-mono text-xs">{t.ref}</span>
                  <span className="block text-xs text-muted-foreground">
                    Sent {t.date} by {t.sentBy}
                  </span>
                </td>
                <td className={td}>
                  {t.from} → {t.to}
                </td>
                <td className={td}>
                  <Flag tone={st === "Received" ? "neutral" : st === "In transit" ? "warning" : "error"}>{st}</Flag>
                  {t.receivedOn ? (
                    <span className="mt-0.5 block text-xs text-muted-foreground">
                      {t.receivedOn} by {t.receivedBy}
                    </span>
                  ) : null}
                </td>
                <td className={cn(td, "text-xs")}>
                  {tab === "lost" ? (
                    <>
                      {t.lines
                        .filter((l) => lostQty(l) > 0)
                        .map((l) => `${lostQty(l)} of ${l.sent} ${l.unit} ${l.item}`)
                        .join("; ")}
                      {t.shortNote ? <span className="block text-muted-foreground">“{t.shortNote}”</span> : null}
                    </>
                  ) : (
                    `${t.lines.length} ${t.lines.length === 1 ? "item" : "items"}, ${n(t.lines.reduce((s, l) => s + l.sent, 0))} units`
                  )}
                </td>
                <td className={tdR}>{kes(tab === "lost" ? lostValue(t) : sentValue(t))}</td>
                <td className="px-2 py-2 text-right">
                  <Button size="sm" variant="ghost" onClick={() => onPrint?.(t.ref)}>
                    Print
                  </Button>
                </td>
              </tr>
            );
          })}
          {!rows.length ? (
            <tr>
              <td colSpan={6} className="px-3 py-8 text-center text-muted-foreground">
                {tab === "receivable" ? `Nothing on its way to ${branch}.` : tab === "lost" ? "Nothing lost in transit." : "No transfers in this period."}
              </td>
            </tr>
          ) : null}
        </tbody>
        {rows.length ? (
          <tfoot className="border-t-2 border-[var(--color-border-panel)] bg-muted/30 font-semibold">
            <tr>
              <td colSpan={4} className={td}>
                {tab === "lost" ? "Written off as lost in transit" : tab === "receivable" ? "Value on its way" : "Value transferred"}
              </td>
              <td className={tdR}>{kes(rows.reduce((s, t) => s + (tab === "lost" ? lostValue(t) : sentValue(t)), 0))}</td>
              <td />
            </tr>
          </tfoot>
        ) : null}
      </Frame>
    </div>
  );
}

/** IN-25 printable transfer document: one copy travels with the goods and comes back signed. */
export const TransferNote = React.forwardRef<HTMLDivElement, { transfer: TransferRecord; company: string; printedBy: string; printedAt: string }>(function TransferNote({ transfer: t, company, printedBy, printedAt }, ref) {
  const st = transferState(t);
  return (
    <div ref={ref} className="mx-auto box-border w-[210mm] bg-white p-[12mm] text-[9pt] leading-[1.35] text-black shadow-md print:w-auto print:p-0 print:shadow-none" aria-label={`Transfer note ${t.ref}`}>
      <header className="flex items-start justify-between gap-6">
        <div>
          <PrintLogo className="mb-2 h-[9mm]" />
          <p className="text-[10pt] font-bold">{company}</p>
        </div>
        <div className="text-right">
          <h1 className="text-[18pt] leading-none font-bold uppercase">Transfer note</h1>
          <p className="mt-2 inline-block border border-black px-2 py-0.5 font-bold uppercase">{st}</p>
          <dl className="mt-3 grid grid-cols-[auto_auto] justify-end gap-x-3 gap-y-0.5 text-left tabular-nums">
            <dt>Transfer no</dt>
            <dd className="font-semibold">{t.ref}</dd>
            <dt>Sent</dt>
            <dd>{t.date}</dd>
          </dl>
        </div>
      </header>
      <section className="mt-6 grid grid-cols-2 gap-6">
        <div className="border border-black p-2">
          <p className="text-[8pt] font-bold uppercase">From</p>
          <p className="font-semibold">{t.from}</p>
          <p>Sent by {t.sentBy}</p>
        </div>
        <div className="border border-black p-2">
          <p className="text-[8pt] font-bold uppercase">To</p>
          <p className="font-semibold">{t.to}</p>
          <p>{t.receivedBy ? `Received by ${t.receivedBy}, ${t.receivedOn}` : "Not yet received"}</p>
        </div>
      </section>
      <table className="mt-6 w-full border-collapse tabular-nums">
        <thead>
          <tr className="border-y-2 border-black text-left">
            <th className="py-1 pr-2">#</th>
            <th className="py-1 pr-2">Item</th>
            <th className="py-1 pr-2">Unit</th>
            <th className="py-1 pr-2 text-right">Sent</th>
            <th className="py-1 pr-2 text-right">Received</th>
            <th className="py-1 text-right">Short</th>
          </tr>
        </thead>
        <tbody>
          {t.lines.map((l, i) => (
            <tr key={l.item} className="border-b border-black/30">
              <td className="py-1 pr-2">{i + 1}</td>
              <td className="py-1 pr-2">{l.item}</td>
              <td className="py-1 pr-2">{l.unit}</td>
              <td className="py-1 pr-2 text-right">{n(l.sent)}</td>
              <td className="py-1 pr-2 text-right">{l.received == null ? "______" : n(l.received)}</td>
              <td className="py-1 text-right">{l.received == null ? "" : lostQty(l) ? n(lostQty(l)) : "–"}</td>
            </tr>
          ))}
        </tbody>
      </table>
      {t.note ? <p className="mt-3">Note: {t.note}</p> : null}
      {t.shortNote ? <p className="mt-1">Short received: {t.shortNote}</p> : null}
      <section className="mt-12 grid grid-cols-3 gap-6">
        {["Dispatched by", "Carried by", "Received by"].map((s) => (
          <div key={s}>
            <div className="h-10 border-b border-black" />
            <p className="mt-1">{s}: name, signature, date</p>
          </div>
        ))}
      </section>
      <footer className="mt-8 text-[7.5pt] text-black/70">
        Printed {printedAt} by {printedBy}. Count the goods before signing; write any shortfall in Received.
      </footer>
    </div>
  );
});

/* ------------------------------ Supplier returns and purchase ageing (IN-19) ------------------------------ */

export type GoodsReturn = { ref: string; date: string; supplier: string; items: string; value: number; creditNote?: string; credited: number };

/** IN-19 goods returns: what went back to suppliers and whether the credit has come in. */
export function GoodsReturnsReport({ returns }: { returns: GoodsReturn[] }) {
  const value = returns.reduce((s, r) => s + r.value, 0);
  const credited = returns.reduce((s, r) => s + r.credited, 0);
  return (
    <Frame minWidth="min-w-[680px]">
      <thead className="bg-[var(--color-bg-surface-subtle)] text-left text-xs text-muted-foreground">
        <tr>
          <th className={th}>Return</th>
          <th className={th}>Supplier and items</th>
          <th className={th}>Credit</th>
          <th className={thR}>Value</th>
          <th className={thR}>Still to credit</th>
        </tr>
      </thead>
      <tbody className="divide-y divide-[var(--color-border-subtle)]">
        {returns.map((r) => {
          const due = r.value - r.credited;
          return (
            <tr key={r.ref}>
              <td className={td}>
                <span className="font-mono text-xs">{r.ref}</span>
                <span className="block text-xs text-muted-foreground">{r.date}</span>
              </td>
              <td className={td}>
                {r.supplier}
                <span className="block text-xs text-muted-foreground">{r.items}</span>
              </td>
              <td className={td}>
                {due <= 0.005 ? <Flag tone="neutral">Credited {r.creditNote}</Flag> : r.credited ? <Flag tone="warning">Part credited {r.creditNote}</Flag> : <Flag tone="warning">Waiting for credit note</Flag>}
              </td>
              <td className={tdR}>{kes(r.value)}</td>
              <td className={cn(tdR, due > 0.005 && "font-semibold")}>{due > 0.005 ? kes(due) : "–"}</td>
            </tr>
          );
        })}
      </tbody>
      <tfoot className="border-t-2 border-[var(--color-border-panel)] bg-muted/30 font-semibold">
        <tr>
          <td colSpan={3} className={td}>
            {returns.length} returns
          </td>
          <td className={tdR}>{kes(value)}</td>
          <td className={tdR}>{kes(value - credited)}</td>
        </tr>
      </tfoot>
    </Frame>
  );
}

export const AGE_BUCKETS = ["0–30 days", "31–60 days", "61–90 days", "Over 90 days"] as const;
export type AgeingRow = { supplier: string; buckets: [number, number, number, number] };

/**
 * IN-19 purchase ageing: unpaid goods received per supplier, by days since received. The bar beside each
 * row shows the mix; the figures carry the meaning, so the bar uses one hue darkening with age.
 */
export function PurchaseAgeing({ rows, asOf }: { rows: AgeingRow[]; asOf: string }) {
  const shades = VIZ_SEQ.slice(1);
  const col = (i: number) => rows.reduce((s, r) => s + r.buckets[i], 0);
  const grand = [0, 1, 2, 3].reduce((s, i) => s + col(i), 0);
  return (
    <div className="space-y-2">
      <p className="text-xs text-muted-foreground">Unpaid goods received, aged from the date received, as at {asOf}.</p>
      <Frame minWidth="min-w-[760px]">
        <thead className="bg-[var(--color-bg-surface-subtle)] text-left text-xs text-muted-foreground">
          <tr>
            <th className={th}>Supplier</th>
            {AGE_BUCKETS.map((b, i) => (
              <th key={b} className={thR}>
                <span className="inline-flex items-center gap-1">
                  <span className="size-2.5 rounded-[2px]" style={{ backgroundColor: shades[i] }} aria-hidden />
                  {b}
                </span>
              </th>
            ))}
            <th className={thR}>Total</th>
            <th className={cn(th, "w-36")}>Mix</th>
          </tr>
        </thead>
        <tbody className="divide-y divide-[var(--color-border-subtle)]">
          {rows.map((r) => {
            const total = r.buckets.reduce((s, v) => s + v, 0);
            return (
              <tr key={r.supplier}>
                <td className={td}>
                  {r.supplier}
                  {r.buckets[3] > 0 ? (
                    <span className="ml-2">
                      <Flag tone="error">Over 90 days</Flag>
                    </span>
                  ) : null}
                </td>
                {r.buckets.map((v, i) => (
                  <td key={i} className={tdR}>
                    {v ? kes(v) : "–"}
                  </td>
                ))}
                <td className={cn(tdR, "font-semibold")}>{kes(total)}</td>
                <td className={td}>
                  <span className="flex h-3 w-full gap-[2px]" role="img" aria-label={AGE_BUCKETS.map((b, i) => `${b} ${total ? Math.round((r.buckets[i] / total) * 100) : 0}%`).join(", ")}>
                    {r.buckets.map((v, i) => (v ? <span key={i} className="h-full first:rounded-l-[3px] last:rounded-r-[3px]" style={{ width: `${(v / total) * 100}%`, backgroundColor: shades[i] }} /> : null))}
                  </span>
                </td>
              </tr>
            );
          })}
        </tbody>
        <tfoot className="border-t-2 border-[var(--color-border-panel)] bg-muted/30 font-semibold">
          <tr>
            <td className={td}>All suppliers</td>
            {[0, 1, 2, 3].map((i) => (
              <td key={i} className={tdR}>
                {kes(col(i))}
              </td>
            ))}
            <td className={tdR}>{kes(grand)}</td>
            <td className={cn(td, "text-xs font-normal text-muted-foreground")}>{grand ? `${Math.round((col(3) / grand) * 100)}% over 90 days` : ""}</td>
          </tr>
        </tfoot>
      </Frame>
    </div>
  );
}
