const crypto = require("node:crypto");
const fs = require("node:fs");
const path = require("node:path");

function sha256File(p) {
  const h = crypto.createHash("sha256");
  h.update(fs.readFileSync(p));
  return h.digest("hex");
}

function sha256String(s) {
  return crypto.createHash("sha256").update(s).digest("hex");
}

function tryReadJSON(p) {
  try {
    return JSON.parse(fs.readFileSync(p, "utf8"));
  } catch {
    return null;
  }
}

function main() {
  const root = path.resolve(__dirname, "..");
  const pkg = tryReadJSON(path.join(root, "package.json")) || {};
  const lock = tryReadJSON(path.join(root, "package-lock.json")) || {};

  const code = {
    "src/index.js": sha256File(path.join(root, "src/index.js")),
    "src/render_pdf.js": sha256File(path.join(root, "src/render_pdf.js")),
    "src/validate.js": sha256File(path.join(root, "src/validate.js")),
    "src/errors.js": sha256File(path.join(root, "src/errors.js")),
    "src/logger.js": sha256File(path.join(root, "src/logger.js")),
    "scripts/test-fixtures.js": sha256File(path.join(root, "scripts/test-fixtures.js")),
    "scripts/copy-assets.js": sha256File(path.join(root, "scripts/copy-assets.js")),
    "scripts/generate-manifest.js": sha256File(path.join(root, "scripts/generate-manifest.js"))
  };

  const assets = {
    "assets/js/mermaid.min.js": sha256File(path.join(root, "assets/js/mermaid.min.js")),
    "assets/js/paged.polyfill.js": sha256File(path.join(root, "assets/js/paged.polyfill.js")),
    "assets/css/basic.css": sha256File(path.join(root, "assets/css/basic.css")),
    "assets/css/professional.css": sha256File(path.join(root, "assets/css/professional.css")),
    "assets/fonts/ibm-plex-sans-latin-400-normal.woff2": sha256File(path.join(root, "assets/fonts/ibm-plex-sans-latin-400-normal.woff2")),
    "assets/fonts/ibm-plex-sans-latin-600-normal.woff2": sha256File(path.join(root, "assets/fonts/ibm-plex-sans-latin-600-normal.woff2")),
    "assets/fonts/ibm-plex-mono-latin-400-normal.woff2": sha256File(path.join(root, "assets/fonts/ibm-plex-mono-latin-400-normal.woff2"))
  };

  let chromePath = null;
  let chromeSha = null;
  let chromeVersion = null;
  try {
    const puppeteer = require("puppeteer");
    chromePath = puppeteer.executablePath();
    chromeSha = sha256File(chromePath);
    if (typeof puppeteer.browserVersion === "function") {
      chromeVersion = puppeteer.browserVersion();
    }
  } catch {
    // noop
  }

  const deps = (pkg && pkg.dependencies) || {};
  const manifestCore = {
    versions: {
      worker: pkg.version || "0.0.0",
      node: process.version,
      puppeteer: deps.puppeteer || null,
      mermaid: deps.mermaid || null,
      pagedjs: deps.pagedjs || null,
      markdownIt: deps["markdown-it"] || null,
      sanitizeHtml: deps["sanitize-html"] || null,
      ibmPlexSans: deps["@fontsource/ibm-plex-sans"] || null,
      ibmPlexMono: deps["@fontsource/ibm-plex-mono"] || null,
      lockfileVersion: lock.lockfileVersion || null
    },
    chromium: chromePath ? { sha256: chromeSha, version: chromeVersion || null } : null,
    code,
    assets
  };

  const canonical = JSON.stringify(manifestCore);
  const manifest = { ...manifestCore, manifest_sha: sha256String(canonical) };

  fs.writeFileSync(path.join(root, "manifest.json"), JSON.stringify(manifest, null, 2));
}

main();
