"""applicability.resolve_applicability 테스트.

Phase 1.2 — validator 레지스트리 계약 검증.
"""
from types import SimpleNamespace

import pytest

from app.core.applicability import (
    APPLICABILITY_VALIDATORS, resolve_applicability,
)


def _fake_runner(applicability: str, step_id: str = "fake_step") -> SimpleNamespace:
    return SimpleNamespace(
        manifest={"applicability": applicability},
        step_id=step_id,
        project_id="p1",
        episode_id="e1",
    )


def test_always_returns_true():
    assert resolve_applicability(_fake_runner("always")) is True


def test_disabled_returns_false():
    assert resolve_applicability(_fake_runner("disabled")) is False


def test_on_demand_returns_true():
    """on_demand는 수동 호출 전제라 always와 동일하게 True."""
    assert resolve_applicability(_fake_runner("on_demand")) is True


def test_unknown_rule_raises_value_error():
    """미지 rule은 crash (fail-fast). 신규 rule은 레지스트리 등록 후 사용.

    Claude Phase 1 리뷰 M4.
    """
    with pytest.raises(ValueError, match="Unknown applicability rule"):
        resolve_applicability(_fake_runner("if_totally_made_up"))


def test_known_if_rules_present_in_registry():
    """manifest에서 쓰는 if_* 규칙이 모두 레지스트리에 등록되어 있어야."""
    from app.core.step_manifest import STEP_MANIFEST
    used_if_rules = {
        s["applicability"] for s in STEP_MANIFEST.values()
        if s["applicability"].startswith("if_")
    }
    missing = used_if_rules - set(APPLICABILITY_VALIDATORS.keys())
    assert not missing, f"manifest uses unregistered if_* rules: {missing}"


def test_registry_does_not_have_always_or_disabled():
    """always/disabled/on_demand는 레지스트리에 두지 않음 (resolve_applicability 내부 분기)."""
    for reserved in ("always", "disabled", "on_demand"):
        assert reserved not in APPLICABILITY_VALIDATORS
