/**
 * Generate example projects for all LaTeX templates.
 *
 * Usage:  pnpm --filter @claude-prism/desktop generate-previews
 *
 * Requires pdflatex to be installed (part of TeX Live / MacTeX).
 * Output: public/examples/{template-id}/main.tex, main.pdf, references.bib (if applicable)
 */

import { execSync } from "node:child_process";
import fs from "node:fs";
import path from "node:path";
import os from "node:os";
import { fileURLToPath } from "node:url";

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

// Import template registry (pure data, no DOM dependencies)
const registryPath = path.resolve(__dirname, "../src/lib/template-registry.ts");

// Since this is a .ts file with exports, we rely on tsx to handle it
async function loadTemplates() {
  const mod = await import(registryPath);
  return mod.getAllTemplates() as Array<{
    id: string;
    name: string;
    mainFileName: string;
    content: string;
    hasBibliography: boolean;
  }>;
}

const EXAMPLES_DIR = path.resolve(__dirname, "../public/examples");
const COMPILE_TIMEOUT = 30_000;

async function main() {
  console.log("Generating example projects...\n");

  const templates = await loadTemplates();
  let successCount = 0;
  let failCount = 0;

  for (const template of templates) {
    process.stdout.write(`  ${template.id}... `);

    const exampleDir = path.join(EXAMPLES_DIR, template.id);
    fs.mkdirSync(exampleDir, { recursive: true });

    const tmpDir = fs.mkdtempSync(
      path.join(os.tmpdir(), `prism-preview-${template.id}-`),
    );

    try {
      // Write .tex file (inject \null for blank templates to force a page)
      let content = template.content;
      if (template.id === "blank") {
        content = content.replace(
          "\\begin{document}",
          "\\begin{document}\n\\null",
        );
      }
      const texPath = path.join(tmpDir, template.mainFileName);
      fs.writeFileSync(texPath, content, "utf-8");

      // Write stub .bib if template uses bibliography
      if (template.hasBibliography) {
        fs.writeFileSync(
          path.join(tmpDir, "references.bib"),
          "% empty bibliography\n",
          "utf-8",
        );
      }

      const cmd = [
        "pdflatex",
        "-interaction=nonstopmode",
        `-output-directory=${tmpDir}`,
        texPath,
      ].join(" ");

      // First pass
      execSync(cmd, { cwd: tmpDir, timeout: COMPILE_TIMEOUT, stdio: "pipe" });

      // Second pass (for TOC, references, etc.)
      try {
        execSync(cmd, { cwd: tmpDir, timeout: COMPILE_TIMEOUT, stdio: "pipe" });
      } catch {
        // Second pass failure is non-fatal
      }

      // Copy source files to example folder
      fs.copyFileSync(texPath, path.join(exampleDir, template.mainFileName));
      if (template.hasBibliography) {
        fs.copyFileSync(
          path.join(tmpDir, "references.bib"),
          path.join(exampleDir, "references.bib"),
        );
      }

      // Copy compiled PDF to example folder
      const pdfName = template.mainFileName.replace(/\.tex$/, ".pdf");
      const pdfPath = path.join(tmpDir, pdfName);

      if (fs.existsSync(pdfPath)) {
        fs.copyFileSync(pdfPath, path.join(exampleDir, pdfName));
        const sizeKb = Math.round(
          fs.statSync(path.join(exampleDir, pdfName)).size / 1024,
        );
        console.log(`OK (${sizeKb} KB)`);
        successCount++;
      } else {
        console.log("WARN: no PDF output");
        failCount++;
      }
    } catch (err) {
      const msg =
        err instanceof Error ? err.message.slice(0, 120) : String(err);
      console.log(`FAIL: ${msg}`);
      failCount++;
    } finally {
      fs.rmSync(tmpDir, { recursive: true, force: true });
    }
  }

  console.log(`\nDone: ${successCount} succeeded, ${failCount} failed`);
  if (failCount > 0) {
    console.log(
      "Note: Failed templates may require document classes not installed in your TeX distribution.",
    );
    console.log(
      "The gallery will show CSS fallback thumbnails for those templates.",
    );
  }
}

main().catch((err) => {
  console.error("Fatal error:", err);
  process.exit(1);
});
