const fs = require("fs");
const path = require("path");
const { marked } = require("marked");

function escapeHtml(s) {
  return s
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;");
}

function stripHtml(s) {
  return s.replace(/<[^>]*>/g, "");
}

function buildToc(items) {
  if (items.length === 0) return "";
  let html = "";
  let prevDepth = 0;
  for (const item of items) {
    if (item.depth > prevDepth) {
      for (let i = prevDepth; i < item.depth; i++) html += "<ul>";
    } else if (item.depth < prevDepth) {
      for (let i = item.depth; i < prevDepth; i++) html += "</ul>";
    }
    html += `<li><a href="#${item.slug}">${escapeHtml(item.text)}</a></li>\n`;
    prevDepth = item.depth;
  }
  for (let i = 0; i < prevDepth; i++) html += "</ul>";
  return html;
}

function markdownToHtml(md) {
  const renderer = new marked.Renderer();
  const defaultCode = renderer.code.bind(renderer);

  renderer.code = function ({ text, lang }) {
    if (lang === "mermaid") {
      return `<pre class="mermaid">${escapeHtml(text)}</pre>\n`;
    }
    return defaultCode({ text, lang });
  };

  const tocItems = [];
  renderer.heading = function ({ text, depth }) {
    const slug = text
      .toLowerCase()
      .replace(/<[^>]*>/g, "")
      .replace(/[^\w\s-]/g, "")
      .replace(/\s+/g, "-")
      .replace(/-+/g, "-")
      .trim();
    tocItems.push({ text: stripHtml(text), depth, slug });
    return `<h${depth} id="${slug}">${text}</h${depth}>\n`;
  };

  marked.setOptions({ renderer, gfm: true, breaks: false });
  const bodyHtml = marked.parse(md);
  const tocHtml = buildToc(tocItems);
  const docTitle = tocItems.length > 0 ? tocItems[0].text : "Document";

  return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${escapeHtml(docTitle)}</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 16px; scroll-behavior: smooth; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  color: #24292f;
  background: #ffffff;
  line-height: 1.6;
  display: flex;
  min-height: 100vh;
}
#toc-sidebar {
  position: fixed;
  top: 0; left: 0;
  width: 280px;
  height: 100vh;
  overflow-y: auto;
  background: #f6f8fa;
  border-right: 1px solid #d0d7de;
  padding: 20px 16px;
  font-size: 0.85rem;
  z-index: 10;
}
#toc-sidebar ul { list-style: none; padding-left: 0; }
#toc-sidebar ul ul { padding-left: 16px; }
#toc-sidebar li { margin: 3px 0; }
#toc-sidebar a {
  color: #0969da;
  text-decoration: none;
  display: block;
  padding: 2px 6px;
  border-radius: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#toc-sidebar a:hover { background: #ddf4ff; }
#toc-sidebar a.active { background: #0969da; color: #fff; }
#toc-toggle {
  display: none;
  position: fixed;
  top: 12px; left: 12px;
  z-index: 20;
  background: #f6f8fa;
  border: 1px solid #d0d7de;
  border-radius: 6px;
  padding: 6px 10px;
  cursor: pointer;
  font-size: 1.1rem;
}
#content {
  margin-left: 280px;
  max-width: 920px;
  padding: 40px 48px 80px;
  width: 100%;
}
h1, h2, h3, h4, h5, h6 {
  margin-top: 1.8em;
  margin-bottom: 0.6em;
  font-weight: 600;
  line-height: 1.25;
  color: #1f2328;
}
h1 { font-size: 2em; border-bottom: 1px solid #d0d7de; padding-bottom: 0.3em; }
h2 { font-size: 1.5em; border-bottom: 1px solid #d0d7de; padding-bottom: 0.3em; }
h3 { font-size: 1.25em; }
h1:first-child { margin-top: 0; }
p { margin: 0 0 1em; }
a { color: #0969da; text-decoration: none; }
a:hover { text-decoration: underline; }
strong { font-weight: 600; }
hr { border: none; border-top: 1px solid #d0d7de; margin: 2em 0; }
ul, ol { margin: 0 0 1em 2em; }
li + li { margin-top: 0.25em; }
table {
  border-collapse: collapse;
  width: 100%;
  margin: 0 0 1em;
  font-size: 0.9rem;
}
th, td { border: 1px solid #d0d7de; padding: 8px 12px; text-align: left; }
th { background: #f6f8fa; font-weight: 600; }
tr:nth-child(even) { background: #f6f8fa; }
code {
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  font-size: 0.875em;
  background: #f6f8fa;
  padding: 0.2em 0.4em;
  border-radius: 4px;
}
pre {
  background: #f6f8fa;
  border: 1px solid #d0d7de;
  border-radius: 6px;
  padding: 16px;
  overflow-x: auto;
  margin: 0 0 1em;
  line-height: 1.45;
}
pre code { background: none; padding: 0; font-size: 0.85rem; }
pre.mermaid {
  background: #fff;
  border: 1px solid #d0d7de;
  text-align: center;
  padding: 20px;
}
@media (max-width: 900px) {
  #toc-sidebar { transform: translateX(-100%); transition: transform 0.25s; }
  #toc-sidebar.open { transform: translateX(0); }
  #toc-toggle { display: block; }
  #content { margin-left: 0; padding: 40px 24px 80px; }
}
@media print {
  #toc-sidebar, #toc-toggle { display: none; }
  #content { margin-left: 0; max-width: 100%; padding: 0; }
  pre.mermaid { border: none; }
  h1, h2 { break-after: avoid; }
  table { break-inside: avoid; }
}
</style>
</head>
<body>
<button id="toc-toggle" onclick="document.getElementById('toc-sidebar').classList.toggle('open')" aria-label="Toggle table of contents">&#9776;</button>
<nav id="toc-sidebar">
${tocHtml}
</nav>
<main id="content">
${bodyHtml}
</main>
<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
<script>
  mermaid.initialize({
    startOnLoad: true,
    theme: "default",
    flowchart: { useMaxWidth: true, htmlLabels: true, curve: "basis" },
    securityLevel: "loose"
  });
</script>
<script>
(function () {
  const links = document.querySelectorAll("#toc-sidebar a");
  const headings = [];
  links.forEach(function (a) {
    const id = a.getAttribute("href").slice(1);
    const el = document.getElementById(id);
    if (el) headings.push({ el: el, a: a });
  });
  if (headings.length === 0) return;
  function onScroll() {
    let current = headings[0];
    for (const h of headings) {
      if (h.el.getBoundingClientRect().top <= 80) current = h;
    }
    links.forEach(function (a) { a.classList.remove("active"); });
    current.a.classList.add("active");
  }
  window.addEventListener("scroll", onScroll, { passive: true });
  onScroll();
})();
</script>
</body>
</html>`;
}

async function htmlToPdf(html) {
  const puppeteer = require("puppeteer-core");

  const browser = await puppeteer.launch({
    executablePath: process.env.CHROME_PATH || "/usr/bin/google-chrome-stable",
    args: ["--no-sandbox", "--disable-setuid-sandbox"],
  });
  const page = await browser.newPage();

  const htmlForPdf = html.replace(
    /<script src="https:\/\/cdn\.jsdelivr\.net\/npm\/mermaid@[^"]*"><\/script>/,
    ""
  );
  await page.setContent(htmlForPdf, { waitUntil: "domcontentloaded" });

  const hasMermaid = await page.evaluate(
    () => document.querySelectorAll("pre.mermaid").length > 0
  );
  if (hasMermaid) {
    const mermaidJs = fs.readFileSync(
      path.join(__dirname, "mermaid.min.js"),
      "utf-8"
    );
    await page.addScriptTag({ content: mermaidJs });
    await page.evaluate(() => {
      mermaid.initialize({
        startOnLoad: false,
        theme: "default",
        flowchart: { useMaxWidth: true, htmlLabels: true, curve: "basis" },
        securityLevel: "loose",
      });
      return mermaid.run({ querySelector: "pre.mermaid" });
    });
  }

  const pdfBuffer = await page.pdf({
    format: "A4",
    printBackground: true,
    margin: { top: "20mm", bottom: "20mm", left: "15mm", right: "15mm" },
  });
  await browser.close();
  return pdfBuffer;
}

module.exports = { markdownToHtml, htmlToPdf };
