#!/usr/bin/env python3
"""Build a self-contained HTML rendering of an Ontology Semantic Atlas.

Usage: build_atlas_html.py <project-dir> <mermaid-bundle.js> [--atlas documentation/semantic-atlas.md] [--out documentation/semantic-atlas.html]

The bundle is Mermaid + @mermaid-js/layout-elk (registered) compiled to a single IIFE that sets
window.mermaid (see scripts/build_mermaid_bundle.sh) — so every ```mermaid block, all of which carry
the `config: layout: elk` frontmatter, is laid out by ELK with no CDN, plugin or viewer support needed.
Blocks that fail to render are replaced in-page by a visible RENDER ERROR box, and the page exposes
window.__report = {total, ok, errors:[{index, message}]} for headless checks.

Requires the `markdown` package (pip install markdown).
"""
from __future__ import annotations
import argparse, re
from pathlib import Path
import markdown

ap = argparse.ArgumentParser()
ap.add_argument("project_dir", type=Path); ap.add_argument("bundle", type=Path)
ap.add_argument("--atlas", type=Path, default=Path("documentation/semantic-atlas.md"))
ap.add_argument("--out", type=Path, default=Path("documentation/semantic-atlas.html"))
a = ap.parse_args()
proj = a.project_dir.resolve()
atlas = a.atlas if a.atlas.is_absolute() else proj / a.atlas
out = a.out if a.out.is_absolute() else proj / a.out
md_src = atlas.read_text(encoding="utf-8")
body = markdown.markdown(md_src, extensions=["tables", "fenced_code", "toc"])
# python-markdown emits <pre><code class="language-mermaid">…escaped…</code></pre>; keep the escaped text,
# Mermaid decodes entities from a <pre> element's textContent.
pat = re.compile(r'<pre><code class="language-mermaid">(.*?)</code></pre>', re.S)
n = 0
def repl(m):
    global n; n += 1
    return f'<pre class="mermaid" data-idx="{n-1}">{m.group(1)}</pre>'
body = pat.sub(repl, body)
assert n == md_src.count("```mermaid"), (n, md_src.count("```mermaid"))
title_m = re.search(r"^# (.+)$", md_src, re.M)
title = title_m.group(1) if title_m else "Ontology Semantic Atlas"
css = """
body{font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;max-width:1400px;margin:0 auto;padding:1rem 2rem;color:#1a1a1a;background:#fff;line-height:1.45}
table{border-collapse:collapse;font-size:.85rem;margin:1rem 0;display:block;overflow-x:auto}
th,td{border:1px solid #ccc;padding:.3rem .5rem;text-align:left;vertical-align:top} th{background:#f3f3f3}
pre.mermaid{background:transparent;overflow-x:auto;margin:1rem 0} pre.mermaid svg{max-width:100%;height:auto}
pre.render-error{background:#fff0f0;border:2px solid #c00;padding:1rem;white-space:pre-wrap;font-size:.8rem}
code{background:#f4f4f4;padding:0 .2em;border-radius:3px;font-size:.9em} pre:not(.mermaid) code{background:none}
h1,h2,h3{margin-top:2rem}
#status{position:fixed;top:0;right:0;background:#222;color:#fff;font:12px monospace;padding:.3rem .6rem;z-index:9}
"""
js = """
(async()=>{
  const st=document.getElementById('status');
  mermaid.initialize({startOnLoad:false, securityLevel:'strict', maxTextSize:900000, maxEdges:5000});
  const nodes=[...document.querySelectorAll('pre.mermaid')];
  const report={total:nodes.length, ok:0, errors:[]}; window.__report=report;
  for(const el of nodes){
    const idx=el.dataset.idx, src=el.textContent;
    try{ const {svg}=await mermaid.render('atlas-svg-'+idx, src); el.innerHTML=svg; report.ok++; }
    catch(e){ const p=document.createElement('pre'); p.className='render-error';
      p.textContent='RENDER ERROR (block '+idx+'): '+(e&&e.message||e)+'\\n\\n'+src;
      el.replaceWith(p); report.errors.push({index:+idx, message:String(e&&e.message||e)}); }
    st.textContent='rendered '+(report.ok+report.errors.length)+'/'+report.total+(report.errors.length?'  errors: '+report.errors.length:'');
  }
  window.__done=true;
})();
"""
doc = f"""<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>{title}</title><style>{css}</style>
<script>{a.bundle.read_text(encoding="utf-8")}</script>
</head><body><div id="status">rendering…</div>
{body}
<script>{js}</script></body></html>"""
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(doc, encoding="utf-8")
print(f"Wrote {out} — {n} mermaid blocks, {out.stat().st_size/1e6:.1f} MB")
