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

const COLORS = {
    primary: "#1E293B",
    secondary: "#0F5132",
    accent: "#198754",
    text: "#212529",
    muted: "#6C757D",
    border: "#94A3B8",
    lightBorder: "#CBD5E1",
    rowAlt: "#F8F9FA",
    headerBg: "#0F172A",
    subHeaderBg: "#1E293B",
    greenRow: "#D1E7DD",
    mintRow: "#A7F3D0",
    blueRow: "#DBEAFE",
    totalRowBg: "#ECFDF5",
    white: "#FFFFFF",
    emeraldText: "#047857",
    darkGreenText: "#15803D",
    redText: "#DC2626",
    blueText: "#1D4ED8",
    purpleText: "#6B21A8",
    purpleBg: "#F3E8FF",
    blueBadgeBg: "#EFF6FF",
};

const PAGE_MARGIN = 25;

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

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

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

        res.setHeader("Content-Type", "application/pdf");
        res.setHeader(
            "Content-Disposition",
            `inline; filename="retail-daily-summary-${data.financialSummary?.date || 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, "RETAIL DAILY SUMMARY & FINANCIAL REPORT");

        this.drawFinancialSummaryCard(doc, pageWidth, data.financialSummary);
        
        this.drawRetailItemizedTable(doc, pageWidth, data.retailItemized || []);
        
        if (data.stockMovements && data.stockMovements.length > 0) {
            this.drawStockMovementsTable(doc, pageWidth, data.stockMovements);
        }

        this.drawFooter(doc, pageWidth);
        doc.end();
    }

    private static formatDate(dateStr?: string): string {
        if (!dateStr) return new Date().toLocaleDateString("en-GB").replace(/\//g, "-");
        const parts = dateStr.split("-");
        if (parts.length === 3) {
            return `${parts[2]}.${parts[1]}.${parts[0]}`;
        }
        return dateStr;
    }

    private static drawFinancialSummaryCard(doc: PDFKit.PDFDocument, pageWidth: number, summary: any) {
        const cardX = PAGE_MARGIN;
        const cardY = doc.y + 4;
        const colWidth = pageWidth / 2;
        const rowHeight = 16.5;

        const open = summary?.opening || summary || {};
        const close = summary?.closing || summary || {};

        const sales = summary?.sales ?? open.sales ?? 0;
        const cogs = summary?.cogs ?? open.cogs ?? 0;
        const grossAmount = summary?.grossAmount ?? open.grossAmount ?? 0;
        const expenses = summary?.expenses ?? open.expenses ?? 0;
        const profit = summary?.profit ?? open.profit ?? 0;
        const allocatedQty = summary?.allocatedQty ?? open.allocatedQty ?? 0;
        const allocatedValue = summary?.allocatedValue ?? open.allocatedValue ?? 0;
        const spoilageQty = summary?.spoilageQty ?? close.spoilageQty ?? 0;
        const remainingRetailStockValue = summary?.remainingRetailStockValue ?? close.remainingRetailStockValue ?? 0;

        const bannerHeight = 30;
        const formattedDate = this.formatDate(summary?.date);

        // Dark Banner
        doc.rect(cardX, cardY, pageWidth, bannerHeight).fill(COLORS.headerBg);

        doc.font("Helvetica-Bold")
            .fontSize(8)
            .fillColor("#94A3B8")
            .text(`Date : ${formattedDate}`, cardX, cardY + 4, { width: pageWidth, align: "center", lineBreak: false });

        doc.font("Helvetica-Bold")
            .fontSize(10)
            .fillColor(COLORS.white)
            .text("FINANCIAL SUMMARY (RETAIL)", cardX, cardY + 15, { width: pageWidth, align: "center", lineBreak: false });

        let currentY = cardY + bannerHeight;

        // Grid Header
        doc.rect(cardX, currentY, colWidth, rowHeight).fill(COLORS.subHeaderBg);
        doc.rect(cardX + colWidth, currentY, colWidth, rowHeight).fill(COLORS.subHeaderBg);

        doc.font("Helvetica-Bold")
            .fontSize(8.5)
            .fillColor(COLORS.white)
            .text("RETAIL METRICS", cardX, currentY + 4, { width: colWidth, align: "center", lineBreak: false })
            .text("AMOUNT / VALUE", cardX + colWidth, currentY + 4, { width: colWidth, align: "center", lineBreak: false });

        currentY += rowHeight;

        const rows = [
            { label: "Total Retail Sales Revenue", val: `Rs.${fmt(sales)}`, bold: true, isEmerald: true },
            { label: "Cost of Goods Sold (COGS)", val: `Rs.${fmt(cogs)}` },
            { label: "Gross Profit Amount", val: `Rs.${fmt(grossAmount)}`, bg: COLORS.greenRow, bold: true, isEmerald: true },
            { label: "Total Retail Expenses", val: `Rs.${fmt(expenses)}`, isRed: true },
            { label: "NET RETAIL PROFIT", val: `Rs.${fmt(profit)}`, bg: COLORS.mintRow, bold: true, isEmerald: true },
            { label: "Total Allocated Stock Qty (Kg)", val: `${fmtQty(allocatedQty)} kg` },
            { label: "Allocated Stock Valuation", val: `Rs.${fmt(allocatedValue)}` },
            { label: "Retail Spoilage Qty (Kg)", val: `${fmtQty(spoilageQty)} kg` },
            { label: "Remaining Retail Stock Valuation", val: `Rs.${fmt(remainingRetailStockValue)}`, bg: COLORS.blueRow, bold: true, isBlue: true },
        ];

        for (const row of rows) {
            if (row.bg) {
                doc.rect(cardX, currentY, pageWidth, rowHeight).fill(row.bg);
            }

            doc.rect(cardX, currentY, colWidth, rowHeight).stroke(COLORS.lightBorder);
            doc.rect(cardX + colWidth, currentY, colWidth, rowHeight).stroke(COLORS.lightBorder);

            const fontName = row.bold ? "Helvetica-Bold" : "Helvetica";
            doc.font(fontName).fontSize(8).fillColor(COLORS.text);

            doc.text(row.label, cardX + 8, currentY + 4, { width: colWidth - 12, align: "left", lineBreak: false });

            if (row.isEmerald) doc.font("Helvetica-Bold").fillColor(COLORS.emeraldText);
            else if (row.isRed) doc.fillColor(COLORS.redText);
            else if (row.isBlue) doc.font("Helvetica-Bold").fillColor(COLORS.blueText);
            else doc.fillColor(COLORS.text);

            doc.text(row.val, cardX + colWidth + 8, currentY + 4, { width: colWidth - 16, align: "right", lineBreak: false });

            currentY += rowHeight;
        }

        doc.rect(cardX, cardY, pageWidth, currentY - cardY).stroke(COLORS.border);

        doc.y = currentY + 12;
    }

    private static drawRetailItemizedTable(doc: PDFKit.PDFDocument, pageWidth: number, items: any[]) {
        const titleH = 16;
        const headerH = 18;
        const rowH = 16.5;

        if (doc.y + titleH + headerH + rowH > doc.page.height - PAGE_MARGIN - 20) {
            doc.addPage();
        }

        doc.font("Helvetica-Bold").fontSize(10).fillColor(COLORS.primary).text("Retail Sales Itemised Profit Breakdown", PAGE_MARGIN, doc.y, { lineBreak: false });
        doc.y += 14;

        const cols = {
            no: { x: PAGE_MARGIN, width: 30 },
            invoiceNo: { x: PAGE_MARGIN + 30, width: 120 },
            customer: { x: PAGE_MARGIN + 150, width: 100 },
            veg: { x: PAGE_MARGIN + 250, width: 90 },
            lotNo: { x: PAGE_MARGIN + 340, width: 90 },
            qty: { x: PAGE_MARGIN + 430, width: 65 },
            costRate: { x: PAGE_MARGIN + 495, width: 75 },
            sellRate: { x: PAGE_MARGIN + 570, width: 75 },
            totalAmt: { x: PAGE_MARGIN + 645, width: 75 },
            profit: { x: PAGE_MARGIN + 720, width: 71.89 },
        };

        const drawHeader = () => {
            const y = doc.y;
            doc.rect(PAGE_MARGIN, y, pageWidth, headerH).fill(COLORS.subHeaderBg);
            doc.font("Helvetica-Bold").fontSize(7.5).fillColor(COLORS.white);

            doc.text("#", cols.no.x, y + 5, { width: cols.no.width, align: "center", lineBreak: false })
                .text("Invoice No", cols.invoiceNo.x + 4, y + 5, { width: cols.invoiceNo.width - 4, align: "left", lineBreak: false })
                .text("Customer", cols.customer.x, y + 5, { width: cols.customer.width, align: "left", lineBreak: false })
                .text("Vegetable", cols.veg.x, y + 5, { width: cols.veg.width, align: "left", lineBreak: false })
                .text("Lot No", cols.lotNo.x, y + 5, { width: cols.lotNo.width, align: "left", lineBreak: false })
                .text("Qty Sold", cols.qty.x, y + 5, { width: cols.qty.width - 2, align: "right", lineBreak: false })
                .text("Cost Price", cols.costRate.x, y + 5, { width: cols.costRate.width - 2, align: "right", lineBreak: false })
                .text("Sell Rate", cols.sellRate.x, y + 5, { width: cols.sellRate.width - 2, align: "right", lineBreak: false })
                .text("Sales Amount", cols.totalAmt.x, y + 5, { width: cols.totalAmt.width - 2, align: "right", lineBreak: false })
                .text("Profit", cols.profit.x, y + 5, { width: cols.profit.width - 2, align: "right", lineBreak: false });

            doc.y = y + headerH;
        };

        drawHeader();

        let sumQty = 0;
        let sumSales = 0;
        let sumProfit = 0;

        items.forEach((item: any, idx: number) => {
            if (doc.y + rowH > doc.page.height - PAGE_MARGIN - 20) {
                doc.addPage();
                drawHeader();
            }

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

            const isArrival = !!item.isArrival;
            const isFlexible = !isArrival && (!!item.isFlexible || item.unit === "PIECES");
            sumQty += Number(item.quantity || 0);
            sumSales += Number(item.totalAmt || 0);
            if (!isFlexible) {
                sumProfit += Number(item.profit || 0);
            }

            doc.font("Helvetica").fontSize(7.5).fillColor(COLORS.text);

            // Row #
            doc.text(String(idx + 1), cols.no.x, y + 4, { width: cols.no.width, align: "center", lineBreak: false });

            // Invoice No badge
            if (item.invoiceNo) {
                doc.roundedRect(cols.invoiceNo.x + 2, y + 2, cols.invoiceNo.width - 6, 12.5, 3).fill(COLORS.blueBadgeBg);
                doc.font("Helvetica-Bold").fontSize(7.5).fillColor(COLORS.blueText)
                    .text(item.invoiceNo, cols.invoiceNo.x + 4, y + 4, { width: cols.invoiceNo.width - 10, align: "left", lineBreak: false });
            } else {
                doc.text("-", cols.invoiceNo.x + 4, y + 4, { width: cols.invoiceNo.width - 4, align: "left", lineBreak: false });
            }

            // Customer
            doc.font("Helvetica").fontSize(7.5).fillColor(COLORS.text)
                .text(item.walkInName || item.customerName || "-", cols.customer.x, y + 4, { width: cols.customer.width, align: "left", lineBreak: false });

            // Vegetable
            doc.text(item.vegetableName || "-", cols.veg.x, y + 4, { width: cols.veg.width, align: "left", lineBreak: false });

            // Lot No badge
            if (item.lotNo && item.lotNo !== "-") {
                doc.roundedRect(cols.lotNo.x, y + 2, cols.lotNo.width - 10, 12.5, 3).fill(COLORS.purpleBg);
                doc.font("Helvetica-Bold").fontSize(7.5).fillColor(COLORS.purpleText)
                    .text(item.lotNo, cols.lotNo.x + 4, y + 4, { width: cols.lotNo.width - 18, align: "center", lineBreak: false });
            } else {
                doc.font("Helvetica").fontSize(7.5).fillColor(COLORS.text)
                    .text("-", cols.lotNo.x, y + 4, { width: cols.lotNo.width, align: "left", lineBreak: false });
            }

            // Qty Sold
            doc.font("Helvetica-Bold").fontSize(7.5).fillColor(COLORS.text)
                .text(`${fmtQty(item.quantity)} ${item.unit || ''}`.trim(), cols.qty.x, y + 4, { width: cols.qty.width - 2, align: "right", lineBreak: false });

            // Cost Price & Selling Rate
            doc.font("Helvetica").fontSize(7.5).fillColor(COLORS.text)
                .text((isArrival || isFlexible) ? "-" : fmt(item.costPerUnit), cols.costRate.x, y + 4, { width: cols.costRate.width - 2, align: "right", lineBreak: false })
                .text(fmt(item.sellingRate), cols.sellRate.x, y + 4, { width: cols.sellRate.width - 2, align: "right", lineBreak: false });

            // Sales Amount (Rs.) (Emerald)
            doc.font("Helvetica-Bold").fillColor(COLORS.emeraldText)
                .text(`Rs.${fmt(item.totalAmt)}`, cols.totalAmt.x, y + 4, { width: cols.totalAmt.width - 2, align: "right", lineBreak: false });

            // Profit (Rs.) (Green if >=0, Red if <0)
            if (isFlexible) {
                doc.font("Helvetica").fillColor(COLORS.text)
                    .text("-", cols.profit.x, y + 4, { width: cols.profit.width - 2, align: "right", lineBreak: false });
            } else {
                const profitVal = Number(item.profit || 0);
                doc.font("Helvetica-Bold").fillColor(profitVal >= 0 ? COLORS.darkGreenText : COLORS.redText)
                    .text(`Rs.${fmt(profitVal)}`, cols.profit.x, y + 4, { width: cols.profit.width - 2, align: "right", lineBreak: false });
            }

            doc.rect(PAGE_MARGIN, y, pageWidth, rowH).stroke(COLORS.lightBorder);
            doc.y = y + rowH;
        });

        // Totals Row
        if (doc.y + rowH > doc.page.height - PAGE_MARGIN - 20) {
            doc.addPage();
            drawHeader();
        }

        const totY = doc.y;
        doc.rect(PAGE_MARGIN, totY, pageWidth, rowH + 2).fill(COLORS.totalRowBg);
        doc.font("Helvetica-Bold").fontSize(8).fillColor(COLORS.primary);
        doc.text("TOTAL:", cols.no.x, totY + 5, { width: cols.sellRate.x + cols.sellRate.width - cols.no.x - 6, align: "right", lineBreak: false });

        doc.fillColor(COLORS.emeraldText).text(`Rs.${fmt(sumSales)}`, cols.totalAmt.x, totY + 5, { width: cols.totalAmt.width - 2, align: "right", lineBreak: false });
        doc.fillColor(COLORS.darkGreenText).text(`Rs.${fmt(sumProfit)}`, cols.profit.x, totY + 5, { width: cols.profit.width - 2, align: "right", lineBreak: false });

        doc.rect(PAGE_MARGIN, totY, pageWidth, rowH + 2).stroke(COLORS.border);
        doc.y = totY + rowH + 12;
    }

    private static drawStockMovementsTable(doc: PDFKit.PDFDocument, pageWidth: number, movements: any[]) {
        const titleH = 16;
        const headerH = 18;
        const rowH = 16.5;

        if (doc.y + titleH + headerH + rowH > doc.page.height - PAGE_MARGIN - 20) {
            doc.addPage();
        }

        doc.font("Helvetica-Bold").fontSize(10).fillColor(COLORS.primary).text("Retail Stock Movements", PAGE_MARGIN, doc.y, { lineBreak: false });
        doc.y += 14;

        const cols = {
            lotNo: { x: PAGE_MARGIN, width: 120 },
            veg: { x: PAGE_MARGIN + 120, width: 200 },
            allocated: { x: PAGE_MARGIN + 320, width: 150 },
            sold: { x: PAGE_MARGIN + 470, width: 150 },
            remaining: { x: PAGE_MARGIN + 620, width: 171.89 },
        };

        const drawHeader = () => {
            const y = doc.y;
            doc.rect(PAGE_MARGIN, y, pageWidth, headerH).fill(COLORS.subHeaderBg);
            doc.font("Helvetica-Bold").fontSize(7.5).fillColor(COLORS.white);

            doc.text("Lot No", cols.lotNo.x + 4, y + 5, { width: cols.lotNo.width - 4, align: "left", lineBreak: false })
                .text("Vegetable", cols.veg.x, y + 5, { width: cols.veg.width, align: "left", lineBreak: false })
                .text("Allocated Qty", cols.allocated.x, y + 5, { width: cols.allocated.width - 4, align: "right", lineBreak: false })
                .text("Sold Qty", cols.sold.x, y + 5, { width: cols.sold.width - 4, align: "right", lineBreak: false })
                .text("Remaining Stock Qty", cols.remaining.x, y + 5, { width: cols.remaining.width - 4, align: "right", lineBreak: false });

            doc.y = y + headerH;
        };

        drawHeader();

        movements.forEach((m: any, idx: number) => {
            if (doc.y + rowH > doc.page.height - PAGE_MARGIN - 20) {
                doc.addPage();
                drawHeader();
            }

            const rowY = doc.y;
            if (idx % 2 === 1) doc.rect(PAGE_MARGIN, rowY, pageWidth, rowH).fill(COLORS.rowAlt);

            // Lot No badge
            if (m.lotNo && m.lotNo !== "-") {
                doc.roundedRect(cols.lotNo.x + 2, rowY + 2, cols.lotNo.width - 20, 12.5, 3).fill(COLORS.purpleBg);
                doc.font("Helvetica-Bold").fontSize(7.5).fillColor(COLORS.purpleText)
                    .text(m.lotNo, cols.lotNo.x + 4, rowY + 4, { width: cols.lotNo.width - 24, align: "center", lineBreak: false });
            } else {
                doc.font("Helvetica").fontSize(7.5).fillColor(COLORS.text)
                    .text("-", cols.lotNo.x + 4, rowY + 4, { width: cols.lotNo.width - 4, align: "left", lineBreak: false });
            }

            // Vegetable
            doc.font("Helvetica").fontSize(7.5).fillColor(COLORS.text)
                .text(m.vegetableName || "-", cols.veg.x, rowY + 4, { width: cols.veg.width, align: "left", lineBreak: false });

            // Allocated Qty
            doc.text(`${fmtQty(m.allocatedQty)} ${m.unit || ''}`.trim(), cols.allocated.x, rowY + 4, { width: cols.allocated.width - 4, align: "right", lineBreak: false });

            // Sold Qty (Blue)
            doc.font("Helvetica-Bold").fillColor(COLORS.blueText)
                .text(`${fmtQty(m.soldQty)} ${m.unit || ''}`.trim(), cols.sold.x, rowY + 4, { width: cols.sold.width - 4, align: "right", lineBreak: false });

            // Remaining Stock Qty (Green)
            doc.font("Helvetica-Bold").fillColor(COLORS.darkGreenText)
                .text(`${fmtQty(m.remainingQty)} ${m.unit || ''}`.trim(), cols.remaining.x, rowY + 4, { width: cols.remaining.width - 4, align: "right", lineBreak: false });

            doc.rect(PAGE_MARGIN, rowY, pageWidth, rowH).stroke(COLORS.lightBorder);
            doc.y = rowY + rowH;
        });
    }

    private static drawFooter(doc: PDFKit.PDFDocument, pageWidth: number) {
        const pages = doc.bufferedPageRange();
        for (let i = 0; i < pages.count; i++) {
            doc.switchToPage(i);

            const oldBottomMargin = doc.page.margins.bottom;
            doc.page.margins.bottom = 0;

            const footerY = doc.page.height - 18;
            doc.font("Helvetica").fontSize(7.5).fillColor(COLORS.muted)
                .text(`Generated on ${new Date().toLocaleString("en-IN")}`, PAGE_MARGIN, footerY, {
                    width: pageWidth,
                    align: "left",
                    lineBreak: false,
                });

            doc.page.margins.bottom = oldBottomMargin;
        }
    }
}
