"""`core/` の GUI 非依存の検証（project-structure.md「依存方向のルール」）．

- `core/` は PySide6・GUI に依存してはならない（import 禁止）
- 逆方向（`gui/` → `core/`）は許可される
"""

import ast
import subprocess
import sys
from pathlib import Path

FORBIDDEN_ROOTS = {"PySide6", "PyQt5", "PyQt6", "shiboken6"}


def _core_source_files(repo_root: Path) -> list[Path]:
    return sorted((repo_root / "src" / "tiasjudge" / "core").rglob("*.py"))


def _imported_roots(source_path: Path) -> set[str]:
    """ファイル内の import 文から，トップレベルのモジュール名を収集する．"""
    tree = ast.parse(source_path.read_text(encoding="utf-8"), filename=str(source_path))
    roots: set[str] = set()
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                roots.add(alias.name)
        elif isinstance(node, ast.ImportFrom) and node.level == 0 and node.module:
            roots.add(node.module)
    return roots


def test_core_package_has_source_files(repo_root: Path) -> None:
    """走査対象が 0 件だと以降のテストが空振りするため前提を確認する．"""
    assert _core_source_files(repo_root), "core/ に Python ファイルが無い"


def test_core_does_not_import_gui_toolkit(repo_root: Path) -> None:
    """静的解析: core/ 配下のどのファイルも GUI ツールキットを import しない．"""
    violations: list[tuple[str, str]] = []
    for source_path in _core_source_files(repo_root):
        for imported in _imported_roots(source_path):
            if imported.split(".")[0] in FORBIDDEN_ROOTS:
                violations.append((source_path.name, imported))
    assert violations == []


def test_core_does_not_import_project_gui_package(repo_root: Path) -> None:
    """静的解析: core/ が `tiasjudge.gui` に依存しない．"""
    violations: list[tuple[str, str]] = []
    for source_path in _core_source_files(repo_root):
        for imported in _imported_roots(source_path):
            if imported.startswith("tiasjudge.gui") or imported == "gui":
                violations.append((source_path.name, imported))
    assert violations == []


def test_importing_core_does_not_load_gui_toolkit(repo_root: Path) -> None:
    """実行時: `tiasjudge.core` を import しても GUI ツールキットがロードされない．"""
    code = (
        "import sys\n"
        "import tiasjudge.core\n"
        "loaded = sorted(m for m in sys.modules if m.split('.')[0] in "
        f"{sorted(FORBIDDEN_ROOTS)!r})\n"
        "print(loaded)\n"
    )
    result = subprocess.run(
        [sys.executable, "-c", code],
        cwd=repo_root,
        capture_output=True,
        text=True,
        encoding="utf-8",
        errors="replace",
    )
    assert result.returncode == 0, result.stderr
    assert result.stdout.strip() == "[]"
