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

const COLORS = {
  primary: "#002060",
  secondary: "#1B5E20",
  accent: "#D32F2F",
  text: "#212529",
  muted: "#6C757D",
  border: "#DEE2E6",
  bgLight: "#F8F9FA",
  highlight: "#E8F8F5",
};

const PAGE_MARGIN = 36;

function fmt(value: number | undefined | null): string {
  const n = Number(value ?? 0);
  return Number.isFinite(n)
    ? `${n.toLocaleString("en-IN", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`
    : "0.00";
}

export class FinancialSummaryPdf {
  static async generate(data: FinancialSummaryResponse, res: Response) {
    const doc = new PDFDocument({
      size: "A4",
      layout: "portrait",
      margin: PAGE_MARGIN,
      bufferPages: true,
    });

    res.setHeader("Content-Type", "application/pdf");
    res.setHeader(
      "Content-Disposition",
      `attachment; filename="Financial_Summary_${data.date}.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, "FINANCIAL SUMMARY REPORT");

    this.drawDateBadge(doc, pageWidth, data.date);
    this.drawBalancingTable(doc, pageWidth, data);
    this.drawMovementsSection(doc, pageWidth, data);
    this.drawFooter(doc, pageWidth);

    doc.end();
  }

  private static drawDateBadge(doc: PDFKit.PDFDocument, pageWidth: number, dateStr: string) {
    const y = doc.y + 6;
    doc.rect(PAGE_MARGIN, y, pageWidth, 24).fillAndStroke(COLORS.bgLight, COLORS.border);

    doc
      .font("Helvetica-Bold")
      .fontSize(10)
      .fillColor(COLORS.primary)
      .text(`DATE : ${dateStr} | FINANCIAL SUMMARY`, PAGE_MARGIN + 10, y + 6, {
        width: pageWidth - 20,
        align: "left",
      });

    doc.moveDown(1.5);
  }

  private static drawBalancingTable(
    doc: PDFKit.PDFDocument,
    pageWidth: number,
    data: FinancialSummaryResponse
  ) {
    const startY = doc.y + 4;
    const colW = (pageWidth - 10) / 2;

    doc
      .font("Helvetica-Bold")
      .fontSize(11)
      .fillColor(COLORS.primary)
      .text("OPENING & CLOSING BALANCE", PAGE_MARGIN, startY);

    const tableY = startY + 16;
    const rowH = 20;

    const rows = [
      {
        label: "Customer Outstanding",
        openVal: fmt(data.opening.outstanding),
        closeVal: fmt(data.closing.outstanding),
        bold: false,
        bgColor: null,
        textColor: COLORS.text,
      },
      {
        label: "Supplier Outstanding",
        openVal: fmt(data.opening.supplierOutstanding),
        closeVal: fmt(data.closing.supplierOutstanding),
        bold: false,
        bgColor: null,
        textColor: COLORS.text,
      },
      {
        label: "Total Outstanding",
        openVal: fmt(data.opening.totalOutstanding ?? (data.opening.outstanding + data.opening.supplierOutstanding)),
        closeVal: fmt(data.closing.totalOutstanding ?? (data.closing.outstanding + data.closing.supplierOutstanding)),
        bold: true,
        bgColor: "#F5F3FF",
        textColor: "#581C87",
      },
      {
        label: "Cash in Hand",
        openVal: fmt(data.opening.cashInHand),
        closeVal: fmt(data.closing.cashInHand),
        bold: false,
        bgColor: null,
        textColor: COLORS.text,
      },
      {
        label: "Cash in Bank",
        openVal: fmt(data.opening.cashInBank),
        closeVal: fmt(data.closing.cashInBank),
        bold: false,
        bgColor: null,
        textColor: COLORS.text,
      },
      {
        label: "Total Cash & Bank",
        openVal: fmt(data.opening.totalCashBank ?? (data.opening.cashInHand + data.opening.cashInBank)),
        closeVal: fmt(data.closing.totalCashBank ?? (data.closing.cashInHand + data.closing.cashInBank)),
        bold: true,
        bgColor: "#EFF6FF",
        textColor: "#1E3A8A",
      },
      {
        label: "Combined Total",
        openVal: fmt(data.opening.total),
        closeVal: fmt(data.closing.total),
        bold: true,
        bgColor: COLORS.highlight,
        textColor: COLORS.primary,
      },
    ];

    const totalTableH = rowH * (rows.length + 1);

    // Opening Card Box
    doc.rect(PAGE_MARGIN, tableY, colW, totalTableH).fillAndStroke("#FFFFFF", COLORS.border);
    doc.rect(PAGE_MARGIN, tableY, colW, rowH).fillAndStroke(COLORS.primary, COLORS.primary);
    doc
      .font("Helvetica-Bold")
      .fontSize(9.5)
      .fillColor("#FFFFFF")
      .text("OPENING", PAGE_MARGIN + 8, tableY + 5);

    // Closing Card Box
    const closingX = PAGE_MARGIN + colW + 10;
    doc.rect(closingX, tableY, colW, totalTableH).fillAndStroke("#FFFFFF", COLORS.border);
    doc.rect(closingX, tableY, colW, rowH).fillAndStroke(COLORS.secondary, COLORS.secondary);
    doc
      .font("Helvetica-Bold")
      .fontSize(9.5)
      .fillColor("#FFFFFF")
      .text("CLOSING", closingX + 8, tableY + 5);

    rows.forEach((r, idx) => {
      const currentY = tableY + rowH * (idx + 1);

      if (r.bgColor) {
        doc.rect(PAGE_MARGIN, currentY, colW, rowH).fill(r.bgColor);
        doc.rect(closingX, currentY, colW, rowH).fill(r.bgColor);
      }

      // Border line between rows
      doc.rect(PAGE_MARGIN, currentY, colW, rowH).stroke(COLORS.border);
      doc.rect(closingX, currentY, colW, rowH).stroke(COLORS.border);

      // Opening
      doc
        .font(r.bold ? "Helvetica-Bold" : "Helvetica")
        .fontSize(8.5)
        .fillColor(r.textColor)
        .text(r.label, PAGE_MARGIN + 8, currentY + 5, { width: colW * 0.55 });
      doc
        .font(r.bold ? "Helvetica-Bold" : "Helvetica")
        .fontSize(8.5)
        .fillColor(r.textColor)
        .text(r.openVal, PAGE_MARGIN + colW * 0.55, currentY + 5, {
          width: colW * 0.42,
          align: "right",
        });

      // Closing
      doc
        .font(r.bold ? "Helvetica-Bold" : "Helvetica")
        .fontSize(8.5)
        .fillColor(r.textColor)
        .text(r.label, closingX + 8, currentY + 5, { width: colW * 0.55 });
      doc
        .font(r.bold ? "Helvetica-Bold" : "Helvetica")
        .fontSize(8.5)
        .fillColor(r.textColor)
        .text(r.closeVal, closingX + colW * 0.55, currentY + 5, {
          width: colW * 0.42,
          align: "right",
        });
    });

    doc.y = tableY + totalTableH + 14;
  }

  private static drawMovementsSection(
    doc: PDFKit.PDFDocument,
    pageWidth: number,
    data: FinancialSummaryResponse
  ) {
    const startY = doc.y;
    const colW = (pageWidth - 10) / 2;
    const closingX = PAGE_MARGIN + colW + 10;
    const rowH = 20;

    doc
      .font("Helvetica-Bold")
      .fontSize(11)
      .fillColor(COLORS.primary)
      .text("DAILY FINANCIAL MOVEMENTS", PAGE_MARGIN, startY);

    const tableY = startY + 16;
    const ym = data.yesterdayMovements;
    const leftRows = [
      { label: "Expenses", value: fmt(ym?.expenses ?? 0), textColor: "#C62828" },
      { label: "Supplier Payments", value: fmt(ym?.supplierPayments ?? 0), textColor: "#6A1B9A" },
      { label: "Wholesale Sales", value: fmt(ym?.wholesaleSales ?? ym?.sales ?? 0), textColor: "#1B5E20" },
      { label: "Retail Sales (Moved)", value: fmt(ym?.retailSales ?? 0), textColor: "#0D5302" },
      { label: "Total Sales Amount", value: fmt(ym?.sales ?? 0), textColor: "#1B5E20" },
      { label: "Purchase Amount", value: fmt(ym?.purchases ?? 0), textColor: "#283593" },
      { label: "Customer Payments", value: fmt(ym?.customerPayments ?? 0), textColor: "#1565C0" },
      { label: "Cash to Bank Transfer (Contra)", value: fmt(ym?.transfers ?? 0), textColor: "#00695C" },
    ];

    const rightRows = [
      { label: "Expenses", value: fmt(data.movements.expenses.total), textColor: "#C62828" },
      { label: "Supplier Payments", value: fmt(data.movements.supplierPayments.total), textColor: "#6A1B9A" },
      { label: "Wholesale Sales", value: fmt(data.movements.sales.wholesale ?? data.movements.sales.total), textColor: "#1B5E20" },
      { label: "Retail Sales (Moved)", value: fmt(data.movements.sales.retail ?? 0), textColor: "#0D5302" },
      { label: "Total Sales Amount", value: fmt(data.movements.sales.total), textColor: "#1B5E20" },
      { label: "Purchase Amount", value: fmt(data.movements.purchases.total), textColor: "#283593" },
      { label: "Customer Payments", value: fmt(data.movements.customerPayments.total), textColor: "#1565C0" },
      { label: "Cash to Bank Transfer (Contra)", value: fmt(data.movements.transfers.cashToBank), textColor: "#00695C" },
    ];

    const totalTableH = rowH * (leftRows.length + 1);

    // Left Box (Yesterday / Opening Side)
    doc.rect(PAGE_MARGIN, tableY, colW, totalTableH).fillAndStroke("#FFFFFF", COLORS.border);
    doc.rect(PAGE_MARGIN, tableY, colW, rowH).fillAndStroke(COLORS.primary, COLORS.primary);
    doc
      .font("Helvetica-Bold")
      .fontSize(9.5)
      .fillColor("#FFFFFF")
      .text("YESTERDAY (OPENING)", PAGE_MARGIN + 8, tableY + 5);

    // Right Box (Today / Closing Side)
    doc.rect(closingX, tableY, colW, totalTableH).fillAndStroke("#FFFFFF", COLORS.border);
    doc.rect(closingX, tableY, colW, rowH).fillAndStroke(COLORS.secondary, COLORS.secondary);
    doc
      .font("Helvetica-Bold")
      .fontSize(9.5)
      .fillColor("#FFFFFF")
      .text("TODAY (CLOSING)", closingX + 8, tableY + 5);

    for (let i = 0; i < leftRows.length; i++) {
      const currentY = tableY + rowH * (i + 1);
      const isAlt = i % 2 === 1;

      if (isAlt) {
        doc.rect(PAGE_MARGIN, currentY, colW, rowH).fill("#FAFAFA");
        doc.rect(closingX, currentY, colW, rowH).fill("#FAFAFA");
      }

      doc.rect(PAGE_MARGIN, currentY, colW, rowH).stroke(COLORS.border);
      doc.rect(closingX, currentY, colW, rowH).stroke(COLORS.border);

      const l = leftRows[i];
      const r = rightRows[i];
      if (!l || !r) continue;

      // Left Item (Opening side)
      doc
        .font("Helvetica")
        .fontSize(8.5)
        .fillColor(COLORS.text)
        .text(l.label, PAGE_MARGIN + 8, currentY + 5, { width: colW * 0.58 });
      doc
        .font("Helvetica-Bold")
        .fontSize(8.5)
        .fillColor(l.textColor)
        .text(l.value, PAGE_MARGIN + colW * 0.58, currentY + 5, {
          width: colW * 0.38,
          align: "right",
        });

      // Right Item (Closing side)
      doc
        .font("Helvetica")
        .fontSize(8.5)
        .fillColor(COLORS.text)
        .text(r.label, closingX + 8, currentY + 5, { width: colW * 0.58 });
      doc
        .font("Helvetica-Bold")
        .fontSize(8.5)
        .fillColor(r.textColor)
        .text(r.value, closingX + colW * 0.58, currentY + 5, {
          width: colW * 0.38,
          align: "right",
        });
    }

    doc.y = tableY + totalTableH + 14;
  }

  private static drawFooter(doc: PDFKit.PDFDocument, pageWidth: number) {
    const totalPages = doc.bufferedPageRange().count;
    for (let i = 0; i < totalPages; i++) {
      doc.switchToPage(i);
      const footerY = doc.page.height - PAGE_MARGIN - 15;

      doc
        .font("Helvetica")
        .fontSize(7.5)
        .fillColor(COLORS.muted)
        .text(
          `Financial Summary generated on ${new Date().toLocaleString("en-GB")} | Amman Vegetables Stores`,
          PAGE_MARGIN,
          footerY,
          { width: pageWidth * 0.7 }
        );

      doc
        .font("Helvetica")
        .fontSize(7.5)
        .fillColor(COLORS.muted)
        .text(`Page ${i + 1} of ${totalPages}`, PAGE_MARGIN + pageWidth * 0.7, footerY, {
          width: pageWidth * 0.3,
          align: "right",
        });
    }
  }
}

export default FinancialSummaryPdf;
