"""将本地离线 HTML（如 viz_export_html / viz_data_chart）渲染为 PNG，不删除源 HTML。"""

from __future__ import annotations

from pathlib import Path
from typing import Any, Callable


def render_html_file_to_png(
    html_path: Path,
    output_png: Path,
    *,
    policy_check: Callable[[Path], None],
    selector: str | None = None,
    full_page: bool = True,
    device_scale_factor: float = 2.0,
    wait_after_load_ms: int = 1200,
    timeout_ms: int = 120_000,
) -> dict[str, Any]:
    """
    用 Playwright 打开 ``file://`` 页面并截图。

    - **不修改、不删除** ``html_path``；同级 ``res/`` 由浏览器按相对路径加载。
    - ``selector`` 非空时截取该元素，否则整页（``full_page`` 控制是否完整滚动高度）。
    """
    hp = html_path.expanduser().resolve()
    out = output_png.expanduser().resolve()
    policy_check(hp)
    policy_check(out)
    if not hp.is_file():
        return {"ok": False, "error": f"html file not found: {hp}"}
    if hp.suffix.lower() not in {".html", ".htm"}:
        return {"ok": False, "error": "html_path must be .html or .htm"}
    if out.suffix.lower() != ".png":
        return {"ok": False, "error": "output_png_path must end with .png"}

    out.parent.mkdir(parents=True, exist_ok=True)
    uri = hp.resolve().as_uri()

    try:
        from playwright.sync_api import sync_playwright
    except ImportError as e:
        return {
            "ok": False,
            "error": f"playwright not available: {e}",
            "hint": "pip install playwright && python -m playwright install chromium",
        }

    sel = (selector or "").strip() or None
    dsf = max(1.0, min(4.0, float(device_scale_factor)))
    wait_ms = max(0, min(60_000, int(wait_after_load_ms)))

    try:
        with sync_playwright() as p:
            browser = p.chromium.launch(headless=True)
            try:
                context = browser.new_context(device_scale_factor=dsf)
                page = context.new_page()
                page.set_default_timeout(timeout_ms)
                page.goto(uri, wait_until="load")
                if wait_ms:
                    page.wait_for_timeout(wait_ms)
                if sel:
                    loc = page.locator(sel).first
                    loc.wait_for(state="visible", timeout=timeout_ms)
                    loc.screenshot(path=str(out), type="png")
                else:
                    page.screenshot(
                        path=str(out),
                        full_page=bool(full_page),
                        type="png",
                    )
            finally:
                browser.close()
    except Exception as e:
        msg = str(e).lower()
        hint = "运行: python -m playwright install chromium"
        if "executable doesn't exist" in msg or "browsertype.launch" in msg:
            hint = "未找到 Chromium，请执行: python -m playwright install chromium"
        return {"ok": False, "error": str(e), "hint": hint}

    if not out.is_file() or out.stat().st_size == 0:
        return {"ok": False, "error": "PNG was not written or is empty"}

    return {
        "ok": True,
        "png_path": str(out),
        "html_path": str(hp),
        "source_retained": True,
        "note": "Source .html and sibling res/ are unchanged; use png_path in docx_compose / pptx_compose.",
    }
