"""Tests for scoring module."""


from priorart.scoring import compute_signal


def make_repo(stars: int) -> dict:
    return {
        "name": "org/repo",
        "stars": stars,
        "description": "test",
        "url": "https://github.com/org/repo",
        "updated": "2024-01-01",
        "language": "Python",
    }


def make_hn(points: int) -> dict:
    return {
        "title": "Test post",
        "points": points,
        "comments": 10,
        "url": "https://news.ycombinator.com/item?id=1",
        "date": "2024-01-01",
    }


class TestComputeSignal:
    def test_empty_results_returns_zero(self):
        result = compute_signal([], [])
        assert result["score"] == 0
        assert result["verdict"] == "LOW"
        assert result["breakdown"]["github"] == 0
        assert result["breakdown"]["hn"] == 0

    def test_low_verdict_under_30(self):
        result = compute_signal([], [])
        assert result["verdict"] == "LOW"
        assert result["score"] < 30

    def test_moderate_verdict_30_to_60(self):
        # 4 repos with low stars → gh=30, no HN → score=30 → MODERATE
        repos = [make_repo(10) for _ in range(4)]
        result = compute_signal(repos, [])
        assert result["verdict"] == "MODERATE"
        assert 30 <= result["score"] <= 60

    def test_high_verdict_over_60(self):
        # 8+ repos with 5000+ stars + 3+ HN posts → HIGH
        repos = [make_repo(10000) for _ in range(10)]
        hn = [make_hn(200) for _ in range(5)]
        result = compute_signal(repos, hn)
        assert result["verdict"] == "HIGH"
        assert result["score"] > 60

    def test_max_stars_boost_github(self):
        one_repo = [make_repo(5000)]
        result = compute_signal(one_repo, [])
        # 1 repo = 15, 5000 stars = +20 → 35
        assert result["breakdown"]["github"] == 35

    def test_score_capped_at_100(self):
        repos = [make_repo(10000) for _ in range(20)]
        hn = [make_hn(500) for _ in range(20)]
        result = compute_signal(repos, hn)
        assert result["score"] <= 100

    def test_breakdown_keys_present(self):
        result = compute_signal([], [])
        assert "github" in result["breakdown"]
        assert "hn" in result["breakdown"]

    # ------------------------------------------------------------------
    # GitHub tier boundaries
    # ------------------------------------------------------------------

    def test_gh_score_single_repo_no_stars(self):
        result = compute_signal([make_repo(10)], [])
        # 1 repo (base=15); 10 stars → no boost
        assert result["breakdown"]["github"] == 15

    def test_gh_score_4_repos_no_stars(self):
        result = compute_signal([make_repo(10) for _ in range(4)], [])
        # 4 repos (base=30); 10 stars → no boost
        assert result["breakdown"]["github"] == 30

    def test_gh_score_8_repos_no_stars(self):
        result = compute_signal([make_repo(10) for _ in range(8)], [])
        # 8 repos (base=45); 10 stars → no boost
        assert result["breakdown"]["github"] == 45

    def test_gh_stars_100_to_999_adds_10(self):
        result = compute_signal([make_repo(500)], [])
        # base=15; 500 stars (100–999) → +10 = 25
        assert result["breakdown"]["github"] == 25

    def test_gh_stars_1000_to_4999_adds_15(self):
        result = compute_signal([make_repo(2000)], [])
        # base=15; 2000 stars (1000–4999) → +15 = 30
        assert result["breakdown"]["github"] == 30

    def test_gh_score_capped_at_60(self):
        result = compute_signal([make_repo(10000) for _ in range(10)], [])
        # base=45; 10000 stars → +20 = 65, capped at 60
        assert result["breakdown"]["github"] == 60

    # ------------------------------------------------------------------
    # HN tier boundaries
    # ------------------------------------------------------------------

    def test_hn_score_2_posts_no_boost(self):
        result = compute_signal([], [make_hn(5), make_hn(10)])
        # 2 posts (base=10); max_points=10 < 30 → no boost
        assert result["breakdown"]["hn"] == 10

    def test_hn_score_3_posts_no_boost(self):
        result = compute_signal([], [make_hn(5) for _ in range(3)])
        # 3 posts (base=25); max_points=5 < 30 → no boost
        assert result["breakdown"]["hn"] == 25

    def test_hn_points_30_to_99_adds_10(self):
        result = compute_signal([], [make_hn(50)])
        # 1 post (base=10); 50 pts (30–99) → +10 = 20
        assert result["breakdown"]["hn"] == 20

    def test_hn_points_100_plus_adds_15(self):
        result = compute_signal([], [make_hn(150)])
        # 1 post (base=10); 150 pts (≥100) → +15 = 25
        assert result["breakdown"]["hn"] == 25

    def test_hn_score_capped_at_40(self):
        result = compute_signal([], [make_hn(500) for _ in range(5)])
        # 5 posts (base=25); 500 pts → +15 = 40, capped at 40
        assert result["breakdown"]["hn"] == 40

    # ------------------------------------------------------------------
    # Verdict boundary values
    # ------------------------------------------------------------------

    def test_score_exactly_30_is_moderate(self):
        # 4 repos, 10 stars → gh=30, hn=0 → score=30 → MODERATE
        result = compute_signal([make_repo(10) for _ in range(4)], [])
        assert result["score"] == 30
        assert result["verdict"] == "MODERATE"

    def test_score_25_is_low(self):
        # 1 repo, 500 stars → gh=15+10=25, hn=0 → score=25 → LOW
        result = compute_signal([make_repo(500)], [])
        assert result["score"] == 25
        assert result["verdict"] == "LOW"

    def test_score_exactly_60_is_moderate(self):
        # 8 repos, 2000 stars → gh=45+15=60, hn=0 → score=60 → MODERATE
        result = compute_signal([make_repo(2000) for _ in range(8)], [])
        assert result["score"] == 60
        assert result["verdict"] == "MODERATE"

    def test_score_above_60_is_high(self):
        # 8 repos (500 stars) + 1 HN post (20 pts) → gh=55, hn=10 → score=65 → HIGH
        result = compute_signal(
            [make_repo(500) for _ in range(8)],
            [make_hn(20)],
        )
        assert result["score"] == 65
        assert result["verdict"] == "HIGH"
