import jsPDF from "jspdf";
import autoTable, { RowInput } from "jspdf-autotable";
import { fmtDate } from "./format";
import { loadBrandedLogo, drawBrandedHeader, drawBrandedFooter } from "./reportHeader";

export type ReconRow = { name: string; date: string; number: string; memo: string; amount: number };

export type ReconReportData = {
  companyName: string;
  /** e.g. "1003 BBC - Operating" */
  accountName: string;
  statementEndDate: string;
  beginningBalance: number;
  endingBalance: number;
  bookBalance: number;
  clearedDeposits: ReconRow[];
  clearedWithdrawals: ReconRow[];
  unclearedDeposits: ReconRow[];
  unclearedWithdrawals: ReconRow[];
  preparedBy: string;
  currency: string;
  completedAt: string;
  logoUrl?: string | null;
};

const TEXT: [number, number, number] = [33, 37, 41];
const HEADER_FILL: [number, number, number] = [222, 226, 230];

/** Two decimals, thousands separators, negatives in parentheses. */
function num(n: number): string {
  const v = Math.round((n + Number.EPSILON) * 100) / 100 || 0;
  const abs = Math.abs(v).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  return v < 0 ? `(${abs})` : abs;
}
const sum = (rows: ReconRow[]) => rows.reduce((s, r) => s + Number(r.amount || 0), 0);

export async function renderReconciliationPdf(d: ReconReportData) {
  const doc = new jsPDF({ unit: "pt", format: "letter" });
  const W = doc.internal.pageSize.getWidth();
  const ML = 40;

  const logo = await loadBrandedLogo(d.logoUrl);
  let y = drawBrandedHeader(doc, {
    logo,
    title: "Bank Reconciliation",
    metaLines: [
      { label: "Bank account", value: d.accountName },
      { label: "Statement ending date", value: fmtDate(d.statementEndDate) },
    ],
  }) + 8;

  const clearedDep = sum(d.clearedDeposits);
  const clearedWd = sum(d.clearedWithdrawals);
  const unclearedDep = sum(d.unclearedDeposits);
  const unclearedWd = sum(d.unclearedWithdrawals);

  // ── Summary block ──
  const lineH = 18;
  const summary: { label: string; value: number; bold?: boolean }[] = [
    { label: "Beginning balance", value: d.beginningBalance, bold: true },
    { label: "  + Cleared deposits", value: clearedDep },
    { label: "  - Cleared withdrawals", value: -clearedWd },
    { label: "Ending balance", value: d.endingBalance, bold: true },
    { label: "  + Uncleared deposits", value: unclearedDep },
    { label: "  - Uncleared withdrawals", value: -unclearedWd },
    { label: "Book balance", value: d.bookBalance, bold: true },
  ];
  for (const r of summary) {
    doc.setFont("helvetica", r.bold ? "bold" : "normal");
    doc.setFontSize(r.bold ? 11 : 10);
    doc.setTextColor(...TEXT);
    doc.text(r.label, ML, y);
    doc.text(num(r.value), W - ML, y, { align: "right" });
    doc.setDrawColor(225); doc.setLineWidth(0.5);
    doc.line(ML, y + 5, W - ML, y + 5);
    y += lineH;
  }
  y += 10;

  // ── Register ──
  const COLS = 5;
  const body: RowInput[] = [];
  const sectionRow = (label: string, fill?: boolean) =>
    body.push([{ content: label, colSpan: COLS, styles: { fontStyle: "bold", fillColor: fill ? [240, 242, 245] : [255, 255, 255] } }]);
  const subHeaderRow = (label: string) =>
    body.push([{ content: label, colSpan: COLS, styles: { fontStyle: "bold", cellPadding: { top: 3, bottom: 2, left: 14, right: 4 } } }]);
  const dataRow = (r: ReconRow, withdrawal: boolean) =>
    body.push([
      { content: r.name || "", styles: { cellPadding: { top: 2, bottom: 2, left: 22, right: 4 } } },
      r.date ? fmtDate(r.date) : "",
      r.number || "",
      r.memo || "",
      { content: num(withdrawal ? -Math.abs(r.amount) : r.amount), styles: { halign: "right" } },
    ]);
  const totalRow = (label: string, value: number) =>
    body.push([
      { content: label, colSpan: 4, styles: { halign: "right", fontStyle: "bold", cellPadding: { top: 2, bottom: 2, left: 4, right: 8 } } },
      { content: num(value), styles: { halign: "right", fontStyle: "bold" } },
    ]);

  body.push([
    { content: "Beginning balance", colSpan: 4, styles: { fontStyle: "bold" } },
    { content: num(d.beginningBalance), styles: { halign: "right", fontStyle: "bold" } },
  ]);

  const group = (title: string, deposits: ReconRow[], withdrawals: ReconRow[]) => {
    sectionRow(title, true);
    subHeaderRow("+ Deposits");
    deposits.forEach((r) => dataRow(r, false));
    totalRow(`Total for ${title} deposits`, sum(deposits));
    subHeaderRow("- Withdrawals");
    withdrawals.forEach((r) => dataRow(r, true));
    totalRow(`Total for ${title} withdrawals`, -sum(withdrawals));
  };

  group("Cleared", d.clearedDeposits, d.clearedWithdrawals);
  group("Uncleared", d.unclearedDeposits, d.unclearedWithdrawals);

  autoTable(doc, {
    startY: y,
    head: [["Name", "Date", "Number", "Memo", "Amount"]],
    body,
    styles: { font: "helvetica", fontSize: 8.5, textColor: TEXT, lineColor: [225, 228, 232], lineWidth: 0.1, cellPadding: 2 },
    headStyles: { fillColor: HEADER_FILL, textColor: TEXT, fontStyle: "bold" },
    columnStyles: {
      1: { halign: "left", cellWidth: 64 },
      2: { halign: "left", cellWidth: 60 },
      4: { halign: "right", cellWidth: 80 },
    },
    margin: { left: ML, right: ML },
  });

  drawBrandedFooter(doc);
  doc.save(`reconciliation-${d.accountName.replace(/\s+/g, "-").toLowerCase()}-${d.statementEndDate}.pdf`);
}
