import type { jsPDF } from "jspdf";

/** Data for the shared, branded report cover page. */
export type ReportCoverData = {
  title: string;
  date: string;
  companyName: string;
  preparedBy: string;
  logoUrl?: string;
  bgUrl?: string;
};

/** Load an image URL as a data URL for jsPDF embedding (browser only). */
export function loadImageAsDataURL(
  url: string,
  format: "jpeg" | "png" = "jpeg",
): Promise<{ dataURL: string; w: number; h: number } | null> {
  return new Promise((resolve) => {
    if (!url) return resolve(null);
    const img = new Image();
    img.crossOrigin = "anonymous";
    img.onload = () => {
      const canvas = document.createElement("canvas");
      canvas.width = img.width;
      canvas.height = img.height;
      const ctx = canvas.getContext("2d");
      if (format === "jpeg") {
        ctx!.fillStyle = "#ffffff";
        ctx!.fillRect(0, 0, canvas.width, canvas.height);
      }
      ctx?.drawImage(img, 0, 0);
      const mime = format === "png" ? "image/png" : "image/jpeg";
      resolve({ dataURL: canvas.toDataURL(mime, 0.85), w: img.width, h: img.height });
    };
    img.onerror = () => resolve(null);
    img.src = url;
  });
}

/**
 * Draw the shared branded cover page on the current page of `doc`.
 * Used by the general Report Generator and all financial reports so every
 * exported report opens with the same look.
 */
export async function drawReportCoverPage(
  doc: jsPDF,
  W: number,
  H: number,
  cover: ReportCoverData,
): Promise<void> {
  const cx = W / 2;
  const headerH = H * 0.42;
  const pdfFont = doc.getFontList()["Open Sans"] ? "Open Sans" : "helvetica";

  const bgImg = cover.bgUrl ? await loadImageAsDataURL(cover.bgUrl, "jpeg") : null;
  if (bgImg) {
    const imgAspect = bgImg.w / bgImg.h;
    const headerAspect = W / headerH;
    let drawW = W, drawH = headerH, drawX = 0, drawY = 0;
    if (imgAspect > headerAspect) {
      drawH = headerH;
      drawW = headerH * imgAspect;
      drawX = -(drawW - W) / 2;
    } else {
      drawW = W;
      drawH = W / imgAspect;
      drawY = -(drawH - headerH) / 2;
    }
    doc.addImage(bgImg.dataURL, "JPEG", drawX, drawY, drawW, drawH);
  } else {
    doc.setFillColor(30, 41, 59);
    doc.rect(0, 0, W, headerH, "F");
  }

  doc.setFillColor(37, 99, 235);
  doc.rect(0, headerH, W, 4, "F");

  let y = headerH + 14;

  const logoImg = cover.logoUrl ? await loadImageAsDataURL(cover.logoUrl, "png") : null;
  if (logoImg) {
    const logoH = 50;
    const logoW = logoH * (logoImg.w / logoImg.h);
    doc.addImage(logoImg.dataURL, "PNG", cx - logoW / 2, y, logoW, logoH);
    y += logoH + 24;
  }

  doc.setFont(pdfFont, "bold");
  doc.setFontSize(28);
  doc.setTextColor(15, 23, 42);
  const titleLines = doc.splitTextToSize(cover.title.replace(/\n/g, " "), W - 100);
  doc.text(titleLines, cx, y, { align: "center", lineHeightFactor: 1.3 });
  y += titleLines.length * 32 + 8;

  doc.setFillColor(37, 99, 235);
  doc.rect(cx - 30, y, 60, 3, "F");
  y += 24;

  doc.setFont(pdfFont, "bold");
  doc.setFontSize(9);
  doc.setTextColor(100, 116, 139);
  doc.text("PREPARED FOR", cx, y, { align: "center" });
  y += 22;

  doc.setFont(pdfFont, "bold");
  doc.setFontSize(22);
  doc.setTextColor(30, 41, 59);
  const compLines = doc.splitTextToSize(cover.companyName || "Association Name", W - 120);
  doc.text(compLines, cx, y, { align: "center" });
  y += compLines.length * 26 + 20;

  doc.setFillColor(248, 250, 252);
  doc.setDrawColor(226, 232, 240);
  const dateW = 200;
  doc.roundedRect(cx - dateW / 2, y, dateW, 32, 3, 3, "FD");
  doc.setFont(pdfFont, "bold");
  doc.setFontSize(11);
  doc.setTextColor(15, 23, 42);
  doc.text(cover.date, cx, y + 21, { align: "center" });

  const footY = H - 60;
  doc.setDrawColor(226, 232, 240);
  doc.setLineWidth(0.5);
  doc.line(60, footY, W - 60, footY);
  doc.setFont(pdfFont, "bold");
  doc.setFontSize(8);
  doc.setTextColor(100, 116, 139);
  doc.text("PREPARED BY", cx, footY + 16, { align: "center" });
  doc.setFont(pdfFont, "bold");
  doc.setFontSize(12);
  doc.setTextColor(30, 41, 59);
  doc.text(cover.preparedBy || "", cx, footY + 32, { align: "center" });
}
