import json
from models import LEADERBOARD_CAP


def add(client, name, score, headers, board="global"):
    client.post(
        f"/{board}/add",
        data=json.dumps({"name": name, "score": score}),
        headers=headers,
    )


class TestPrune:
    def test_returns_200(self, client, auth_headers):
        assert client.post("/global/prune", headers=auth_headers).status_code == 200

    def test_prune_under_cap_removes_nothing(self, client, auth_headers):
        for i in range(10):
            add(client, f"Player{i}", i, auth_headers)

        resp = client.post("/global/prune", headers=auth_headers)
        assert resp.get_json()["pruned"] == 0

    def test_prune_removes_entries_outside_top_cap(self, client, auth_headers):
        # Insert LEADERBOARD_CAP + 1 entries with distinct ascending scores
        for i in range(LEADERBOARD_CAP + 1):
            add(client, f"Player{i}", i, auth_headers)

        resp = client.post("/global/prune", headers=auth_headers)
        assert resp.get_json()["pruned"] == 1

        remaining = client.get(f"/global/top/{LEADERBOARD_CAP}").get_json()
        assert len(remaining) == LEADERBOARD_CAP

    def test_prune_keeps_highest_scores(self, client, auth_headers):
        for i in range(LEADERBOARD_CAP + 1):
            add(client, f"Player{i}", i, auth_headers)

        client.post("/global/prune", headers=auth_headers)

        # Score 0 (the lowest) should have been evicted
        remaining_scores = [
            e["score"]
            for e in client.get(f"/global/top/{LEADERBOARD_CAP}").get_json()
        ]
        assert 0 not in remaining_scores

    def test_prune_tie_at_boundary_evicts_oldest(self, client, auth_headers):
        # Fill exactly to cap, all with the same score, then add one more
        for i in range(LEADERBOARD_CAP + 1):
            add(client, f"Player{i}", 1, auth_headers)

        resp = client.post("/global/prune", headers=auth_headers)
        assert resp.get_json()["pruned"] == 1

        remaining_names = [
            e["name"]
            for e in client.get(f"/global/top/{LEADERBOARD_CAP}").get_json()
        ]
        # Player0 was inserted first (oldest created), so it should be evicted
        assert "Player0" not in remaining_names
        assert f"Player{LEADERBOARD_CAP}" in remaining_names

    def test_requires_api_key(self, client):
        assert client.post("/global/prune").status_code == 401

    def test_invalid_leaderboard_returns_404(self, client, auth_headers):
        assert client.post("/nonexistent/prune", headers=auth_headers).status_code == 404
