"use client";

import * as React from "react";

import { kes } from "@/components/medora/payroll";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select";
import { count, formatDate } from "@/lib/format";
import { cn } from "@/lib/utils";

/*
 * Expenses (AC-16): one form, the ledger posting it will make shown before saving, and the expenses
 * payment report. VAT on an expense can only be claimed with the supplier's KRA CU invoice number, so the
 * form asks for it exactly when the VAT box is ticked.
 */

export type ExpenseCategory = { name: string; account: string };
export type PayingAccount = { name: string; account: string };
export type ExpenseDraft = { category: string; date: string; amount: string; vatClaimable: boolean; supplier: string; reference: string; cuNo: string; paidFrom: string; branch: string; note: string };

export function expenseProblems(d: ExpenseDraft, today: string, priorRefs: string[]): { problems: Partial<Record<keyof ExpenseDraft, string>>; warnings: string[] } {
  const p: Partial<Record<keyof ExpenseDraft, string>> = {};
  const warnings: string[] = [];
  if (!d.category) p.category = "Choose what the money was spent on.";
  if (!d.date) p.date = "Enter the date it was paid.";
  else if (d.date > today) p.date = "Expenses are recorded once paid; this date is in the future.";
  const amt = Number(d.amount.replace(/,/g, ""));
  if (!/^\d+(\.\d{1,2})?$/.test(d.amount.replace(/,/g, "")) || amt <= 0) p.amount = "Enter the amount paid, VAT included.";
  if (!d.paidFrom) p.paidFrom = "Which account did the money come out of?";
  if (!d.branch) p.branch = "Which branch is this for?";
  if (d.vatClaimable) {
    if (!d.supplier.trim()) p.supplier = "VAT can only be claimed on a supplier's tax invoice: name the supplier.";
    if (!/^\d{10,20}$/.test(d.cuNo.replace(/\s/g, ""))) p.cuNo = "Enter the KRA CU invoice number from their eTIMS invoice (10 to 20 digits), or untick VAT.";
  }
  if (d.reference.trim() && priorRefs.includes(`${d.supplier.trim().toLowerCase()}|${d.reference.trim().toLowerCase()}`)) warnings.push(`${d.supplier} reference ${d.reference} is already recorded. Make sure this isn't the same bill twice.`);
  if (amt >= 50000) warnings.push("Over KES 50,000: an Admin approves it before it posts.");
  return { problems: p, warnings };
}

/** The journal the expense will post: expense (and VAT) debited, the paying account credited. */
export function expensePosting(d: ExpenseDraft, cats: ExpenseCategory[], payers: PayingAccount[]) {
  const amt = Number(d.amount.replace(/,/g, "")) || 0;
  const vat = d.vatClaimable ? Math.round((amt * 16) / 116 * 100) / 100 : 0;
  const cat = cats.find((c) => c.name === d.category);
  const payer = payers.find((x) => x.name === d.paidFrom);
  return [
    { account: cat?.account ?? "Expense account", debit: Math.round((amt - vat) * 100) / 100, credit: 0 },
    ...(vat ? [{ account: "1410 VAT on purchases", debit: vat, credit: 0 }] : []),
    { account: payer?.account ?? "Paying account", debit: 0, credit: amt },
  ];
}

export function ExpenseForm({ d, onChange, categories, payers, branches, problems, warnings, show }: { d: ExpenseDraft; onChange: (d: ExpenseDraft) => void; categories: ExpenseCategory[]; payers: PayingAccount[]; branches: string[]; problems: Partial<Record<keyof ExpenseDraft, string>>; warnings: string[]; show: boolean }) {
  const P = show ? problems : {};
  const set = <K extends keyof ExpenseDraft>(k: K, v: ExpenseDraft[K]) => onChange({ ...d, [k]: v });
  const f = (k: keyof ExpenseDraft, label: string, node: React.ReactNode, hint?: string) => (
    <div className="space-y-1" data-invalid={!!P[k] || undefined}>
      <label htmlFor={`ex-${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 ExpenseDraft, extra?: React.ComponentProps<typeof Input>) => <Input id={`ex-${k}`} value={String(d[k])} onChange={(e) => set(k, e.target.value as never)} aria-invalid={!!P[k]} {...extra} />;
  const posting = expensePosting(d, categories, payers);
  const ok = !!d.category && !!d.paidFrom && Number(d.amount.replace(/,/g, "")) > 0;
  return (
    <div className="space-y-4">
      <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
        {f(
          "category",
          "Category",
          <NativeSelect id="ex-category" value={d.category} onChange={(e) => set("category", e.target.value)} aria-invalid={!!P.category}>
            <NativeSelectOption value="">Choose…</NativeSelectOption>
            {categories.map((c) => (
              <NativeSelectOption key={c.name}>{c.name}</NativeSelectOption>
            ))}
          </NativeSelect>,
        )}
        {f("date", "Date paid", input("date", { type: "date" }))}
        {f("amount", "Amount, VAT included", input("amount", { inputMode: "decimal", className: "tabular-nums" }))}
        {f("supplier", d.vatClaimable ? "Supplier" : "Supplier (optional)", input("supplier"))}
        {f("reference", "Their reference (optional)", input("reference"), "Bill or receipt number.")}
        {f(
          "paidFrom",
          "Paid from",
          <NativeSelect id="ex-paidFrom" value={d.paidFrom} onChange={(e) => set("paidFrom", e.target.value)} aria-invalid={!!P.paidFrom}>
            <NativeSelectOption value="">Choose…</NativeSelectOption>
            {payers.map((x) => (
              <NativeSelectOption key={x.name}>{x.name}</NativeSelectOption>
            ))}
          </NativeSelect>,
        )}
        {f(
          "branch",
          "Branch",
          <NativeSelect id="ex-branch" value={d.branch} onChange={(e) => set("branch", e.target.value)} aria-invalid={!!P.branch}>
            <NativeSelectOption value="">Choose…</NativeSelectOption>
            {branches.map((b) => (
              <NativeSelectOption key={b}>{b}</NativeSelectOption>
            ))}
          </NativeSelect>,
        )}
        <div className="flex items-start gap-2 self-end pb-1 sm:col-span-2">
          <Checkbox id="ex-vat" checked={d.vatClaimable} onCheckedChange={(v) => set("vatClaimable", !!v)} />
          <label htmlFor="ex-vat" className="text-sm">
            Includes VAT we can claim
            <span className="block text-xs text-muted-foreground">Only with a supplier&apos;s eTIMS tax invoice. The VAT is posted separately and reduces what we pay KRA.</span>
          </label>
        </div>
        {d.vatClaimable ? f("cuNo", "KRA CU invoice number", input("cuNo", { className: "font-mono", inputMode: "numeric", onChange: (e) => set("cuNo", e.target.value.replace(/[^\d\s]/g, "")) })) : null}
      </div>
      {warnings.length ? (
        <ul className="list-disc space-y-0.5 pl-5 text-sm text-status-warning-text">
          {warnings.map((w) => (
            <li key={w}>{w}</li>
          ))}
        </ul>
      ) : null}
      <div className="rounded-md border border-[var(--color-border-panel)] bg-muted/30 p-3">
        <p className="mb-2 text-xs font-semibold text-muted-foreground uppercase">Will post to the ledger</p>
        {ok ? (
          <table className="w-full text-sm tabular-nums">
            <thead className="bg-[var(--color-bg-surface-subtle)] text-xs text-muted-foreground">
              <tr>
                <th className="py-1 text-left font-medium">Account</th>
                <th className="py-1 text-right font-medium">Debit</th>
                <th className="py-1 text-right font-medium">Credit</th>
              </tr>
            </thead>
            <tbody>
              {posting.map((l) => (
                <tr key={l.account} className="border-t border-[var(--color-border-subtle)]">
                  <td className="py-1">{l.account}</td>
                  <td className="py-1 text-right">{l.debit ? kes(l.debit) : ""}</td>
                  <td className="py-1 text-right">{l.credit ? kes(l.credit) : ""}</td>
                </tr>
              ))}
            </tbody>
          </table>
        ) : (
          <p className="text-sm text-muted-foreground">Choose a category, amount and paying account to see the entry.</p>
        )}
      </div>
    </div>
  );
}

export type ExpenseRow = { ref: string; date: string; category: string; supplier?: string; paidFrom: string; amount: number; vat: number };

/** AC-16 expenses payment report: by category, with what came out of each paying account. */
export function ExpensePaymentsReport({ rows, period }: { rows: ExpenseRow[]; period: string }) {
  const [open, setOpen] = React.useState<string | null>(null);
  const cats = [...new Set(rows.map((r) => r.category))].map((c) => {
    const rs = rows.filter((r) => r.category === c);
    return { category: c, rows: rs, amount: rs.reduce((s, r) => s + r.amount, 0), vat: rs.reduce((s, r) => s + r.vat, 0) };
  }).sort((a, b) => b.amount - a.amount);
  const total = rows.reduce((s, r) => s + r.amount, 0);
  const vat = rows.reduce((s, r) => s + r.vat, 0);
  const payers = [...new Set(rows.map((r) => r.paidFrom))].map((p) => ({ name: p, amount: rows.filter((r) => r.paidFrom === p).reduce((s, r) => s + r.amount, 0) })).sort((a, b) => b.amount - a.amount);
  return (
    <div className="space-y-3">
      <p className="text-sm">
        {period}: <strong className="tabular-nums">{kes(total)}</strong> paid in {count(rows.length, "expense")}, of which {kes(vat)} is VAT we can claim.
      </p>
      <div className="overflow-x-auto rounded-md border border-[var(--color-border-panel)] bg-card">
        <table className="w-full min-w-[560px] 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">Category</th>
              <th className="px-3 py-2 text-right font-medium">Payments</th>
              <th className="px-3 py-2 text-right font-medium">Claimable VAT</th>
              <th className="px-3 py-2 text-right font-medium">Paid</th>
              <th className="px-3 py-2 text-right font-medium">Share</th>
            </tr>
          </thead>
          {cats.map((c) => (
            <tbody key={c.category} className="border-t border-[var(--color-border-subtle)]">
              <tr className={cn("cursor-pointer hover:bg-muted/40", open === c.category && "bg-muted/30")} onClick={() => setOpen(open === c.category ? null : c.category)}>
                <td className="px-3 py-2">
                  <button type="button" aria-expanded={open === c.category} className="cursor-pointer text-left font-medium">
                    {c.category}
                  </button>
                </td>
                <td className="px-3 py-2 text-right tabular-nums">{c.rows.length}</td>
                <td className="px-3 py-2 text-right tabular-nums">{c.vat ? kes(c.vat) : "–"}</td>
                <td className="px-3 py-2 text-right tabular-nums">{kes(c.amount)}</td>
                <td className="px-3 py-2 text-right tabular-nums">{((c.amount / total) * 100).toFixed(1)}%</td>
              </tr>
              {open === c.category
                ? c.rows.map((r) => (
                    <tr key={r.ref} className="text-xs text-muted-foreground">
                      <td className="py-1 pr-3 pl-8">
                        <span className="font-mono">{r.ref}</span> · {formatDate(r.date, { short: true })}
                        {r.supplier ? ` · ${r.supplier}` : ""}
                      </td>
                      <td className="px-3 py-1" colSpan={2}>
                        from {r.paidFrom}
                      </td>
                      <td className="px-3 py-1 text-right tabular-nums">{kes(r.amount)}</td>
                      <td />
                    </tr>
                  ))
                : null}
            </tbody>
          ))}
          <tfoot className="border-t-2 border-[var(--color-border-panel)] bg-muted/30 font-semibold">
            <tr>
              <td className="px-3 py-2">All categories</td>
              <td className="px-3 py-2 text-right tabular-nums">{rows.length}</td>
              <td className="px-3 py-2 text-right tabular-nums">{kes(vat)}</td>
              <td className="px-3 py-2 text-right tabular-nums">{kes(total)}</td>
              <td className="px-3 py-2 text-right">100%</td>
            </tr>
          </tfoot>
        </table>
      </div>
      <div>
        <p className="mb-1 text-xs font-semibold text-muted-foreground uppercase">Paid from</p>
        <ul className="grid gap-1 text-sm sm:grid-cols-2">
          {payers.map((p) => (
            <li key={p.name} className="flex justify-between gap-3 rounded-md border border-[var(--color-border-subtle)] px-2 py-1">
              <span>{p.name}</span>
              <span className="tabular-nums">{kes(p.amount)}</span>
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
}
