"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.exportToEpub = exportToEpub;
const path = require("path");
const fs = require("fs");
const mkdirp = require("mkdirp");
const rimraf = require("rimraf");
const uuid_1 = require("uuid");
const child_process_1 = require("child_process");
const shared_1 = require("./shared");
const getLocalizedText = (language) => {
    const translations = {
        en: "Write your answer here",
        es: "Escribe tu respuesta aquí",
        fr: "Écrivez votre réponse ici",
        de: "Schreiben Sie Ihre Antwort hier",
        it: "Scrivi la tua risposta qui",
        pt: "Escreva sua resposta aqui",
        ja: "ここに答えを書いてください",
        ko: "여기에 답을 작성하세요",
        zh: "在这里写下你的答案",
        ar: "اكتب إجابتك هنا",
        ru: "Напишите свой ответ здесь",
    };
    return translations[language] || translations.en;
};
const replaceQuestionsFromMarkdown = (markdown, language = "en") => {
    // Search for all code blocks like this (No breaking lines sensitive)
    // ```question some parameters
    // some text
    // ```
    const questionRegex = /```question([\s\S]*?)```/g;
    const localizedText = getLocalizedText(language);
    return markdown.replace(questionRegex, `<div type="text" class="open-question">${localizedText}</div>`);
};
const replaceMermaidFromMarkdown = (markdown) => {
    // Search for all code blocks like this (No breaking lines sensitive)
    // ```mermaid
    // some graphs in mermaid syntax
    // ```
    const mermaidRegex = /```mermaid([\s\S]*?)```/g;
    return markdown.replace(mermaidRegex, "");
};
const cleanQuizOptions = (markdown) => {
    // Remove [x] from quiz options, keeping only [ ] for all options
    // This handles both - [x] and - [x] patterns
    const quizRegex = /^(\s*-\s*)\[x\](\s+.*)$/gm;
    return markdown.replace(quizRegex, "$1[ ]$2");
};
// Download cover image from bucket
async function downloadCoverImage(bucket, courseSlug, outputDir) {
    try {
        const coverImagePath = path.join(outputDir, "cover.png");
        const [coverBuf] = await bucket
            .file(`courses/${courseSlug}/preview.png`)
            .download();
        fs.writeFileSync(coverImagePath, coverBuf);
        console.log("Cover image downloaded:", coverImagePath);
        return coverImagePath;
    }
    catch (error) {
        console.log("No cover image found, skipping...");
        return undefined;
    }
}
// Generate EPUB using pandoc directly from markdown files
async function generateEpub(markdownFiles, outputPath, metadata, epubMetadata, coverImagePath) {
    return new Promise((resolve, reject) => {
        var _a;
        let stdout = "";
        let stderr = "";
        const yamlPath = path.join(path.dirname(outputPath), "metadata.yaml");
        const escapeYaml = (str) => {
            if (!str)
                return "";
            return str.replace(/"/g, '\\"').replace(/\n/g, "\\n");
        };
        const yamlContent = `---
title: "${epubMetadata.title}"
creator: "${epubMetadata.creator}"
publisher: "${epubMetadata.publisher}"
rights: "${epubMetadata.rights}"
lang: "${epubMetadata.lang}"
description: "${escapeYaml(metadata.description || "")}"
subject: "${((_a = metadata.technologies) === null || _a === void 0 ? void 0 : _a.join(", ")) || "Programming"}"
---`;
        fs.writeFileSync(yamlPath, yamlContent, "utf-8");
        // Include all markdown files in the EPUB
        const pandocArgs = [
            ...markdownFiles, // All markdown files
            "-o",
            outputPath,
            "--from",
            "markdown",
            "--to",
            "epub",
            "--metadata-file",
            yamlPath,
            "--css",
            path.join(__dirname, "../templates/epub/epub.css"),
        ];
        // Add cover image if available - use absolute path
        if (coverImagePath) {
            pandocArgs.push("--epub-cover-image", coverImagePath);
        }
        console.log("🔧 Executing pandoc EPUB command:");
        console.log("Command:", "pandoc", pandocArgs.join(" "));
        const pandoc = (0, child_process_1.spawn)("pandoc", pandocArgs);
        pandoc.stdout.on("data", (data) => {
            const output = data.toString();
            stdout += output;
            console.log("📤 Pandoc STDOUT:", output);
        });
        pandoc.stderr.on("data", (data) => {
            const output = data.toString();
            stderr += output;
            console.log("⚠️ Pandoc STDERR:", output);
        });
        pandoc.on("close", (code) => {
            console.log(`🏁 Pandoc process finished with exit code: ${code}`);
            if (code === 0) {
                console.log("✅ EPUB generation successful!");
                resolve();
            }
            else {
                const errorMessage = `Pandoc process exited with code ${code}\n\nSTDOUT:\n${stdout}\n\nSTDERR:\n${stderr}`;
                console.error("❌ Pandoc Error Details:", errorMessage);
                reject(new Error(errorMessage));
            }
        });
        pandoc.on("error", (err) => {
            console.error("❌ Pandoc spawn error:", err);
            reject(err);
        });
    });
}
// Process exercises and collect markdown files for direct EPUB conversion
async function processExercises(exercisesDir, outputDir, language = "en", learnAssetsDir) {
    const processedMarkdownFiles = [];
    console.log("Processing exercises directory:", exercisesDir);
    console.log("Output directory:", outputDir);
    console.log("Language:", language);
    console.log("Learn assets directory:", learnAssetsDir);
    if (!fs.existsSync(exercisesDir)) {
        console.log("Exercises directory does not exist:", exercisesDir);
        return processedMarkdownFiles;
    }
    console.log("Exercises directory exists, scanning for files...");
    const processDirectory = async (dir, relativePath = "") => {
        console.log(`🔍 Processing directory: ${dir} (relative: ${relativePath})`);
        const entries = fs.readdirSync(dir, { withFileTypes: true });
        console.log(`📁 Found ${entries.length} entries in ${dir}:`, entries.map((e) => e.name));
        // Sort entries to prioritize README files first
        entries.sort((a, b) => {
            const aName = a.name.toLowerCase();
            const bName = b.name.toLowerCase();
            // Prioritize README files
            if (aName === "readme.md" && bName !== "readme.md")
                return -1;
            if (bName === "readme.md" && aName !== "readme.md")
                return 1;
            return aName.localeCompare(bName);
        });
        for (const entry of entries) {
            const fullPath = path.join(dir, entry.name);
            const relativeFilePath = path.join(relativePath, entry.name);
            if (entry.isDirectory()) {
                console.log("Processing subdirectory:", relativeFilePath);
                // esling-disable-next-line
                await processDirectory(fullPath, relativeFilePath);
            }
            else if (entry.name.endsWith(".md") ||
                entry.name.endsWith(".markdown")) {
                // Apply language filtering for all markdown files
                const baseName = entry.name.replace(/\.(md|markdown)$/, "");
                if (language === "en") {
                    // For English: only include README.md and files without language suffixes
                    if (entry.name.toLowerCase() === "readme.md") {
                        console.log(`✅ Including English README: ${relativeFilePath}`);
                    }
                    else if (baseName.includes(".") &&
                        /\.(es|fr|de|it|pt|ja|ko|zh|ar|ru)$/i.test(baseName)) {
                        console.log(`❌ Skipping language-specific file for English: ${relativeFilePath}`);
                        continue;
                    }
                    else {
                        console.log(`✅ Including English file: ${relativeFilePath}`);
                    }
                }
                else {
                    // For other languages: only include files with the correct language suffix
                    if (entry.name.toLowerCase() === "readme.md") {
                        console.log(`❌ Skipping English README for language ${language}: ${relativeFilePath}`);
                        continue;
                    }
                    else if (!baseName.endsWith(`.${language}`)) {
                        console.log(`❌ Skipping file with different language: ${relativeFilePath}`);
                        continue;
                    }
                    else {
                        console.log(`✅ Including ${language} file: ${relativeFilePath}`);
                    }
                }
                // Process markdown content and save to output directory
                console.log("Processing markdown file:", relativeFilePath);
                const processedContent = processMarkdownContent(fullPath, learnAssetsDir, language);
                const processedMarkdownPath = path.join(outputDir, relativeFilePath.replace(/\.(md|markdown)$/, ".processed.md"));
                console.log("Processed markdown output path:", processedMarkdownPath);
                mkdirp.sync(path.dirname(processedMarkdownPath));
                fs.writeFileSync(processedMarkdownPath, processedContent, "utf-8");
                processedMarkdownFiles.push(processedMarkdownPath);
                console.log("Successfully processed:", relativeFilePath, "->", processedMarkdownPath);
            }
            else if (entry.name.endsWith(".html")) {
                // Convert HTML files to markdown for consistency
                console.log("Converting HTML file to markdown:", relativeFilePath);
                const htmlContent = fs.readFileSync(fullPath, "utf-8");
                const processedMarkdownPath = path.join(outputDir, relativeFilePath.replace(/\.html$/, ".processed.md"));
                mkdirp.sync(path.dirname(processedMarkdownPath));
                fs.writeFileSync(processedMarkdownPath, htmlContent, "utf-8");
                processedMarkdownFiles.push(processedMarkdownPath);
                console.log("Successfully converted HTML:", relativeFilePath, "->", processedMarkdownPath);
            }
            else {
                console.log("Skipping file:", relativeFilePath, "(not markdown or HTML)");
            }
        }
    };
    await processDirectory(exercisesDir);
    return processedMarkdownFiles;
}
// Process markdown content for EPUB conversion
function processMarkdownContent(markdownPath, learnAssetsDir, language = "en") {
    let markdownContent = fs.readFileSync(markdownPath, "utf-8");
    if (learnAssetsDir && fs.existsSync(learnAssetsDir)) {
        // Find all image references in markdown
        const imageRegex = /!\[([^\]]*)\]\(([^)]+)\)/g;
        let match;
        while ((match = imageRegex.exec(markdownContent)) !== null) {
            const [fullMatch, altText, imagePath] = match;
            // Check if it's a relative path starting with /learn/assets/
            if (imagePath.startsWith("/.learn/assets/")) {
                const imageName = path.basename(imagePath);
                const absoluteImagePath = path.join(learnAssetsDir, imageName);
                console.log(`📸 Looking for image: ${imageName}`);
                console.log(`📁 Learn assets dir: ${learnAssetsDir}`);
                console.log(`📁 Absolute path: ${absoluteImagePath}`);
                console.log(`📁 Path exists: ${fs.existsSync(absoluteImagePath)}`);
                if (fs.existsSync(absoluteImagePath)) {
                    // Use absolute path for the image
                    console.log(`✅ Found image, replacing path: ${imagePath} -> ${absoluteImagePath}`);
                    markdownContent = markdownContent.replace(fullMatch, `![${altText}](${absoluteImagePath})`);
                }
                else {
                    console.log(`❌ Image not found: ${absoluteImagePath}`);
                    // List files in the assets directory for debugging
                    if (fs.existsSync(learnAssetsDir)) {
                        const files = fs.readdirSync(learnAssetsDir);
                        console.log(`📁 Files in assets directory: ${files.join(", ")}`);
                    }
                    else {
                        console.log(`❌ Assets directory does not exist: ${learnAssetsDir}`);
                    }
                }
            }
        }
    }
    markdownContent = replaceQuestionsFromMarkdown(markdownContent, language);
    markdownContent = replaceMermaidFromMarkdown(markdownContent);
    markdownContent = cleanQuizOptions(markdownContent);
    return markdownContent;
}
const titlelify = (title) => {
    return title.replace(/[-_]/g, " ").replace(/\b\w/g, (l) => l.toUpperCase());
};
// Read sidebar.json to get exercise titles
function readSidebarData(learnDir) {
    try {
        const sidebarPath = path.join(learnDir, "sidebar.json");
        if (fs.existsSync(sidebarPath)) {
            const sidebarContent = fs.readFileSync(sidebarPath, "utf-8");
            return JSON.parse(sidebarContent);
        }
    }
    catch (error) {
        console.log("⚠️ Could not read sidebar.json:", error);
    }
    return null;
}
async function exportToEpub(options, epubMetadata) {
    var _a, _b, _c;
    const { courseSlug, bucket, outDir, language = "en" } = options;
    console.log("🚀 Starting EPUB export for course:", courseSlug);
    console.log("📁 Output directory:", outDir);
    console.log("🌍 Language:", language);
    console.log("📋 EPUB Metadata:", epubMetadata);
    // 1. Create temporary folder
    const tmpName = (0, uuid_1.v4)();
    const epubOutDir = path.join(outDir, tmpName);
    rimraf.sync(epubOutDir);
    mkdirp.sync(epubOutDir);
    console.log("Created temporary directory:", epubOutDir);
    // 2. Create EPUB template directory
    const epubTemplateDir = path.join(epubOutDir, "template");
    mkdirp.sync(epubTemplateDir);
    // 3. Download exercises, .learn, and cover image from bucket
    console.log("📥 Downloading exercises...");
    await (0, shared_1.downloadS3Folder)(bucket, `courses/${courseSlug}/exercises/`, path.join(epubOutDir, "exercises"));
    console.log("✅ Exercises downloaded successfully");
    console.log("📥 Downloading .learn files...");
    await (0, shared_1.downloadS3Folder)(bucket, `courses/${courseSlug}/.learn/`, path.join(epubOutDir, "learn"));
    console.log("✅ .learn files downloaded successfully");
    console.log("📥 Downloading cover image...");
    const coverImagePath = await downloadCoverImage(bucket, courseSlug, epubOutDir);
    console.log("✅ Cover image download completed:", coverImagePath ? "Found" : "Not found");
    // 4. Read learn.json for course info
    console.log("Reading course metadata...");
    const learnJson = await (0, shared_1.getCourseMetadata)(bucket, courseSlug);
    const metadata = {
        title: ((_a = learnJson.title) === null || _a === void 0 ? void 0 : _a[epubMetadata.lang]) || courseSlug,
        description: ((_b = learnJson.description) === null || _b === void 0 ? void 0 : _b[epubMetadata.lang]) || learnJson.description,
        language: epubMetadata.lang,
        technologies: learnJson.technologies || [],
        difficulty: learnJson.difficulty || "beginner",
    };
    console.log("Course metadata:", metadata);
    // 5. Process exercises and prepare markdown files
    console.log("🔄 Processing exercises and preparing markdown files...");
    // First, let's see what files were downloaded
    const exercisesPath = path.join(epubOutDir, "exercises");
    console.log("📂 Exercises directory contents:");
    if (fs.existsSync(exercisesPath)) {
        const exerciseDirs = fs.readdirSync(exercisesPath, { withFileTypes: true });
        console.log(`Found ${exerciseDirs.length} exercise directories:`);
        exerciseDirs.forEach((dir) => {
            if (dir.isDirectory()) {
                const dirPath = path.join(exercisesPath, dir.name);
                const files = fs.readdirSync(dirPath);
                console.log(`  📁 ${dir.name}: ${files.length} files - ${files.join(", ")}`);
            }
        });
    }
    else {
        console.log("❌ Exercises directory does not exist!");
    }
    const processedMarkdownFiles = await processExercises(path.join(epubOutDir, "exercises"), path.join(epubOutDir, "processed"), language, path.join(epubOutDir, "learn", "assets"));
    // 6. Read sidebar data and create table of contents
    const sidebarData = readSidebarData(path.join(epubOutDir, "learn"));
    console.log("📋 Sidebar data loaded:", sidebarData ? "Success" : "Not found");
    // 7. Create main content file as markdown
    const mainContent = `# ${metadata.title}

${metadata.description || ""}

**Technologies:** ${((_c = metadata.technologies) === null || _c === void 0 ? void 0 : _c.join(", ")) || "Programming"}

**Difficulty:** ${metadata.difficulty}

**Language:** ${language}

---

## Table of Contents

${processedMarkdownFiles
        .map((file, index) => {
        const fileName = path.basename(file, ".processed.md");
        const parentDir = path.basename(path.dirname(file));
        // Get the title from sidebar.json using the parent directory name
        let displayName = fileName;
        if (sidebarData && sidebarData[parentDir]) {
            displayName =
                sidebarData[parentDir][language] ||
                    sidebarData[parentDir]["en"] ||
                    titlelify(parentDir);
        }
        else {
            displayName = titlelify(parentDir);
        }
        return `${index + 1}. ${displayName}`;
    })
        .join("\n")}

---

`;
    const mainContentPath = path.join(epubOutDir, "processed", "main.md");
    mkdirp.sync(path.dirname(mainContentPath));
    fs.writeFileSync(mainContentPath, mainContent, "utf-8");
    // 8. Prepare all markdown files for EPUB generation
    const allMarkdownFiles = [mainContentPath, ...processedMarkdownFiles];
    // 9. Generate EPUB using pandoc
    console.log("📖 Generating EPUB file...");
    const epubPath = path.join(epubOutDir, `${courseSlug}.epub`);
    await generateEpub(allMarkdownFiles, epubPath, metadata, epubMetadata, coverImagePath);
    console.log("EPUB generated successfully:", epubPath);
    // Clean up temporary files
    console.log("Cleaning up temporary files...");
    rimraf.sync(path.join(epubOutDir, "processed"));
    rimraf.sync(path.join(epubOutDir, "exercises"));
    rimraf.sync(path.join(epubOutDir, "learn"));
    console.log("EPUB export completed successfully");
    return epubPath;
}
