/**
 * PdfHeader — reusable document header matching the standard Shop Bill layout.
 *
 * Format:
 * ┌──────────────────────────────────────────────────────────────────────────────────┐
 * │ [God Name 1]                   [God Name 2]                     [God Name 3]     │
 * │ ──────────────────────────────────────────────────────────────────────────────── │
 * │                           AMMAN VEGETABLES STORES                     ( AVS )    │
 * │ V.M :9042007772                      CREDIT SALES BILL           V.R :8838261772     │
 * │ ──────────────────────────────────────────────────────────────────────────────── │
 * │ [God Img 1] [QR Code]          VEGETABLE & FRUITS TRADING           [God Img 2]  │
 * │                         NO: 80,NB BLOCK,NO: 6 GATE ,GANDHI MARKET                │
 * │                                TRICHY-620 008                                    │
 * └──────────────────────────────────────────────────────────────────────────────────┘
 */

import https from "https";
import http from "http";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import QRCode from "qrcode";
import sharp from "sharp";
import { ShopService } from "../../../services/ShopService.js";

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

const FONTS_DIR = path.join(__dirname, "..", "fonts");
const TAMIL_REGULAR = path.join(FONTS_DIR, "NotoSansTamil-Regular.ttf");
const TAMIL_BOLD = path.join(FONTS_DIR, "NotoSansTamil-Bold.ttf");

const GOD_IMAGE_DIR = path.join(process.cwd(), "uploads", "god-images");
const LOGO_DIR = path.join(process.cwd(), "uploads", "logos");
const LOCAL_LOGO_PATH = path.join(__dirname, "..", "img", "Logo.png");

const BASE_URL = (process.env.BASE_URL || "http://localhost:5000").replace(/\/$/, "");

const resolveFileUrl = (filename: string | null | undefined, folder: string): string | null => {
    if (!filename) return null;
    if (filename.startsWith("http")) return filename;
    return `${BASE_URL}/${folder}/${filename}`;
};

const COLORS = {
    navy: "#002060",
    border: "#002060",
};

export class PdfHeader {
    static async draw(
        doc: PDFKit.PDFDocument,
        pageWidth: number,
        margin: number,
        reportTitle: string
    ): Promise<void> {
        const shop = await new ShopService().getShop();

        // ── Register Tamil fonts if available ──
        if (fs.existsSync(TAMIL_REGULAR) && !(doc as any)._registeredFonts?.["TamilFont"]) {
            doc.registerFont("TamilFont", TAMIL_REGULAR);
        }
        if (fs.existsSync(TAMIL_BOLD) && !(doc as any)._registeredFonts?.["TamilFontBold"]) {
            doc.registerFont("TamilFontBold", TAMIL_BOLD);
        }

        const getFont = (text?: string | null, isBold = false) => {
            if (text && /[\u0B80-\u0BFF]/.test(text)) {
                if (isBold && (doc as any)._registeredFonts?.["TamilFontBold"]) return "TamilFontBold";
                if ((doc as any)._registeredFonts?.["TamilFont"]) return "TamilFont";
            }
            return isBold ? "Helvetica-Bold" : "Helvetica";
        };

        // ── Extract Shop Data ──
        const shopName = shop?.shopName ?? "AMMAN VEGETABLES STORES";
        const shortName = (shop?.shortName?.trim() || "AVS").slice(0, 3);
        const godName1 = shop?.godName1 ?? "ஸ்ரீ உருமணசாமி துணை";
        const godName2 = shop?.godName2 ?? "ஸ்ரீ சமயபுர மாரியம்மன் துணை";
        const godName3 = shop?.godName3 ?? "ஸ்ரீ காளியம்மன் துணை";
        const mobile1 = shop?.mobile ?? "9042007772";
        const mobile2 = shop?.mobile2 ?? "8838261772";
        const mapUrl = shop?.mapUrl ?? "https://maps.app.goo.gl/zCDd2uwtA5zAAhpc8?g_st=ac";
        const address = shop?.address ?? "VEGETABLE & FRUITS TRADING\nNO: 80,NB BLOCK,NO: 6 GATE ,GANDHI MARKET, TRICHY-620 008";

        const displayTitle = (reportTitle === "INVOICE" || !reportTitle) ? "CREDIT SALES BILL" : reportTitle;

        const startX = margin;
        const startY = doc.y;

        // ── 1. Top Row: God Names (3 Columns) ──
        const colWidth = pageWidth / 3;
        const topRowY = startY + 6;

        doc.fillColor(COLORS.navy);

        // God 1 (Left)
        doc.font(getFont(godName1, true)).fontSize(9.5).text(godName1, startX + 6, topRowY, {
            width: colWidth - 12,
            align: "left",
            lineBreak: false,
        });

        // God 2 (Center)
        doc.font(getFont(godName2, true)).fontSize(9.5).text(godName2, startX + colWidth, topRowY, {
            width: colWidth,
            align: "center",
            lineBreak: false,
        });

        // God 3 (Right)
        doc.font(getFont(godName3, true)).fontSize(9.5).text(godName3, startX + colWidth * 2, topRowY, {
            width: colWidth - 6,
            align: "right",
            lineBreak: false,
        });

        // Horizontal Line 1
        const line1Y = startY + 22;
        doc.moveTo(startX, line1Y).lineTo(startX + pageWidth, line1Y).lineWidth(0.75).strokeColor(COLORS.border).stroke();

        // ── 2. Middle Row: Shop Name & Oval Logo Badge ──
        const titleRowY = line1Y + 5;
        doc.font(getFont(shopName, true)).fontSize(17).fillColor(COLORS.navy).text(shopName, startX, titleRowY, {
            width: pageWidth,
            align: "center",
            lineBreak: false,
        });

        // Oval Badge (AVS text) on far right
        const badgeW = 46;
        const badgeH = 22;
        const badgeX = startX + pageWidth - badgeW - 10;
        const badgeY = titleRowY + 1;
        const badgeCX = badgeX + badgeW / 2;
        const badgeCY = badgeY + badgeH / 2;

        doc.save();
        doc.ellipse(badgeCX, badgeCY, badgeW / 2, badgeH / 2).lineWidth(1.2).strokeColor(COLORS.border).stroke();
        doc.font("Helvetica-Bold").fontSize(11).fillColor(COLORS.navy).text(shortName, badgeX, badgeCY - 4.5, {
            width: badgeW,
            align: "center",
        });
        doc.restore();

        // ── 3. Sub-Header Row: Mobile 1 | Bill Title | Mobile 2 ──
        const row3Y = titleRowY + 24;

        // Left: V.M :9042007772
        const formattedMobile1 = mobile1.startsWith("V.M") ? mobile1 : `V.M :${mobile1}`;
        doc.font("Helvetica-Bold").fontSize(10.5).fillColor(COLORS.navy).text(formattedMobile1, startX + 6, row3Y + 4, {
            lineBreak: false,
        });

        // Center: CREDIT SALES BILL
        doc.font(getFont(displayTitle, true)).fontSize(11.5).fillColor(COLORS.navy).text(displayTitle, startX, row3Y, {
            width: pageWidth,
            align: "center",
            lineBreak: false,
        });

        // Right: V.R :8838261772
        const formattedMobile2 = mobile2 ? (mobile2.startsWith("V.R") ? mobile2 : `V.R :${mobile2}`) : "";
        doc.font("Helvetica-Bold").fontSize(10.5).fillColor(COLORS.navy).text(formattedMobile2, startX + pageWidth - 140, row3Y + 4, {
            width: 134,
            align: "right",
            lineBreak: false,
        });

        // Horizontal Line 2
        const line2Y = row3Y + 16;
        doc.moveTo(startX, line2Y).lineTo(startX + pageWidth, line2Y).lineWidth(0.75).strokeColor(COLORS.border).stroke();

        // ── 4. Fourth Row (Body Header): God Img 1 | QR | Address | God Img 2 ──
        const bodyY = line2Y + 4;
        const imgH = 64;
        const imgW = 46;

        // God Image 1 (Far Left)
        const god1Filename = shop?.godImage1 ?? "default-god1.png";
        const god1Url = resolveFileUrl(god1Filename, "uploads/god-images");
        await this.drawGodImage(doc, god1Url, startX + 6, bodyY, imgW, imgH, "1");

        // QR Code (Next to God Image 1)
        const qrX = startX + 58;
        const qrSize = 60;
        if (mapUrl) {
            try {
                const qrBuffer = await QRCode.toBuffer(mapUrl, { margin: 1, width: 120 });
                doc.image(qrBuffer, qrX, bodyY + 2, { width: qrSize, height: qrSize });
            } catch (e) {
                console.error("[PdfHeader] QR generation failed:", e);
            }
        }

        // God Image 2 (Far Right)
        const god2Filename = shop?.godImage2 ?? "default-god2.png";
        const god2Url = resolveFileUrl(god2Filename, "uploads/god-images");
        const god2X = startX + pageWidth - imgW - 6;
        await this.drawGodImage(doc, god2Url, god2X, bodyY, imgW, imgH, "2");

        // Address Section (Centered between QR Code and God Image 2)
        const addrX = qrX + qrSize + 6;
        const addrW = god2X - addrX - 6;

        const rawLines = address.split("\n").map(l => l.trim()).filter(Boolean);
        doc.fillColor(COLORS.navy);

        let currY = bodyY + 6;
        rawLines.forEach((line, index) => {
            const font = getFont(line, true);
            const size = index === 0 ? 11 : 9.5;
            doc.font(font).fontSize(size).text(line, addrX, currY, {
                width: addrW,
                align: "center",
            });
            currY = doc.y + 2;
        });

        // ── 5. Outer Frame Border ──
        const finalHeaderY = bodyY + imgH + 6;
        const frameHeight = finalHeaderY - startY;

        doc.rect(startX, startY, pageWidth, frameHeight).lineWidth(1.2).strokeColor(COLORS.border).stroke();

        doc.y = finalHeaderY + 10;
    }

    private static async drawGodImage(
        doc: PDFKit.PDFDocument,
        url: string | null,
        x: number,
        y: number,
        w: number,
        h: number,
        num: string
    ) {
        let buf: Buffer | null = null;

        // 1. Try reading directly from local disk first
        if (url) {
            const filename = path.basename(url);
            const localPath = path.join(GOD_IMAGE_DIR, filename);
            if (fs.existsSync(localPath)) {
                try {
                    buf = fs.readFileSync(localPath);
                } catch (e) {
                    console.error(`[PdfHeader] Error reading local image ${filename}:`, e);
                }
            }
        }

        // 2. Fallback to default local file
        if (!buf) {
            const defaultPath = path.join(GOD_IMAGE_DIR, `default-god${num}.png`);
            if (fs.existsSync(defaultPath)) {
                try {
                    buf = fs.readFileSync(defaultPath);
                } catch (e) { }
            }
        }

        // 3. Fallback to any god image in directory
        if (!buf) {
            try {
                const files = fs.readdirSync(GOD_IMAGE_DIR).filter(f => f.toLowerCase().includes(`god${num}`));
                if (files.length > 0 && files[0]) {
                    buf = fs.readFileSync(path.join(GOD_IMAGE_DIR, files[0]));
                }
            } catch (e) { }
        }

        // 4. HTTP fetch fallback
        if (!buf && url && url.startsWith("http")) {
            try {
                buf = await this.fetchImageBuffer(url);
            } catch (e) {
                console.error(`[PdfHeader] HTTP fetch failed for god image ${num}:`, e);
            }
        }

        if (buf) {
            try {
                const pngBuf = await sharp(buf).png().toBuffer();
                doc.image(pngBuf, x, y, { width: w, height: h, fit: [w, h] });
                return;
            } catch (err) {
                console.error(`[PdfHeader] Sharp PNG conversion error on image ${num}, trying raw:`, err);
                try {
                    doc.image(buf, x, y, { width: w, height: h, fit: [w, h] });
                    return;
                } catch (e2) {
                    console.error(`[PdfHeader] PDFKit failed to draw god image ${num}:`, e2);
                }
            }
        }

        // Stroke box placeholder if image is missing
        doc.rect(x, y, w, h).lineWidth(0.5).strokeColor(COLORS.border).stroke();
    }

    private static fetchImageBuffer(url: string, redirectsLeft = 3): Promise<Buffer> {
        return new Promise((resolve, reject) => {
            const client = url.startsWith("https") ? https : http;
            const req = client.get(url, { timeout: 8000 }, (res) => {
                const status = res.statusCode ?? 0;
                if (status >= 300 && status < 400 && res.headers.location) {
                    res.resume();
                    if (redirectsLeft <= 0) { reject(new Error("Too many redirects")); return; }
                    resolve(this.fetchImageBuffer(new URL(res.headers.location || "", url).toString(), redirectsLeft - 1));
                    return;
                }
                if (status !== 200) { reject(new Error("Failed to fetch image")); res.resume(); return; }
                const chunks: Buffer[] = [];
                res.on("data", (c) => chunks.push(c));
                res.on("end", () => resolve(Buffer.concat(chunks)));
                res.on("error", reject);
            })
                .on("error", reject)
                .on("timeout", () => req.destroy(new Error("Timed out")));
        });
    }
}
