"""Render hand-authored SVG figures to PNG previews via Playwright.

Each SVG is rendered at 2× device pixel ratio for crisp preview PNGs.
The SVG files themselves are the Figma-editable source.

Outputs:
  - SVG source: /data/cameron/para/paper/figs/svg/figN_*.svg
  - PNG preview: saved to BOTH output dirs, named figN_*_svg.png
                 (so we don't overwrite the HTML-rendered figN_*.png)
  - The .svg files are also copied to the web review media dir
    so the review page can link to them for download.

Usage:
    python3 render_svg_figures.py --figs 1
    python3 render_svg_figures.py --figs all
"""
import argparse
import shutil
import sys
from pathlib import Path
from playwright.sync_api import sync_playwright

SVG_DIR = Path("/data/cameron/para/paper/figs/svg")
OUT_DIRS = [
    Path("/data/cameron/para/paper/figs/generated"),
    Path("/data/cameron/para/.agents/reports/paper_figures/media"),
]

FIGURES = {
    # Fig 1 now overwrites the HTML-rendered version (canonical)
    "1": {"svg": "fig1_overview.svg", "png": "fig1_overview.png",
          "width": 1400, "height": 700, "dpr": 3},
    "3": {"svg": "fig3_realrobot.svg", "png": "fig3_realrobot.png",
          "width": 1400, "height": 680, "dpr": 3},
    "4": {"svg": "fig4_ood.svg", "png": "fig4_ood.png",
          "width": 1400, "height": 820, "dpr": 3},
    "6": {"svg": "fig6_pretrain.svg", "png": "fig6_pretrain.png",
          "width": 1400, "height": 500, "dpr": 3},
    "2": {"svg": "fig2_method.svg",   "png": "fig2_method.png",
          "width": 1400, "height": 410, "dpr": 3},
    "2a": {"svg": "fig2a_method.svg", "png": "fig2a_method.png",
           "width": 1400, "height": 460, "dpr": 3},
    "2b": {"svg": "fig2b_invariance.svg", "png": "fig2b_invariance.png",
           "width": 820, "height": 880, "dpr": 3},
    "5": {"svg": "fig5_video.svg",    "png": "fig5_video.png",
          "width": 1400, "height": 500, "dpr": 3},
    "vkv": {"svg": "volume_kv_method.svg", "png": "volume_kv_method.png",
            "width": 1400, "height": 760, "dpr": 3},
    "qry": {"svg": "query_arch_method.svg", "png": "query_arch_method.png",
            "width": 1500, "height": 820, "dpr": 3},
}


def render(fig_key):
    cfg = FIGURES[fig_key]
    svg_path = SVG_DIR / cfg["svg"]
    if not svg_path.exists():
        print(f"  skip {fig_key}: {svg_path} not found")
        return

    # Wrap the raw SVG in an HTML shell so Chromium renders it cleanly with
    # Google Fonts loaded for Inter.
    shell_html = f"""<!DOCTYPE html>
<html><head>
<meta charset="UTF-8">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
  html,body {{ margin: 0; padding: 0; background: white; font-family: 'Inter', Arial, sans-serif; }}
  svg {{ display: block; }}
</style>
</head><body>
{svg_path.read_text()}
</body></html>"""

    tmp_html = SVG_DIR / f".preview_{cfg['svg']}.html"
    tmp_html.write_text(shell_html)

    try:
        with sync_playwright() as p:
            browser = p.chromium.launch(headless=True)
            context = browser.new_context(
                viewport={"width": cfg["width"], "height": cfg["height"]},
                device_scale_factor=cfg.get("dpr", 2),
            )
            page = context.new_page()
            page.goto(f"file://{tmp_html}")
            page.wait_for_load_state("networkidle")
            page.evaluate("document.fonts.ready")
            page.wait_for_timeout(400)

            svg_element = page.locator("svg").first
            png_bytes = svg_element.screenshot(omit_background=False)
            browser.close()
    finally:
        tmp_html.unlink(missing_ok=True)

    # Save PNG preview + copy SVG source to the review-media dir
    for d in OUT_DIRS:
        d.mkdir(parents=True, exist_ok=True)
        (d / cfg["png"]).write_bytes(png_bytes)
    # Copy the .svg file itself into the media dir (so the review page can link it)
    review_media = Path("/data/cameron/para/.agents/reports/paper_figures/media")
    shutil.copy(svg_path, review_media / cfg["svg"])
    print(f"  wrote {cfg['png']} to 2 locations + {cfg['svg']} to review media")


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--figs", default="all")
    args = parser.parse_args()
    if args.figs == "all":
        keys = list(FIGURES.keys())
    else:
        keys = [k.strip() for k in args.figs.split(",")]
    for k in keys:
        if k not in FIGURES:
            print(f"unknown: {k}")
            sys.exit(1)
        print(f"=== render fig {k} (SVG) ===")
        render(k)


if __name__ == "__main__":
    main()
