"""Tier-range invariants — the selection model's load-bearing properties.

The supervisor's whole tier story rests on: tier ranges are nested
(`0-N` ⊆ `0-(N+1)`), unmarked tests fall to DEFAULT_TIER, and a
multi-marked test takes the HIGHEST tier (conservative budgeting). If any
of these silently breaks, `--tier` selection is wrong and nobody notices.
(No Hypothesis — the supervisor stays stdlib-only per TS-23.)
"""

from __future__ import annotations

import pytest

from mgf.test_supervisor.durations import DurationStore
from mgf.test_supervisor.tiers import (
    DEFAULT_TIER,
    MARKER_TIER,
    parse_tier_range,
    tier_for_markers,
)


def test_tier_ranges_are_nested_subsets() -> None:
    for hi in range(3):
        assert parse_tier_range(f"0-{hi}") < parse_tier_range(f"0-{hi + 1}")


def test_full_range_is_all_four_tiers() -> None:
    assert parse_tier_range("0-3") == {0, 1, 2, 3}


def test_single_tier_is_singleton() -> None:
    for t in range(4):
        assert parse_tier_range(str(t)) == {t}


def test_unmarked_test_is_default_tier() -> None:
    assert tier_for_markers(()) == DEFAULT_TIER


def test_highest_marker_wins() -> None:
    # smoke=0, stress=3 → the conservative (highest) tier is chosen.
    assert tier_for_markers(("smoke", "stress")) == 3
    assert tier_for_markers(("contract", "perf")) == MARKER_TIER["perf"]


def test_every_marker_maps_into_range() -> None:
    for marker, tier in MARKER_TIER.items():
        assert 0 <= tier <= 3, f"{marker} → out-of-range tier {tier}"


def test_slow_marker_completed_removal() -> None:
    # M2 Wave-2: the deprecated `slow` marker is gone from the mapping
    # (a test is slow BECAUSE of what it does — perf / stress / e2e —
    # or auto-tier promotes it from observed durations).
    assert "slow" not in MARKER_TIER


def test_explicit_override_wins_and_validates() -> None:
    # tier_for_markers gained override/mapping (M2 Wave-2), matching
    # mgf.common.testing.effective_tier semantics.
    assert tier_for_markers(("e2e",), override=0) == 0
    assert tier_for_markers((), override=2) == 2
    with pytest.raises(ValueError, match=r"0\.\.3"):
        tier_for_markers(("smoke",), override=7)


class TestAutoTierFromRealBase:
    """auto_tier_overrides starts from each test's MARKER tier (M2
    Wave-2) — pre-Wave-2 it hardcoded base 1, capping every promotion
    at tier-2 and ignoring the marker floor."""

    @staticmethod
    def _store_with_slow_history(tmp_path, test_id: str, dur_ms: int) -> DurationStore:
        store = DurationStore(tmp_path / "durations.json")
        for i in range(5):
            store.record(test_id, "passed", dur_ms, f"run-{i}")
        return store

    def test_integration_test_can_exceed_tier_2(self, tmp_path) -> None:
        tid = "t.py::test_slow_integration"
        store = self._store_with_slow_history(tmp_path, tid, dur_ms=30_000)  # 30s >> 5x2s
        overrides = store.auto_tier_overrides({tid: MARKER_TIER["integration"]})
        assert overrides == {tid: 3}

    def test_default_base_matches_legacy_behaviour(self, tmp_path) -> None:
        tid = "t.py::test_slow_unmarked"
        store = self._store_with_slow_history(tmp_path, tid, dur_ms=30_000)
        assert store.auto_tier_overrides() == {tid: 2}  # DEFAULT_TIER + 1

    def test_fast_test_not_promoted(self, tmp_path) -> None:
        tid = "t.py::test_fast"
        store = self._store_with_slow_history(tmp_path, tid, dur_ms=50)
        assert store.auto_tier_overrides({tid: 0}) == {}
