"use client";

import * as React from "react";
import { DownloadIcon, SearchIcon } from "lucide-react";

import { downloadText } from "@/components/medora/file-upload";
import { kes } from "@/components/medora/payroll";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select";

/**
 * Transactions list (AC-14): every money movement in one place, each with the account it debits and the
 * account it credits. Every row is one balanced posting, so the debit and credit columns always total the
 * same; a row opens the document behind it.
 */
export type MoneyTxn = {
  ref: string;
  date: string;
  /** Sale, Supplier payment, Expense, Drop, Payroll… */
  kind: string;
  details: string;
  debit: string;
  credit: string;
  amount: number;
  branch: string;
};

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

export function TransactionsList({ rows, pageSize = 8, onOpen, toolbarStart, body }: { rows: MoneyTxn[]; pageSize?: number; onOpen?: (t: MoneyTxn) => void; toolbarStart?: React.ReactNode; body?: React.ReactNode }) {
  const [q, setQ] = React.useState("");
  const [kind, setKind] = React.useState("");
  const [account, setAccount] = React.useState("");
  const [page, setPage] = React.useState(0);

  const kinds = [...new Set(rows.map((r) => r.kind))].sort();
  const accounts = [...new Set(rows.flatMap((r) => [r.debit, r.credit]))].sort();
  const term = q.trim().toLowerCase();
  const shown = rows.filter(
    (r) =>
      (!kind || r.kind === kind) &&
      (!account || r.debit === account || r.credit === account) &&
      (!term || `${r.ref} ${r.details} ${r.debit} ${r.credit}`.toLowerCase().includes(term)),
  );
  const pages = Math.max(1, Math.ceil(shown.length / pageSize));
  const at = Math.min(page, pages - 1);
  const slice = shown.slice(at * pageSize, at * pageSize + pageSize);
  const total = shown.reduce((s, r) => s + r.amount, 0);
  // With one account chosen, say which way money moved through it, so the total means something.
  const into = account ? shown.filter((r) => r.debit === account).reduce((s, r) => s + r.amount, 0) : 0;
  const outOf = account ? shown.filter((r) => r.credit === account).reduce((s, r) => s + r.amount, 0) : 0;

  const exportCsv = () => {
    const head = ["Reference", "Date", "Type", "Details", "Debit account", "Credit account", "Amount", "Branch"];
    const body = shown.map((r) => [r.ref, r.date, r.kind, r.details, r.debit, r.credit, r.amount.toFixed(2), r.branch].map(csvCell).join(","));
    downloadText("transactions.csv", [head.join(","), ...body].join("\n"));
  };

  return (
    // One container (data table spec §1): toolbar, table and pager share the white surface and its border
    <div className="overflow-hidden rounded-md border border-[var(--color-border-panel)] bg-card">
      <div className="border-b border-[var(--color-border-subtle)] p-3 flex flex-wrap items-center gap-2">
        {toolbarStart}
        <div className="relative min-w-52 flex-1">
          <SearchIcon className="pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground" aria-hidden />
          <Input aria-label="Search transactions" placeholder="Reference, details or account" className="pl-8" value={q} onChange={(e) => (setQ(e.target.value), setPage(0))} />
        </div>
        <NativeSelect aria-label="Type" value={kind} onChange={(e) => (setKind(e.target.value), setPage(0))}>
          <NativeSelectOption value="">All types</NativeSelectOption>
          {kinds.map((k) => (
            <NativeSelectOption key={k} value={k}>
              {k}
            </NativeSelectOption>
          ))}
        </NativeSelect>
        <NativeSelect aria-label="Account" value={account} onChange={(e) => (setAccount(e.target.value), setPage(0))}>
          <NativeSelectOption value="">All accounts</NativeSelectOption>
          {accounts.map((a) => (
            <NativeSelectOption key={a} value={a}>
              {a}
            </NativeSelectOption>
          ))}
        </NativeSelect>
        <Button size="sm" variant="outline" onClick={exportCsv} disabled={!shown.length}>
          <DownloadIcon data-icon="inline-start" />
          Export {shown.length === rows.length ? "all" : shown.length}
        </Button>
      </div>

      {body ?? (
      <>
      <div className="overflow-x-auto">
        <table className="w-full min-w-[760px] text-sm">
          <caption className="sr-only">Money movements with debit and credit accounts</caption>
          <thead className="bg-[var(--color-bg-surface-subtle)] text-left text-xs text-muted-foreground">
            <tr>
              <th className="px-3 py-2 font-medium">Reference</th>
              <th className="px-3 py-2 font-medium">Date</th>
              <th className="px-3 py-2 font-medium">Details</th>
              <th className="px-3 py-2 font-medium">Debit (money to)</th>
              <th className="px-3 py-2 font-medium">Credit (money from)</th>
              <th className="px-3 py-2 text-right font-medium">Amount</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-[var(--color-border-subtle)]">
            {slice.map((r, i) => (
              // One document can post several lines (a split-tender sale), so the reference alone isn't unique.
              <tr key={`${r.ref}-${at * pageSize + i}`} className="hover:bg-muted/40">
                <td className="px-3 py-2 whitespace-nowrap">
                  <button type="button" className="cursor-pointer font-mono text-xs text-primary underline-offset-4 hover:underline" onClick={() => onOpen?.(r)}>
                    {r.ref}
                  </button>
                  <span className="block text-xs text-muted-foreground">{r.kind}</span>
                </td>
                <td className="px-3 py-2 whitespace-nowrap tabular-nums">{r.date}</td>
                <td className="px-3 py-2">
                  {r.details}
                  <span className="block text-xs text-muted-foreground">{r.branch}</span>
                </td>
                <td className="px-3 py-2">{r.debit}</td>
                <td className="px-3 py-2">{r.credit}</td>
                <td className="px-3 py-2 text-right tabular-nums">{kes(r.amount)}</td>
              </tr>
            ))}
            {!slice.length ? (
              <tr>
                <td colSpan={6} className="px-3 py-8 text-center text-muted-foreground">
                  No transactions match these filters.
                </td>
              </tr>
            ) : null}
          </tbody>
          {shown.length ? (
            <tfoot className="border-t-2 border-[var(--color-border-panel)] bg-muted/30 text-sm font-semibold">
              <tr>
                <td colSpan={5} className="px-3 py-2">
                  {account ? (
                    <>
                      {account}: in {kes(into)}, out {kes(outOf)}, net {into - outOf < 0 ? "out" : "in"} {kes(Math.abs(into - outOf))}
                    </>
                  ) : (
                    <>Total of {shown.length.toLocaleString("en-US")} transactions (debits equal credits on every row)</>
                  )}
                </td>
                <td className="px-3 py-2 text-right tabular-nums">{account ? "" : kes(total)}</td>
              </tr>
            </tfoot>
          ) : null}
        </table>
      </div>

      {pages > 1 ? (
        <div className="border-t border-[var(--color-border-subtle)] p-3 flex items-center justify-between text-xs text-muted-foreground">
          <span>
            {at * pageSize + 1}–{Math.min(shown.length, at * pageSize + pageSize)} of {shown.length.toLocaleString("en-US")}
          </span>
          <span className="flex gap-1">
            <Button size="sm" variant="outline" disabled={at === 0} onClick={() => setPage(at - 1)}>
              Previous
            </Button>
            <Button size="sm" variant="outline" disabled={at >= pages - 1} onClick={() => setPage(at + 1)}>
              Next
            </Button>
          </span>
        </div>
      ) : null}
      </>
      )}
    </div>
  );
}
