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

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

const PAGE_MARGIN = 40;

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

export class SupplierPaymentPdf {
    /**
     * Generates and streams a Supplier Payment PDF to the Express response.
     */
    static async generate(
        payments: any[],
        res: Response,
        filters?: {
            search?: string;
            dateFrom?: string;
            dateTo?: string;
        }
    ) {
        const doc = new PDFDocument({
            size: "A4",
            margin: PAGE_MARGIN,
            bufferPages: true,
        });

        res.setHeader("Content-Type", "application/pdf");
        res.setHeader(
            "Content-Disposition",
            `attachment; filename="supplier-payments-${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, "SUPPLIER PAYMENT REPORT");

        this.drawFilterLine(doc, pageWidth, filters);
        this.drawTable(doc, payments, pageWidth);
        this.drawTotals(doc, payments, 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 }
    ) {
        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?.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,
        payments: any[],
        pageWidth: number
    ) {
        // Portrait A4 pageWidth ≈ 515 pts
        const pw = pageWidth;
        const cols = {
            no:          { x: PAGE_MARGIN + pw * 0.000, width: pw * 0.055 },
            date:        { x: PAGE_MARGIN + pw * 0.055, width: pw * 0.130 },
            supplier:    { x: PAGE_MARGIN + pw * 0.185, width: pw * 0.245 },
            paymentMode: { x: PAGE_MARGIN + pw * 0.430, width: pw * 0.130 },
            referenceNo: { x: PAGE_MARGIN + pw * 0.560, width: pw * 0.185 },
            amount:      { x: PAGE_MARGIN + pw * 0.745, width: pw * 0.255 },
        };

        const rowHeight = 24;
        const headerH = 26;

        const drawTableHeader = () => {
            const y = doc.y;
            doc
                .font("Helvetica-Bold")
                .fontSize(8.5)
                .fillColor(COLORS.primary)
                .text("#",            cols.no.x,          y + 6, { width: cols.no.width,         align: "center" })
                .text("DATE",         cols.date.x,         y + 6, { width: cols.date.width })
                .text("SUPPLIER",     cols.supplier.x,     y + 6, { width: cols.supplier.width })
                .text("MODE",         cols.paymentMode.x,  y + 6, { width: cols.paymentMode.width })
                .text("REFERENCE",    cols.referenceNo.x,  y + 6, { width: cols.referenceNo.width })
                .text("AMOUNT",       cols.amount.x,       y + 6, { width: cols.amount.width - 4, align: "right" });

            doc.y = y + headerH;

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

            doc.y += 4;
        };

        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();

        payments.forEach((p, i) => {
            ensureSpace(rowHeight);
            const y = doc.y;

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

            const dateStr = p.paymentDate
                ? new Date(p.paymentDate).toLocaleDateString("en-GB").replace(/\//g, "-")
                : "-";

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

            doc.font("Helvetica").fontSize(9).fillColor(COLORS.text);
            doc.text(dateStr,                            cols.date.x,        y + 5, { width: cols.date.width - 4,        lineBreak: false });
            doc.text(p.supplier?.name ?? "-",            cols.supplier.x,    y + 5, { width: cols.supplier.width - 4,    ellipsis: true, lineBreak: false });
            doc.text(p.paymentMode ?? "-",               cols.paymentMode.x, y + 5, { width: cols.paymentMode.width - 4, lineBreak: false });
            doc.text(p.referenceNo ?? "-",               cols.referenceNo.x, y + 5, { width: cols.referenceNo.width - 4, ellipsis: true, lineBreak: false });

            doc
                .font("Helvetica-Bold")
                .fontSize(9)
                .fillColor(COLORS.primary)
                .text(`${fmt(p.amount)}`, cols.amount.x, y + 5, { width: cols.amount.width - 6, align: "right", lineBreak: false });

            doc.y = y + rowHeight;
        });

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

        doc.y += 14;
    }

    // ── Totals ─────────────────────────────────────────────────────
    private static drawTotals(
        doc: PDFKit.PDFDocument,
        payments: any[],
        pageWidth: number
    ) {
        const total = payments.reduce((s, p) => s + Number(p.amount ?? 0), 0);
        const boxWidth = pageWidth * 0.42;
        const labelX = PAGE_MARGIN + pageWidth - boxWidth;

        const y = doc.y;

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

        doc.y = y + 6;

        doc
            .font("Helvetica-Bold")
            .fontSize(11)
            .fillColor(COLORS.primary)
            .text("TOTAL PAID:", labelX, doc.y, { width: boxWidth * 0.58 })
            .text(`${fmt(total)}`, labelX, doc.y - 13.5, { width: boxWidth, align: "right" });

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