import fs from "fs";
import path from "path";
import puppeteer from "puppeteer";
import { GraphAILogger, sleep } from "graphai";
import { MulmoPresentationStyleMethods } from "../methods/index.js";
import { localizedText, isHttp } from "../utils/utils.js";
import { getOutputPdfFilePath, writingMessage, getHTMLFile, mulmoCreditPath } from "../utils/file.js";
import { interpolate } from "../utils/html_render.js";
import { MulmoStudioContextMethods } from "../methods/mulmo_studio_context.js";
const isCI = process.env.CI === "true";
const getPdfSize = (pdfSize) => {
    return pdfSize === "a4" ? "A4" : "Letter";
};
const loadImage = async (imagePath, index) => {
    try {
        const imageData = isHttp(imagePath) ? Buffer.from(await (await fetch(imagePath)).arrayBuffer()) : fs.readFileSync(imagePath);
        const ext = path.extname(imagePath).toLowerCase().replace(".", "");
        const mimeType = ext === "jpg" ? "jpeg" : ext;
        return `data:image/${mimeType};base64,${imageData.toString("base64")}`;
    }
    catch (error) {
        GraphAILogger.info(`loadImage failed: file: ${imagePath} index: ${index}`, error);
        const placeholderData = fs.readFileSync(mulmoCreditPath());
        return `data:image/png;base64,${placeholderData.toString("base64")}`;
    }
};
const formatTextAsParagraphs = (text) => text
    .split("\n")
    .map((line) => `<p>${line}</p>`)
    .join("");
const generateSlideHTML = (imageDataUrls) => imageDataUrls
    .map((imageUrl) => `
      <div class="page">
        <img src="${imageUrl}" alt="">
      </div>`)
    .join("");
const generateTalkHTML = (imageDataUrls, texts) => imageDataUrls
    .map((imageUrl, index) => `
      <div class="page">
        <div class="image-container">
          <img src="${imageUrl}" alt="">
        </div>
        <div class="text-container">
          ${formatTextAsParagraphs(texts[index])}
        </div>
      </div>`)
    .join("");
const generateHandoutHTML = (imageDataUrls, texts) => {
    const itemsPerPage = 4;
    const pages = [];
    for (let i = 0; i < imageDataUrls.length; i += itemsPerPage) {
        const pageItems = Array.from({ length: itemsPerPage }, (_, j) => {
            const index = i + j;
            const hasContent = index < imageDataUrls.length;
            if (hasContent) {
                return `
          <div class="handout-item">
            <div class="handout-image">
              <img src="${imageDataUrls[index]}" alt="">
            </div>
            <div class="handout-text">
              ${formatTextAsParagraphs(texts[index])}
            </div>
          </div>`;
            }
            else {
                // Empty slot to maintain 4-item grid layout
                return `
          <div class="handout-item">
            <div class="handout-image"></div>
            <div class="handout-text"></div>
          </div>`;
            }
        }).join("");
        pages.push(`<div class="page">${pageItems}</div>`);
    }
    return pages.join("");
};
const generatePagesHTML = (pdfMode, imageDataUrls, texts) => {
    switch (pdfMode) {
        case "slide":
            return generateSlideHTML(imageDataUrls);
        case "talk":
            return generateTalkHTML(imageDataUrls, texts);
        case "handout":
            return generateHandoutHTML(imageDataUrls, texts);
        default:
            return "";
    }
};
const getHandoutTemplateData = (isLandscapeImage) => ({
    page_layout: isLandscapeImage ? "flex" : "grid",
    page_direction: isLandscapeImage ? "flex-direction: column;" : "grid-template-columns: repeat(4, 1fr);",
    flex_direction: isLandscapeImage ? "row" : "column",
    image_size: isLandscapeImage ? "width: 45%;" : "height: 60%;",
    text_size: isLandscapeImage ? "width: 55%;" : "height: 40%;",
    item_flex: isLandscapeImage ? "flex: 1;" : "",
});
const resolvePageSize = (pdfMode, pdfSize, imageWidth, imageHeight, isLandscape) => {
    if (pdfMode === "slide")
        return `${imageWidth}px ${imageHeight}px`;
    if (pdfMode === "handout")
        return `${getPdfSize(pdfSize)} portrait`;
    return `${getPdfSize(pdfSize)} ${isLandscape ? "landscape" : "portrait"}`;
};
const generatePDFHTML = async (context, pdfMode, pdfSize) => {
    const { studio, multiLingual, lang = "en" } = context;
    const { width: imageWidth, height: imageHeight } = MulmoPresentationStyleMethods.getCanvasSize(context.presentationStyle);
    const isLandscapeImage = imageWidth > imageHeight;
    const imageFiles = studio.beats.map((beat) => beat.htmlImageFile ?? beat.imageFile);
    const texts = studio.script.beats.map((beat, index) => localizedText(beat, multiLingual?.[index], lang));
    const imageDataUrls = await Promise.all(imageFiles.map(loadImage));
    const pageSize = resolvePageSize(pdfMode, pdfSize, imageWidth, imageHeight, isLandscapeImage);
    const pagesHTML = generatePagesHTML(pdfMode, imageDataUrls, texts);
    const template = getHTMLFile(`pdf_${pdfMode}`);
    const baseTemplateData = {
        lang,
        title: studio.script.title || "MulmoCast PDF",
        page_size: pageSize,
        pages: pagesHTML,
    };
    const templateData = pdfMode === "handout" ? { ...baseTemplateData, ...getHandoutTemplateData(isLandscapeImage) } : baseTemplateData;
    return interpolate(template, templateData);
};
const zeroMargin = { top: "0", bottom: "0", left: "0", right: "0" };
const createPDFOptions = (pdfSize, pdfMode, canvasSize) => {
    if (pdfMode === "slide") {
        return { width: `${canvasSize.width}px`, height: `${canvasSize.height}px`, margin: zeroMargin };
    }
    const baseOptions = { format: getPdfSize(pdfSize), margin: zeroMargin };
    return pdfMode === "handout" ? { ...baseOptions, landscape: false } : baseOptions;
};
export const pdfFilePath = (context, pdfMode) => {
    const { studio, fileDirs, lang = "en" } = context;
    return getOutputPdfFilePath(fileDirs.outDirPath, studio.filename, pdfMode, lang);
};
const PDF_CONTENT_TIMEOUT_MS = 60000;
const generatePDF = async (context, pdfMode, pdfSize) => {
    const outputPdfPath = pdfFilePath(context, pdfMode);
    const html = await generatePDFHTML(context, pdfMode, pdfSize);
    const canvasSize = MulmoPresentationStyleMethods.getCanvasSize(context.presentationStyle);
    const pdfOptions = createPDFOptions(pdfSize, pdfMode, canvasSize);
    const browser = await puppeteer.launch({
        args: isCI ? ["--no-sandbox"] : [],
    });
    try {
        const page = await browser.newPage();
        await page.setContent(html, { waitUntil: "domcontentloaded", timeout: PDF_CONTENT_TIMEOUT_MS });
        await sleep(1000);
        await page.pdf({
            path: outputPdfPath,
            printBackground: true,
            ...pdfOptions,
        });
        writingMessage(outputPdfPath);
    }
    finally {
        await browser.close();
    }
};
export const pdf = async (context, pdfMode, pdfSize) => {
    try {
        MulmoStudioContextMethods.setSessionState(context, "pdf", true);
        await generatePDF(context, pdfMode, pdfSize);
        MulmoStudioContextMethods.setSessionState(context, "pdf", false, true);
    }
    catch (error) {
        MulmoStudioContextMethods.setSessionState(context, "pdf", false, false);
        throw error;
    }
};
