from __future__ import annotations

import json
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path

from tools.build_api_registry import build as build_api_registry
from tools.build_architecture_inventory import (
    build as build_architecture_inventory,
    source_metrics,
)
from tools.verify_baseline import python_test_command


ROOT = Path(__file__).resolve().parents[1]


class MaintenanceToolTests(unittest.TestCase):
    def test_generated_registries_are_current(self) -> None:
        expected_api = json.loads(
            (ROOT / "config" / "api.config.json").read_text(encoding="utf-8")
        )
        expected_architecture = json.loads(
            (ROOT / "config" / "architecture-inventory.json").read_text(
                encoding="utf-8"
            )
        )
        self.assertEqual(expected_api, build_api_registry())
        self.assertEqual(expected_architecture, build_architecture_inventory())

    def test_baseline_verifier_uses_the_application_frontend(self) -> None:
        source = (ROOT / "tools" / "verify_baseline.py").read_text(encoding="utf-8")
        self.assertIn('FRONTEND_ROOT = ROOT / "frontend"', source)
        self.assertIn('path.suffix in {".js", ".mjs"}', source)
        self.assertIn("start_e2e_server()", source)
        self.assertIn("stop_e2e_server(server)", source)
        self.assertNotIn('"static/app.js"', source)

    def test_runtime_artifacts_have_one_ignored_root(self) -> None:
        gitignore = (ROOT / ".gitignore").read_text(encoding="utf-8")
        dockerignore = (ROOT / ".dockerignore").read_text(encoding="utf-8")
        playwright = (ROOT / "playwright.config.js").read_text(encoding="utf-8")
        launcher = (ROOT / "tools" / "start_local.ps1").read_text(encoding="utf-8")
        self.assertIn("runtime/*", gitignore)
        self.assertIn("runtime/", dockerignore)
        self.assertIn('outputDir: "./runtime/test-results"', playwright)
        self.assertIn('Join-Path $runtime "logs"', launcher)
        self.assertEqual(list(ROOT.glob("*.log")), [])

    def test_verifier_runs_the_complete_standalone_suite(self) -> None:
        command = python_test_command()
        self.assertIn("discover", command)
        self.assertIn("tests", command)

    def test_architecture_metrics_are_independent_of_checkout_line_endings(self) -> None:
        with tempfile.TemporaryDirectory() as directory:
            root = Path(directory)
            lf = root / "lf.js"
            crlf = root / "crlf.js"
            lf.write_bytes(b"const a = 1;\nconst b = 2;\n")
            crlf.write_bytes(b"const a = 1;\r\nconst b = 2;\r\n")
            self.assertEqual(source_metrics(lf), source_metrics(crlf))

    def test_every_tool_has_a_non_mutating_help_path(self) -> None:
        for path in sorted((ROOT / "tools").glob("*.py")):
            if path.name.startswith("_"):
                continue
            with self.subTest(tool=path.name):
                result = subprocess.run(
                    [sys.executable, str(path), "--help"],
                    cwd=ROOT,
                    capture_output=True,
                    text=True,
                    timeout=15,
                    check=False,
                )
                self.assertEqual(result.returncode, 0, result.stderr)

    def test_migration_only_tools_are_retired(self) -> None:
        for name in (
            "build_preservation_manifest.py",
            "compare_preservation_apis.py",
            "compare_preservation_databases.py",
            "move_class_methods.py",
            "run_preservation_runtime.py",
        ):
            with self.subTest(name=name):
                self.assertFalse((ROOT / "tools" / name).exists())


if __name__ == "__main__":
    unittest.main()
