from pathlib import Path

import json

from scienith_openapi_contract_tooling.openapi.bundle import bundle_openapi_spec_for_docs
from scienith_openapi_contract_tooling.openapi.load import load_openapi_spec


def _default_redoc_cdn_urls() -> list[str]:
    return [
        "https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js",
        "https://unpkg.com/redoc@next/bundles/redoc.standalone.js",
        "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js",
    ]


def _load_redoc_html_template() -> str:
    from importlib.resources import files

    return files("scienith_openapi_contract_tooling.openapi.templates").joinpath("redoc.html").read_text(encoding="utf-8")


def openapi_to_redoc_html(
    *,
    root_path: str,
    out_path: str,
    bundle: bool,
    title: str | None = None,
    cdn_urls: list[str] | None = None,
) -> None:
    """
    从 OpenAPI YAML/JSON 生成可双击打开的 Redoc 单文件 HTML。

    约束：
    - 默认会把外部文件 `$ref` 尽可能 bundle 为单文件对象，以便 Redoc 正常渲染。
    """
    root = Path(root_path)
    out = Path(out_path)
    out.parent.mkdir(parents=True, exist_ok=True)

    if bundle:
        spec = bundle_openapi_spec_for_docs(root_path=root)
    else:
        spec = load_openapi_spec(root)

    doc_title = title or str((spec.get("info") or {}).get("title") or "OpenAPI Docs")
    urls = cdn_urls or _default_redoc_cdn_urls()

    tpl = _load_redoc_html_template()
    html = (
        tpl.replace("{{TITLE}}", doc_title)
        .replace("{{SPEC_JSON}}", json.dumps(spec, ensure_ascii=False))
        .replace("{{CDN_URLS_JSON}}", json.dumps(urls, ensure_ascii=False))
    )
    out.write_text(html, encoding="utf-8")
