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

interface QuotationData {
    quotation: any;
    shop: any;
}

// ---------- Design tokens ----------
const COLORS = {
    primary: "#0F5132", // Deep vegetable green
    accent: "#198754", // Fresh green
    danger: "#DC3545",
    text: "#212529",
    muted: "#6C757D",
    border: "#DEE2E6",
    rowAlt: "#F8F9FA",
    white: "#FFFFFF",
    bgAlt: "#E8F5E9" // Very light green for cards
};

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const PAGE_MARGIN = 40;

export class QuotationPdf {
    static async generate(data: QuotationData, res: Response) {
        const { quotation, shop } = data;

        const doc = new PDFDocument({
            size: "A4",
            margin: PAGE_MARGIN,
            bufferPages: true,
        });

        res.setHeader("Content-Type", "application/pdf");
        res.setHeader(
            "Content-Disposition",
            `inline; filename=quotation-${quotation.quotationNo ?? quotation.id}.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, "Q U O T A T I O N");
        this.drawQuotationCustomerMeta(doc, quotation, pageWidth);
        this.drawItemsTable(doc, quotation, pageWidth);
        this.drawTotals(doc, quotation, pageWidth);
        this.drawFooter(doc, pageWidth);

        doc.end();
    }



    /**
     * Bill-style meta block — matches the physical vegetable-market credit
     * bill exactly: a single bordered box with a vertical divider, the plain
     * customer name (no caption) on the left, and "No. : value" /
     * "Date : value" as two inline rows on the right.
     */
    private static drawQuotationCustomerMeta(doc: PDFKit.PDFDocument, quotation: any, pageWidth: number) {
        const boxY = doc.y;
        const boxHeight = 62;
        const rightColWidth = pageWidth * 0.4;
        const leftColWidth = pageWidth - rightColWidth;
        const boxX = PAGE_MARGIN;

        const date = quotation?.quotationDate
            ? new Date(quotation.quotationDate).toLocaleDateString("en-GB").replace(/\//g, "-")
            : new Date().toLocaleDateString("en-GB").replace(/\//g, "-");

        // Outer bordered box
        doc
            .rect(boxX, boxY, pageWidth, boxHeight)
            .lineWidth(1)
            .strokeColor(COLORS.border)
            .stroke();

        // Vertical divider between customer name and no/date
        const dividerX = boxX + leftColWidth;
        doc
            .moveTo(dividerX, boxY)
            .lineTo(dividerX, boxY + boxHeight)
            .strokeColor(COLORS.border)
            .lineWidth(1)
            .stroke();

        // ---- Left: Customer Name, vertically centered, plain (no caption) ----
        const leftPad = 16;
        const leftWidth = leftColWidth - leftPad * 2;
        const custName = quotation?.customerName ?? quotation?.customer?.name ?? "-";

        doc
            .font("Helvetica-Bold")
            .fontSize(13)
            .fillColor(COLORS.primary)
            .text(custName, boxX + leftPad, boxY + boxHeight / 2 - 7, {
                width: leftWidth,
                lineBreak: false,
                ellipsis: true,
            });

        // ---- Right: "No. : value" / "Date : value" — fixed-position segments ----
        const rightPad = 16;
        const labelX = dividerX + rightPad;
        const labelWidth = 46;
        const colonX = labelX + labelWidth;
        const colonWidth = rightColWidth - rightPad * 2 - labelWidth;

        const inlineRow = (y: number, label: string, value: string) => {
            doc
                .font("Helvetica-Bold")
                .fontSize(10)
                .fillColor(COLORS.primary)
                .text(label, labelX, y, { width: labelWidth, lineBreak: false });

            doc
                .font("Helvetica-Bold")
                .fontSize(10)
                .fillColor(COLORS.text)
                .text(`: ${value}`, colonX, y, { width: colonWidth, lineBreak: false, ellipsis: true });
        };

        inlineRow(boxY + 14, "No.", `${quotation?.quotationNo ?? quotation?.id}`);
        inlineRow(boxY + 34, "Date", date);

        doc.y = boxY + boxHeight + 20;
    }

    private static drawItemsTable(doc: PDFKit.PDFDocument, quotation: any, pageWidth: number) {
        const cols = {
            no: { x: PAGE_MARGIN, width: pageWidth * 0.06 },
            name: { x: PAGE_MARGIN + pageWidth * 0.06, width: pageWidth * 0.28 },
            hsn: { x: PAGE_MARGIN + pageWidth * 0.34, width: pageWidth * 0.14 },
            qty: { x: PAGE_MARGIN + pageWidth * 0.48, width: pageWidth * 0.14 },
            rate: { x: PAGE_MARGIN + pageWidth * 0.62, width: pageWidth * 0.16 },
            total: { x: PAGE_MARGIN + pageWidth * 0.78, width: pageWidth * 0.22 },
        };
        const rowHeight = 28;

        const drawTableHeader = () => {
            const y = doc.y;
            doc.roundedRect(PAGE_MARGIN, y, pageWidth, rowHeight, 6).fill(COLORS.primary);
            doc
                .font("Helvetica-Bold")
                .fontSize(9)
                .fillColor(COLORS.white)
                .text("#", cols.no.x, y + 9, { width: cols.no.width, align: "center" })
                .text("ITEM", cols.name.x, y + 9, { width: cols.name.width })
                .text("HSN", cols.hsn.x, y + 9, { width: cols.hsn.width })
                .text("QTY", cols.qty.x, y + 9, { width: cols.qty.width, align: "center" })
                .text("RATE", cols.rate.x, y + 9, { width: cols.rate.width, align: "right" })
                .text("AMOUNT", cols.total.x, y + 9, { width: cols.total.width - 8, align: "right" });
            doc.y = y + rowHeight;
        };

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

        drawTableHeader();

        const items: any[] = quotation?.items ?? [];
        items.forEach((item, i) => {
            ensureSpace(rowHeight);
            const y = doc.y;
            const name = item?.vegName ?? "Item";
            const hsn = item?.hsnCode ?? "-";
            const qty = item?.quantity ?? 0;
            const unit = item?.unit ? ` ${item.unit}` : " Kg";
            const rate = this.formatCurrency(item?.price);
            const total = this.formatCurrency(item?.amount);

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

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

            doc.font("Helvetica").fontSize(10).fillColor(COLORS.text);
            doc.text(name, cols.name.x, y + 9, { width: cols.name.width - 4 });
            doc.text(hsn, cols.hsn.x, y + 9, { width: cols.hsn.width });

            doc
                .text(`${qty}${unit}`, cols.qty.x, y + 9, { width: cols.qty.width, align: "center" })
                .text(rate, cols.rate.x, y + 9, { width: cols.rate.width, align: "right" })
                .text(total, cols.total.x, y + 9, { width: cols.total.width - 8, align: "right" });

            doc.y = y + rowHeight;
        });

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

        doc.y += 16;
    }

    private static drawTotals(doc: PDFKit.PDFDocument, quotation: any, pageWidth: number) {
        const subtotal = Number(quotation?.amount ?? 0);
        const discount = Number(quotation?.discount ?? 0);
        const extraCharge = Number(quotation?.extraCharge ?? 0);
        const grandTotal = Number(quotation?.totalAmount ?? subtotal);

        const boxGap = 20;
        const boxWidth = (pageWidth - boxGap) / 2;
        const boxX = PAGE_MARGIN + boxWidth + boxGap;

        const startY = doc.y;

        const row = (
            label: string,
            value: string,
            opts: { bold?: boolean; size?: number; color?: string; bg?: string } = {}
        ) => {
            const y = doc.y;
            const h = 22;
            if (opts.bg) {
                doc.rect(boxX - 10, y, boxWidth + 10, h).fill(opts.bg);
            }
            doc
                .font(opts.bold ? "Helvetica-Bold" : "Helvetica")
                .fontSize(opts.size ?? 10)
                .fillColor(opts.color ?? COLORS.text)
                .text(label, boxX, y + 5, { width: boxWidth * 0.55 })
                .text(value, boxX, y + 5, { width: boxWidth, align: "right" });
            doc.y = y + h;
        };

        row("Subtotal:", this.formatCurrency(subtotal), { color: COLORS.muted });

        if (discount > 0) {
            row("Discount:", `- ${this.formatCurrency(discount)}`, { color: COLORS.accent });
        }
        if (extraCharge > 0) {
            row("Extra Charge:", `+ ${this.formatCurrency(extraCharge)}`, { color: COLORS.muted });
        }

        doc
            .moveTo(boxX, doc.y + 2)
            .lineTo(boxX + boxWidth, doc.y + 2)
            .strokeColor(COLORS.border)
            .lineWidth(1)
            .stroke();
        doc.y += 6;

        row("GRAND TOTAL:", this.formatCurrency(grandTotal), {
            bold: true,
            size: 13,
            color: COLORS.primary,
        });

        doc.y = Math.max(doc.y, startY) + 14;
    }

    private static drawFooter(doc: PDFKit.PDFDocument, pageWidth: number) {
        let y = doc.page.height - PAGE_MARGIN - 20;

        doc.font("Helvetica-Oblique").fontSize(9).fillColor(COLORS.muted);
        const footerText = "This is a computer-generated quotation.";
        doc.text(footerText, PAGE_MARGIN, y, { width: pageWidth, align: "center" });
    }

    private static formatCurrency(val: any): string {
        const num = Number(val);
        if (isNaN(num)) return "Rs. 0.00";
        return `Rs. ${num.toFixed(2)}`;
    }
}