import PDFDocument from "pdfkit";
import type { Response } from "express";
import { PdfHeader } from "./components/PdfHeader.js";

// ── Design tokens ──────────────────────────────────────────────────
const COLORS = {
  primary:   "#0F5132",
  accent:    "#198754",
  text:      "#212529",
  muted:     "#6C757D",
  border:    "#DEE2E6",
  rowAlt:    "#F8F9FA",
  white:     "#FFFFFF",
  highlight: "#D1E7DD",
};

const PAGE_MARGIN = 40;

// ── Helpers ────────────────────────────────────────────────────────
function fmt(value: number | string | undefined | null): string {
  const n = Number(value ?? 0);
  return isNaN(n) ? "-" : n.toLocaleString("en-IN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}

function fmtDate(date: any): string {
  if (!date) return "-";
  const d = new Date(date);
  if (isNaN(d.getTime())) return "-";
  const day = String(d.getDate()).padStart(2, '0');
  const month = String(d.getMonth() + 1).padStart(2, '0');
  return `${day}-${month}-${d.getFullYear()}`;
}

function statusLabel(s: string | undefined | null): string {
  if (!s) return "UNSETTLED";
  return s.replace(/_/g, " ");
}

export class ArrivalSettlementReportPdf {
  /**
   * Generates and streams an Arrival Settlements Report PDF (landscape A4).
   *
   * @param settlements  Raw ArrivalSettlement records from ReportService
   * @param res          Express Response to pipe into
   * @param filters      Optional filter metadata for the sub-header line
   */
  static async generate(
    settlements: any[],
    res: Response,
    filters?: {
      search?: string;
      dateFrom?: string;
      dateTo?: string;
      status?: string;
    }
  ) {
    const doc = new PDFDocument({
      size: "A4",
      layout: "landscape",
      margin: PAGE_MARGIN,
      bufferPages: true,
    });

    res.setHeader("Content-Type", "application/pdf");
    res.setHeader(
      "Content-Disposition",
      `attachment; filename="arrival-settlements-report-${Date.now()}.pdf"`
    );
    res.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
    doc.pipe(res);

    const pageWidth = doc.page.width - PAGE_MARGIN * 2;

    await PdfHeader.draw(doc, pageWidth, PAGE_MARGIN, "ARRIVAL SETTLEMENTS REPORT (P.PATTI)");

    this.drawFilterLine(doc, pageWidth, filters);
    this.drawTable(doc, settlements, pageWidth);
    this.drawTotals(doc, settlements, pageWidth);
    this.drawFooter(doc, pageWidth);

    doc.end();
  }

  // ── Filter sub-line ────────────────────────────────────────────
  private static drawFilterLine(
    doc: PDFKit.PDFDocument,
    pageWidth: number,
    filters?: {
      search?: string;
      dateFrom?: string;
      dateTo?: string;
      status?: string;
    }
  ) {
    const parts: string[] = [];
    if (filters?.dateFrom)
      parts.push(`From: ${new Date(filters.dateFrom).toLocaleDateString("en-GB").replace(/\//g, "-")}`);
    if (filters?.dateTo)
      parts.push(`To: ${new Date(filters.dateTo).toLocaleDateString("en-GB").replace(/\//g, "-")}`);
    if (filters?.status) parts.push(`Status: ${statusLabel(filters.status)}`);
    if (filters?.search) parts.push(`Search: "${filters.search}"`);

    if (parts.length) {
      doc
        .font("Helvetica")
        .fontSize(8.5)
        .fillColor(COLORS.muted)
        .text(parts.join("   |   "), PAGE_MARGIN, doc.y, {
          width: pageWidth,
          align: "right",
        });
      doc.y += 4;
    }

    doc.y += 10;
  }

  // ── Main table ─────────────────────────────────────────────────
  private static drawTable(
    doc: PDFKit.PDFDocument,
    settlements: any[],
    pageWidth: number
  ) {
    const pw = pageWidth;
    const cols = {
      no:          { x: PAGE_MARGIN + pw * 0.000, width: pw * 0.028 },
      pattiNo:     { x: PAGE_MARGIN + pw * 0.028, width: pw * 0.125 },
      date:        { x: PAGE_MARGIN + pw * 0.153, width: pw * 0.075 },
      lotNo:       { x: PAGE_MARGIN + pw * 0.228, width: pw * 0.070 },
      supplier:    { x: PAGE_MARGIN + pw * 0.298, width: pw * 0.140 },
      vegetable:   { x: PAGE_MARGIN + pw * 0.438, width: pw * 0.090 },
      weightSold:  { x: PAGE_MARGIN + pw * 0.528, width: pw * 0.080 },
      grossSales:  { x: PAGE_MARGIN + pw * 0.608, width: pw * 0.085 },
      commission:  { x: PAGE_MARGIN + pw * 0.693, width: pw * 0.075 },
      netPayable:  { x: PAGE_MARGIN + pw * 0.768, width: pw * 0.085 },
      paidAmt:     { x: PAGE_MARGIN + pw * 0.853, width: pw * 0.075 },
      status:      { x: PAGE_MARGIN + pw * 0.928, width: pw * 0.072 },
    };

    const rowHeight = 20;
    const headerH = 22;

    const drawTableHeader = () => {
      const y = doc.y;
      doc
        .font("Helvetica-Bold")
        .fontSize(6.5)
        .fillColor(COLORS.primary)
        .text("#",            cols.no.x,         y + 5, { width: cols.no.width,        align: "center" })
        .text("PATTI NO",     cols.pattiNo.x,    y + 5, { width: cols.pattiNo.width })
        .text("DATE",         cols.date.x,       y + 5, { width: cols.date.width })
        .text("LOT NO",       cols.lotNo.x,      y + 5, { width: cols.lotNo.width })
        .text("SUPPLIER",     cols.supplier.x,   y + 5, { width: cols.supplier.width })
        .text("VEGETABLE",    cols.vegetable.x,  y + 5, { width: cols.vegetable.width })
        .text("WT.SOLD (KG)", cols.weightSold.x, y + 5, { width: cols.weightSold.width, align: "right" })
        .text("GROSS SALES",  cols.grossSales.x, y + 5, { width: cols.grossSales.width, align: "right" })
        .text("COMMISSION",   cols.commission.x, y + 5, { width: cols.commission.width, align: "right" })
        .text("NET PAYABLE",  cols.netPayable.x, y + 5, { width: cols.netPayable.width, align: "right" })
        .text("PAID AMT",     cols.paidAmt.x,    y + 5, { width: cols.paidAmt.width,    align: "right" })
        .text("STATUS",       cols.status.x,     y + 5, { width: cols.status.width - 4, align: "center" });

      doc.y = y + headerH;

      doc
        .moveTo(PAGE_MARGIN, doc.y)
        .lineTo(PAGE_MARGIN + pw, doc.y)
        .strokeColor(COLORS.primary)
        .lineWidth(1)
        .stroke();

      doc.y += 3;
    };

    const ensureSpace = (needed: number) => {
      const bottomLimit = doc.page.height - PAGE_MARGIN - 60;
      if (doc.y + needed > bottomLimit) {
        doc.addPage();
        doc.y = PAGE_MARGIN;
        drawTableHeader();
      }
    };

    drawTableHeader();

    settlements.forEach((s, i) => {
      ensureSpace(rowHeight);
      const y = doc.y;

      if (i % 2 === 1) {
        doc.rect(PAGE_MARGIN, y, pw, rowHeight).fill(COLORS.rowAlt);
      }

      const arrival = s.purchase || {};
      const status = s.status ?? "UNSETTLED";
      const statusColor = status === "SETTLED" ? "#0F5132" : status === "PARTIALLY_SETTLED" ? "#856404" : "#842029";

      doc
        .font("Helvetica-Bold")
        .fontSize(7)
        .fillColor(COLORS.accent)
        .text(`${i + 1}`, cols.no.x, y + 4, { width: cols.no.width, align: "center" });

      doc.font("Helvetica").fontSize(7).fillColor(COLORS.text);
      doc.text(s.settlementNo ?? "-",                  cols.pattiNo.x,  y + 4, { width: cols.pattiNo.width - 4,  ellipsis: true, lineBreak: false });
      doc.text(fmtDate(s.settlementDate),              cols.date.x,     y + 4, { width: cols.date.width - 4,     lineBreak: false });
      doc.text(arrival.lotNo ?? "-",                   cols.lotNo.x,    y + 4, { width: cols.lotNo.width - 4,    ellipsis: true, lineBreak: false });
      doc.text(
        arrival.supplier?.name ?? arrival.cashSupplierName ?? arrival.agentName ?? "-",
        cols.supplier.x, y + 4, { width: cols.supplier.width - 4, ellipsis: true, lineBreak: false }
      );
      doc.text(arrival.vegetable?.name ?? "-",         cols.vegetable.x, y + 4, { width: cols.vegetable.width - 4, ellipsis: true, lineBreak: false });

      doc.font("Helvetica").fontSize(7).fillColor(COLORS.text);
      doc.text(fmt(s.totalWeightSold),  cols.weightSold.x, y + 4, { width: cols.weightSold.width - 2, align: "right", lineBreak: false });

      doc.font("Helvetica-Bold").fontSize(7).fillColor(COLORS.primary);
      doc.text(fmt(s.grossSalesTotal),  cols.grossSales.x, y + 4, { width: cols.grossSales.width - 2, align: "right", lineBreak: false });

      doc.font("Helvetica").fontSize(7).fillColor(COLORS.text);
      doc.text(fmt(s.commissionAmount), cols.commission.x, y + 4, { width: cols.commission.width - 2, align: "right", lineBreak: false });

      doc.font("Helvetica-Bold").fontSize(7).fillColor(COLORS.primary);
      doc.text(fmt(s.netPayable),       cols.netPayable.x, y + 4, { width: cols.netPayable.width - 2, align: "right", lineBreak: false });

      doc.font("Helvetica").fontSize(7).fillColor(COLORS.text);
      doc.text(fmt(s.paidAmount),       cols.paidAmt.x,    y + 4, { width: cols.paidAmt.width - 2,    align: "right", lineBreak: false });

      doc.font("Helvetica-Bold").fontSize(6.5).fillColor(statusColor);
      doc.text(statusLabel(status), cols.status.x, y + 4, { width: cols.status.width - 4, align: "center", lineBreak: false });

      doc.y = y + rowHeight;
    });

    // Bottom divider
    doc
      .moveTo(PAGE_MARGIN, doc.y)
      .lineTo(PAGE_MARGIN + pw, doc.y)
      .strokeColor(COLORS.border)
      .lineWidth(0.5)
      .stroke();

    doc.y += 12;
  }

  // ── Summary totals ─────────────────────────────────────────────
  private static drawTotals(
    doc: PDFKit.PDFDocument,
    settlements: any[],
    pageWidth: number
  ) {
    const totalGrossSales  = settlements.reduce((s, x) => s + Number(x.grossSalesTotal ?? 0), 0);
    const totalCommission  = settlements.reduce((s, x) => s + Number(x.commissionAmount ?? 0), 0);
    const totalDeductions  = settlements.reduce((s, x) => s + Number(x.totalDeductions ?? 0), 0);
    const totalNetPayable  = settlements.reduce((s, x) => s + Number(x.netPayable ?? 0), 0);
    const totalPaidAmount  = settlements.reduce((s, x) => s + Number(x.paidAmount ?? 0), 0);
    const totalBalance     = settlements.reduce((s, x) => s + Number(x.balanceAmount ?? 0), 0);

    const boxWidth = pageWidth * 0.46;
    const labelX   = PAGE_MARGIN + pageWidth - boxWidth;
    const valX     = labelX + boxWidth * 0.58;
    const valWidth = boxWidth * 0.42;

    const y0 = doc.y;

    doc
      .moveTo(labelX, y0)
      .lineTo(PAGE_MARGIN + pageWidth, y0)
      .strokeColor(COLORS.primary)
      .lineWidth(0.75)
      .stroke();

    const drawRow = (label: string, value: string, bold = false) => {
      doc.font(bold ? "Helvetica-Bold" : "Helvetica").fontSize(9).fillColor(COLORS.text)
         .text(label, labelX, doc.y, { width: boxWidth * 0.58 });
      doc.font("Helvetica-Bold").fontSize(9).fillColor(COLORS.primary)
         .text(value, valX, doc.y - 12.5, { width: valWidth, align: "right" });
      doc.y += 4;
    };

    doc.y = y0 + 6;
    drawRow("Total Gross Sales (Rs):",     fmt(totalGrossSales));
    drawRow("Total Commission (Rs):",      fmt(totalCommission));
    drawRow("Total Deductions (Rs):",      fmt(totalDeductions));
    drawRow("Total Net Payable (Rs):",     fmt(totalNetPayable), true);
    drawRow("Total Paid Amount (Rs):",     fmt(totalPaidAmount));
    drawRow("Total Balance Due (Rs):",     fmt(totalBalance));

    doc.y += 18;
  }

  // ── Footer ─────────────────────────────────────────────────────
  private static drawFooter(doc: PDFKit.PDFDocument, pageWidth: number) {
    const y = doc.page.height - PAGE_MARGIN - 20;
    doc
      .font("Helvetica-Oblique")
      .fontSize(8.5)
      .fillColor(COLORS.muted)
      .text(
        "This is a computer-generated arrival settlements report.",
        PAGE_MARGIN,
        y,
        { width: pageWidth, align: "center" }
      );
  }
}
