"""Contracts for the fast pull-request test selector."""

from __future__ import annotations

from pathlib import Path

import pytest

from scripts import select_pr_tests


def _touch(root: Path, *paths: str) -> None:
    for value in paths:
        path = root / value
        path.parent.mkdir(parents=True, exist_ok=True)
        path.write_text("# test fixture\n", encoding="utf-8")


def _policy() -> dict:
    return {
        "always_tests": ["tests/test_smoke.py"],
        "infrastructure_paths": ["ci/**", ".github/workflows/**"],
        "infrastructure_tests": ["tests/test_ci_policy.py"],
        "excluded_test_prefixes": ["tests/conditional/"],
    }


def _risk_map() -> dict:
    return {
        "contract_surfaces": [{
            "paths": ["obliteratus/core.py"],
            "required_tests": [
                "tests/test_core.py",
                "tests/conditional/test_core_gpu.py",
            ],
        }],
    }


def test_selects_smoke_risk_mapped_and_changed_tests(tmp_path):
    _touch(
        tmp_path,
        "tests/test_smoke.py",
        "tests/test_core.py",
        "tests/conditional/test_core_gpu.py",
        "tests/test_new_contract.py",
    )

    assert select_pr_tests.select_tests(
        ["obliteratus/core.py", "tests/test_new_contract.py"],
        policy=_policy(),
        risk_maps=[_risk_map()],
        project_root=tmp_path,
    ) == [
        "tests/test_core.py",
        "tests/test_new_contract.py",
        "tests/test_smoke.py",
    ]


def test_selects_policy_contracts_for_infrastructure_changes(tmp_path):
    _touch(tmp_path, "tests/test_smoke.py", "tests/test_ci_policy.py")

    assert select_pr_tests.select_tests(
        ["ci/pr-test-policy.json"],
        policy=_policy(),
        risk_maps=[_risk_map()],
        project_root=tmp_path,
    ) == ["tests/test_ci_policy.py", "tests/test_smoke.py"]


def test_removed_source_can_use_the_base_risk_map(tmp_path):
    _touch(tmp_path, "tests/test_smoke.py", "tests/test_removed.py")
    head = {"contract_surfaces": []}
    base = {
        "contract_surfaces": [{
            "paths": ["obliteratus/removed.py"],
            "required_tests": ["tests/test_removed.py"],
        }],
    }

    assert select_pr_tests.select_tests(
        ["obliteratus/removed.py"],
        policy=_policy(),
        risk_maps=[head, base],
        project_root=tmp_path,
    ) == ["tests/test_removed.py", "tests/test_smoke.py"]


def test_unmapped_production_source_fails_closed(tmp_path):
    _touch(tmp_path, "tests/test_smoke.py")

    with pytest.raises(ValueError, match="unmapped"):
        select_pr_tests.select_tests(
            ["obliteratus/unowned.py"],
            policy=_policy(),
            risk_maps=[_risk_map()],
            project_root=tmp_path,
        )
