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",
};

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 ArrivalReportPdf {
  /**
   * Generates and streams an Arrivals Report PDF (landscape A4).
   *
   * @param arrivals  Raw arrival (purchase) records from ReportService
   * @param res       Express Response to pipe into
   * @param filters   Optional filter metadata for the sub-header line
   */
  static async generate(
    arrivals: any[],
    res: Response,
    filters?: {
      search?: string;
      dateFrom?: string;
      dateTo?: string;
      supplier?: string;
      vegetable?: string;
      settlementStatus?: 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-report-${Date.now()}.pdf"`
    );
    res.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
    doc.pipe(res);

    // Landscape A4 usable width ≈ 761 pts
    const pageWidth = doc.page.width - PAGE_MARGIN * 2;

    await PdfHeader.draw(doc, pageWidth, PAGE_MARGIN, "ARRIVALS REPORT");

    this.drawFilterLine(doc, pageWidth, filters);
    this.drawTable(doc, arrivals, pageWidth);
    this.drawTotals(doc, arrivals, 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;
      supplier?: string;
      vegetable?: string;
      settlementStatus?: 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?.supplier) parts.push(`Supplier: ${filters.supplier}`);
    if (filters?.vegetable) parts.push(`Vegetable: ${filters.vegetable}`);
    if (filters?.settlementStatus && filters.settlementStatus !== "ALL")
      parts.push(`Status: ${statusLabel(filters.settlementStatus)}`);
    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,
    arrivals: any[],
    pageWidth: number
  ) {
    const pw = pageWidth;
    // Columns: landscape A4 ≈ 761 pts
    const cols = {
      no:         { x: PAGE_MARGIN + pw * 0.000, width: pw * 0.030 },
      date:       { x: PAGE_MARGIN + pw * 0.030, width: pw * 0.080 },
      lotNo:      { x: PAGE_MARGIN + pw * 0.110, width: pw * 0.075 },
      billNo:     { x: PAGE_MARGIN + pw * 0.185, width: pw * 0.070 },
      truckNo:    { x: PAGE_MARGIN + pw * 0.255, width: pw * 0.075 },
      supplier:   { x: PAGE_MARGIN + pw * 0.330, width: pw * 0.150 },
      vegetable:  { x: PAGE_MARGIN + pw * 0.480, width: pw * 0.095 },
      qty:        { x: PAGE_MARGIN + pw * 0.575, width: pw * 0.075 },
      bags:       { x: PAGE_MARGIN + pw * 0.650, width: pw * 0.055 },
      remQty:     { x: PAGE_MARGIN + pw * 0.705, width: pw * 0.080 },
      freight:    { x: PAGE_MARGIN + pw * 0.785, width: pw * 0.080 },
      status:     { x: PAGE_MARGIN + pw * 0.865, width: pw * 0.135 },
    };

    const rowHeight = 20;
    const headerH = 22;

    const drawTableHeader = () => {
      const y = doc.y;
      doc
        .font("Helvetica-Bold")
        .fontSize(7)
        .fillColor(COLORS.primary)
        .text("#",             cols.no.x,        y + 5, { width: cols.no.width,        align: "center" })
        .text("DATE",          cols.date.x,      y + 5, { width: cols.date.width })
        .text("LOT NO",        cols.lotNo.x,     y + 5, { width: cols.lotNo.width })
        .text("BILL NO",       cols.billNo.x,    y + 5, { width: cols.billNo.width })
        .text("TRUCK NO",      cols.truckNo.x,   y + 5, { width: cols.truckNo.width })
        .text("SUPPLIER",      cols.supplier.x,  y + 5, { width: cols.supplier.width })
        .text("VEGETABLE",     cols.vegetable.x, y + 5, { width: cols.vegetable.width })
        .text("QTY (KG)",      cols.qty.x,       y + 5, { width: cols.qty.width,        align: "right" })
        .text("BAGS",          cols.bags.x,      y + 5, { width: cols.bags.width,       align: "right" })
        .text("REM. QTY",      cols.remQty.x,    y + 5, { width: cols.remQty.width,     align: "right" })
        .text("FREIGHT",       cols.freight.x,   y + 5, { width: cols.freight.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();

    arrivals.forEach((a, i) => {
      ensureSpace(rowHeight);
      const y = doc.y;

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

      const dateVal = a.arrivalDate ?? a.purchaseDate;
      const dateStr = dateVal ? fmtDate(dateVal) : "-";
      const status = a.arrivalSettlement?.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.5).fillColor(COLORS.text);
      doc.text(dateStr,                                   cols.date.x,     y + 4, { width: cols.date.width - 4,     lineBreak: false });
      doc.text(a.lotNo ?? "-",                            cols.lotNo.x,    y + 4, { width: cols.lotNo.width - 4,    ellipsis: true, lineBreak: false });
      doc.text(a.billNo ?? "-",                           cols.billNo.x,   y + 4, { width: cols.billNo.width - 4,   ellipsis: true, lineBreak: false });
      doc.text(a.truckNo ?? "-",                          cols.truckNo.x,  y + 4, { width: cols.truckNo.width - 4,  ellipsis: true, lineBreak: false });
      doc.text(
        a.supplier?.name ?? a.cashSupplierName ?? a.agentName ?? "-",
        cols.supplier.x, y + 4, { width: cols.supplier.width - 4, ellipsis: true, lineBreak: false }
      );
      doc.text(a.vegetable?.name ?? "-",                 cols.vegetable.x, y + 4, { width: cols.vegetable.width - 4, ellipsis: true, lineBreak: false });

      doc.font("Helvetica").fontSize(7.5).fillColor(COLORS.text);
      doc.text(fmt(a.quantity),       cols.qty.x,     y + 4, { width: cols.qty.width - 2,     align: "right", lineBreak: false });
      doc.text(fmt(a.bags),           cols.bags.x,    y + 4, { width: cols.bags.width - 2,    align: "right", lineBreak: false });
      doc.text(fmt(a.remainingQuantity), cols.remQty.x, y + 4, { width: cols.remQty.width - 2, align: "right", lineBreak: false });
      doc.text(fmt(a.totalFreight ?? a.freight), cols.freight.x, y + 4, { width: cols.freight.width - 2, align: "right", lineBreak: false });

      doc.font("Helvetica-Bold").fontSize(7).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,
    arrivals: any[],
    pageWidth: number
  ) {
    const totalQty      = arrivals.reduce((s, a) => s + Number(a.quantity ?? 0), 0);
    const totalBags     = arrivals.reduce((s, a) => s + Number(a.bags ?? 0), 0);
    const totalRemQty   = arrivals.reduce((s, a) => s + Number(a.remainingQuantity ?? 0), 0);
    const totalFreight  = arrivals.reduce((s, a) => s + Number(a.totalFreight ?? a.freight ?? 0), 0);
    const totalAdvance  = arrivals.reduce((s, a) => s + Number(a.advanceAmount ?? 0), 0);

    const boxWidth = pageWidth * 0.44;
    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) => {
      doc.font("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 Quantity (KG):",   fmt(totalQty));
    drawRow("Total Bags:",            fmt(totalBags));
    drawRow("Remaining Qty (KG):",    fmt(totalRemQty));
    drawRow("Total Freight (Rs):",    fmt(totalFreight));
    drawRow("Total Advance (Rs):",    fmt(totalAdvance));
    drawRow("Total Arrivals:",        `${arrivals.length}`);

    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 arrivals report.",
        PAGE_MARGIN,
        y,
        { width: pageWidth, align: "center" }
      );
  }
}
