#!/usr/bin/env python3
"""Normalize the public version selector without rebuilding frozen docs."""

from __future__ import annotations

import argparse
import re
from pathlib import Path


SELECT_RE = re.compile(
    r'<select\s+id="version-switcher"[^>]*>.*?</select>',
    re.DOTALL,
)

OPTIONS = {
    "zh": (
        "SPINE V8(当前)",
        "SPINE V6(维护)",
        "SPINE V4(维护)",
        "SPINE V3(历史)",
    ),
    "en": (
        "SPINE V8 (Current)",
        "SPINE V6 (Maintenance)",
        "SPINE V4 (Maintenance)",
        "SPINE V3 (Legacy)",
    ),
}


def replacement(language: str) -> str:
    v8, v6, v4, v3 = OPTIONS[language]
    return (
        '<select id="version-switcher" aria-label="Version switcher" '
        'onchange="switchDocVersion(this.value)">\n'
        f'      <option value="v8">{v8}</option>\n'
        f'      <option value="v6">{v6}</option>\n'
        f'      <option value="v4">{v4}</option>\n'
        f'      <option value="v3">{v3}</option>\n'
        "    </select>"
    )


def normalize_html(text: str, language: str) -> tuple[str, int]:
    return SELECT_RE.subn(replacement(language), text)


def normalize_site(site_root: Path) -> dict[str, int]:
    counts: dict[str, int] = {}
    for version in ("v3", "v4", "v6", "v8"):
        version_count = 0
        for language in ("zh", "en"):
            language_root = site_root / version / language
            if not language_root.is_dir():
                raise RuntimeError(f"Missing documentation tree: {language_root}")
            for html_file in sorted(language_root.rglob("*.html")):
                original = html_file.read_text(encoding="utf-8", errors="strict")
                updated, replacements = normalize_html(original, language)
                if replacements:
                    html_file.write_text(updated, encoding="utf-8", newline="")
                    version_count += replacements
        if version_count == 0:
            raise RuntimeError(f"No version selector found under {site_root / version}")
        counts[version] = version_count
    return counts


def verify_preserved_tree(site_root: Path, specification: str) -> None:
    if "=" not in specification:
        raise RuntimeError(
            f"Invalid --verify-preserved value {specification!r}; expected VERSION=PATH"
        )
    version, raw_source = specification.split("=", 1)
    if version not in {"v3", "v4", "v6"}:
        raise RuntimeError(f"Unsupported preserved version: {version}")

    source = Path(raw_source).resolve()
    target = (site_root / version).resolve()
    source_files = {
        path.relative_to(source): path for path in source.rglob("*") if path.is_file()
    }
    target_files = {
        path.relative_to(target): path for path in target.rglob("*") if path.is_file()
    }
    if source_files.keys() != target_files.keys():
        missing = sorted(str(path) for path in source_files.keys() - target_files.keys())
        extra = sorted(str(path) for path in target_files.keys() - source_files.keys())
        raise RuntimeError(
            f"Preserved {version} file set changed; missing={missing[:5]}, extra={extra[:5]}"
        )

    for relative_path, source_file in source_files.items():
        target_file = target_files[relative_path]
        if source_file.suffix.lower() == ".html":
            language = relative_path.parts[0] if relative_path.parts else ""
            if language not in OPTIONS:
                expected = source_file.read_bytes()
            else:
                source_text = source_file.read_text(encoding="utf-8", errors="strict")
                expected_text, _ = normalize_html(source_text, language)
                expected = expected_text.encode("utf-8")
        else:
            expected = source_file.read_bytes()
        if target_file.read_bytes() != expected:
            raise RuntimeError(
                f"Preserved {version} content changed outside version navigation: "
                f"{relative_path}"
            )


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("site_root", type=Path)
    parser.add_argument(
        "--verify-preserved",
        action="append",
        default=[],
        metavar="VERSION=PATH",
    )
    args = parser.parse_args()

    site_root = args.site_root.resolve()
    counts = normalize_site(site_root)
    for specification in args.verify_preserved:
        verify_preserved_tree(site_root, specification)

    summary = ", ".join(f"{version}={count}" for version, count in counts.items())
    print(f"Version navigation normalized: {summary}")
    if args.verify_preserved:
        print("Frozen documentation verified: only version navigation changed")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())