#!/usr/bin/env python3
"""Download pinned frontend vendor assets into web/app/vendor/ (F2e-06).

Run after upgrading versions in VENDOR_MANIFEST, then commit vendor/ + HTML path updates.
"""

from __future__ import annotations

import hashlib
import json
import urllib.request
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
VENDOR_DIR = ROOT / "web" / "app" / "vendor"

VENDOR_MANIFEST: dict[str, dict[str, str]] = {
    "tailwindcss-browser.js": {
        "url": "https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4.0.6/dist/index.global.js",
        "version": "@tailwindcss/browser@4.0.6",
    },
    "alpinejs.min.js": {
        "url": "https://cdn.jsdelivr.net/npm/alpinejs@3.14.8/dist/cdn.min.js",
        "version": "alpinejs@3.14.8",
    },
    "xterm.css": {
        "url": "https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css",
        "version": "xterm@5.3.0",
    },
    "xterm.js": {
        "url": "https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.js",
        "version": "xterm@5.3.0",
    },
    "xterm-addon-fit.js": {
        "url": "https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js",
        "version": "xterm-addon-fit@0.8.0",
    },
    "xterm-addon-web-links.js": {
        "url": "https://cdn.jsdelivr.net/npm/xterm-addon-web-links@0.9.0/lib/xterm-addon-web-links.js",
        "version": "xterm-addon-web-links@0.9.0",
    },
    "qrious.min.js": {
        "url": "https://cdn.jsdelivr.net/npm/qrious@4.0.2/dist/qrious.min.js",
        "version": "qrious@4.0.2",
    },
}

CDN_REPLACEMENTS = {
    "https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4": "/app/vendor/tailwindcss-browser.js",
    "https://cdn.jsdelivr.net/npm/alpinejs@3.14.8/dist/cdn.min.js": "/app/vendor/alpinejs.min.js",
    "https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css": "/app/vendor/xterm.css",
    "https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.js": "/app/vendor/xterm.js",
    "https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js": "/app/vendor/xterm-addon-fit.js",
    "https://cdn.jsdelivr.net/npm/xterm-addon-web-links@0.9.0/lib/xterm-addon-web-links.js": "/app/vendor/xterm-addon-web-links.js",
    "https://cdn.jsdelivr.net/npm/qrious@4.0.2/dist/qrious.min.js": "/app/vendor/qrious.min.js",
}


def _sha384(path: Path) -> str:
    digest = hashlib.sha384(path.read_bytes()).digest()
    return "sha384-" + __import__("base64").b64encode(digest).decode()


def download_vendor() -> dict:
    VENDOR_DIR.mkdir(parents=True, exist_ok=True)
    manifest: dict[str, dict] = {"files": {}, "replacements": CDN_REPLACEMENTS}
    for filename, meta in VENDOR_MANIFEST.items():
        dest = VENDOR_DIR / filename
        print(f"Fetching {meta['version']} -> {dest.name}")
        with urllib.request.urlopen(meta["url"], timeout=60) as resp:
            data = resp.read()
        dest.write_bytes(data)
        manifest["files"][filename] = {
            "version": meta["version"],
            "url": meta["url"],
            "bytes": len(data),
            "integrity": _sha384(dest),
        }
    (VENDOR_DIR / "manifest.json").write_text(
        json.dumps(manifest, indent=2, ensure_ascii=False) + "\n",
        encoding="utf-8",
    )
    return manifest


def patch_html_files() -> int:
    app_dir = ROOT / "web" / "app"
    changed = 0
    for html in sorted(app_dir.glob("*.html")):
        text = html.read_text(encoding="utf-8")
        original = text
        for old, new in CDN_REPLACEMENTS.items():
            text = text.replace(old, new)
        if text != original:
            html.write_text(text, encoding="utf-8")
            changed += 1
            print(f"Updated {html.name}")
    return changed


def main() -> None:
    download_vendor()
    n = patch_html_files()
    print(f"Done. {n} HTML file(s) patched.")


if __name__ == "__main__":
    main()
