"""`pyproject.toml` の設定検証（PLAN_02 ステップ 1 / ENV_01 技術スタック）．

ステップ 1 の完了条件は「`pyproject.toml`（uv・Ruff・pytest 設定）」であり，
採用技術は ENV_01 のとおり Python 3.12・PySide6・opencv-python(4.x)・NumPy・pytest・Ruff．
"""

import tomllib
from pathlib import Path

import pytest


@pytest.fixture(scope="session")
def pyproject(repo_root: Path) -> dict:
    return tomllib.loads((repo_root / "pyproject.toml").read_text(encoding="utf-8"))


class TestProjectMetadata:
    def test_project_name(self, pyproject: dict) -> None:
        assert pyproject["project"]["name"] == "tiasjudge"

    def test_requires_python_312(self, pyproject: dict) -> None:
        """ENV_01: 言語は Python 3.12．"""
        assert ">=3.12" in pyproject["project"]["requires-python"]

    def test_python_version_file_pins_312(self, repo_root: Path) -> None:
        version_file = repo_root / ".python-version"
        assert version_file.is_file()
        assert version_file.read_text(encoding="utf-8").strip().startswith("3.12")

    @pytest.mark.parametrize("package", ["numpy", "opencv-python", "pyside6"])
    def test_runtime_dependencies_declared(self, pyproject: dict, package: str) -> None:
        declared = [
            dependency.split(">")[0].split("<")[0].split("=")[0].strip().lower()
            for dependency in pyproject["project"]["dependencies"]
        ]
        assert package in declared

    def test_opencv_is_pinned_to_major_version_4(self, pyproject: dict) -> None:
        """ENV_01: `cv2.ml.SVM` の挙動同一性のため OpenCV 4.x 系に固定する．"""
        opencv = next(
            dependency
            for dependency in pyproject["project"]["dependencies"]
            if dependency.lower().startswith("opencv-python")
        )
        assert "<5" in opencv.replace(" ", "")

    @pytest.mark.parametrize("package", ["pytest", "ruff"])
    def test_dev_dependencies_declared(self, pyproject: dict, package: str) -> None:
        dev = [
            dependency.split(">")[0].split("<")[0].split("=")[0].strip().lower()
            for dependency in pyproject["dependency-groups"]["dev"]
        ]
        assert package in dev


class TestToolConfiguration:
    def test_pytest_testpaths_points_to_tests(self, pyproject: dict) -> None:
        assert pyproject["tool"]["pytest"]["ini_options"]["testpaths"] == ["tests"]

    def test_ruff_targets_py312(self, pyproject: dict) -> None:
        assert pyproject["tool"]["ruff"]["target-version"] == "py312"

    def test_ruff_lint_rules_selected(self, pyproject: dict) -> None:
        selected = set(pyproject["tool"]["ruff"]["lint"]["select"])
        assert {"E", "F", "I"} <= selected

    def test_wheel_packages_use_src_layout(self, pyproject: dict) -> None:
        packages = pyproject["tool"]["hatch"]["build"]["targets"]["wheel"]["packages"]
        assert packages == ["src/tiasjudge"]


class TestLockFile:
    def test_uv_lock_exists(self, repo_root: Path) -> None:
        """ENV_01: 依存の完全な再現のため `uv.lock` を管理する．"""
        assert (repo_root / "uv.lock").is_file()

    def test_uv_lock_is_not_git_ignored(self, repo_root: Path) -> None:
        import subprocess

        result = subprocess.run(
            ["git", "check-ignore", "uv.lock"],
            cwd=repo_root,
            capture_output=True,
            text=True,
        )
        assert result.returncode != 0, "uv.lock が .gitignore で除外されている"
