#!/usr/bin/env python3
"""Synchronize frontend package versions with pyproject.toml.

pyproject.toml is the single source of truth for the project version.
Run this script before building the frontend or deploying so the two
files never drift apart.

Usage:
    scripts/sync_version.py            # update package.json and package-lock.json
    scripts/sync_version.py --check    # exit 1 if they already differ
"""

from __future__ import annotations

import argparse
import json
import re
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
PYPROJECT = ROOT / "pyproject.toml"
PACKAGE_JSON = ROOT / "frontend" / "web" / "package.json"
PACKAGE_LOCK = ROOT / "frontend" / "web" / "package-lock.json"


_VERSION_RE = re.compile(r'^version\s*=\s*"([^"]+)"', re.MULTILINE)


def read_pyproject_version() -> str:
    text = PYPROJECT.read_text(encoding="utf-8")
    match = _VERSION_RE.search(text)
    if not match:
        raise RuntimeError(f"could not find version= in {PYPROJECT}")
    return match.group(1)


def package_versions_match(version: str) -> bool:
    package_data = json.loads(PACKAGE_JSON.read_text(encoding="utf-8"))
    lock_data = json.loads(PACKAGE_LOCK.read_text(encoding="utf-8"))
    return (
        package_data.get("version") == version
        and lock_data.get("version") == version
        and lock_data.get("packages", {}).get("", {}).get("version") == version
    )


def write_package_versions(version: str) -> bool:
    """Update package.json and package-lock.json. Returns True if changed."""
    if package_versions_match(version):
        return False

    data = json.loads(PACKAGE_JSON.read_text(encoding="utf-8"))
    data["version"] = version
    PACKAGE_JSON.write_text(
        json.dumps(data, indent=2, ensure_ascii=False) + "\n",
        encoding="utf-8",
    )

    lock_data = json.loads(PACKAGE_LOCK.read_text(encoding="utf-8"))
    lock_data["version"] = version
    lock_data.setdefault("packages", {}).setdefault("", {})["version"] = version
    PACKAGE_LOCK.write_text(
        json.dumps(lock_data, indent=2, ensure_ascii=False) + "\n",
        encoding="utf-8",
    )
    return True


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "--check", action="store_true",
        help="Exit with status 1 if versions already match (CI-friendly).",
    )
    args = parser.parse_args()

    version = read_pyproject_version()
    if args.check:
        if not package_versions_match(version):
            print(f"OUT_OF_SYNC pyproject={version} frontend package versions differ")
            return 1
        print(f"OK version={version}")
        return 0

    changed = write_package_versions(version)
    if changed:
        print(f"synced frontend package versions -> {version}")
    else:
        print(f"already in sync: {version}")
    return 0


if __name__ == "__main__":
    sys.exit(main())
