"""Pure-logic tests for build_tierlist (no audio, no grader import needed at call time).

The grading itself is the katana's job (tested in tools/foundry/tests/test_grade.py);
here we pin the join/stats math that turns grades into the Hall of Fame.
"""
import build_tierlist as T


def test_median_odd_even():
    assert T.median([3, 1, 2]) == 2
    assert T.median([4, 1, 2, 3]) == 2.5
    assert T.median([]) == 0.0
    assert T.median([7]) == 7


def test_spearman_perfect_monotonic():
    # grade rises with usage → ρ = 1
    pairs = [(0.5, 1), (0.6, 2), (0.7, 3), (0.8, 4)]
    assert T.spearman(pairs) == 1.0


def test_spearman_inverse():
    pairs = [(0.8, 1), (0.7, 2), (0.6, 3), (0.5, 4)]
    assert T.spearman(pairs) == -1.0


def test_spearman_ties_averaged():
    # two equal grades share the averaged rank — must not crash or NaN
    pairs = [(0.5, 1), (0.5, 2), (0.7, 3), (0.9, 4)]
    rho = T.spearman(pairs)
    assert rho is not None and 0.0 < rho <= 1.0


def test_spearman_too_few_points():
    assert T.spearman([(0.5, 1), (0.6, 2)]) is None


def test_tier_of_matches_grader_thresholds():
    # build_tierlist must tier identically to the katana
    assert T.tier_of(0.95) == "S"
    assert T.tier_of(0.80) == "A"
    assert T.tier_of(0.70) == "B"
    assert T.tier_of(0.55) == "C"
    assert T.tier_of(0.0) == "D"


def test_usage_counts_counts_tracks_not_occurrences(tmp_path, monkeypatch):
    # a sound used twice IN ONE track counts once; used in two tracks counts twice
    cv = tmp_path / "catalog_view.json"
    cv.write_text(
        '{"tracks": ['
        '{"score_sounds": ["crimewave", "crimewave", "risers"]},'
        '{"score_sounds": ["risers", "fbass"]}'
        ']}'
    )
    monkeypatch.setattr(T, "CV", cv)
    u = T.usage_counts()
    assert u["crimewave"] == 1      # twice in one track → 1
    assert u["risers"] == 2         # once each in two tracks → 2
    assert u["fbass"] == 1
