"""Геймификация (ТЗ 3.13): XP за закрытие задач, уровни, идемпотентность."""

from typing import Any

from fastapi.testclient import TestClient


def _create_task(client: TestClient, **patch: Any) -> int:
    resp = client.post("/api/tasks", json={"title": "Задача для XP"})
    task_id = resp.json()["id"]
    if patch:
        resp2 = client.patch(f"/api/tasks/{task_id}", json=patch)
        assert resp2.status_code == 200
    return task_id


def test_xp_granted_on_done(client: TestClient) -> None:
    task_id = _create_task(client)
    resp = client.patch(f"/api/tasks/{task_id}", json={"status": "done"})
    assert resp.status_code == 200
    # база 10, без приоритета и оценки — только база
    assert resp.headers.get("X-Earned-XP") == "10"

    summary = client.get("/api/xp").json()
    assert summary["total_xp"] == 10
    assert summary["level"] == 1
    assert summary["completed_count"] == 1


def test_xp_weighted_by_priority_and_estimate(client: TestClient) -> None:
    task_id = _create_task(client)
    client.patch(
        f"/api/tasks/{task_id}", json={"priority": 9, "estimated_minutes": 480}
    )
    resp = client.patch(f"/api/tasks/{task_id}", json={"status": "done"})
    # 10 + urgent 15 + >4ч 15 = 40
    assert resp.headers.get("X-Earned-XP") == "40"


def test_xp_granted_once(client: TestClient) -> None:
    task_id = _create_task(client)
    client.patch(f"/api/tasks/{task_id}", json={"status": "done"})
    # возврат в работу и повторное закрытие — XP не растёт
    client.patch(f"/api/tasks/{task_id}", json={"status": "in_progress"})
    resp = client.patch(f"/api/tasks/{task_id}", json={"status": "done"})
    assert "X-Earned-XP" not in resp.headers
    assert client.get("/api/xp").json()["total_xp"] == 10


def test_deleting_task_keeps_xp(client: TestClient) -> None:
    task_id = _create_task(client)
    client.patch(f"/api/tasks/{task_id}", json={"status": "done"})
    client.delete(f"/api/tasks/{task_id}")
    assert client.get("/api/xp").json()["total_xp"] == 10


def test_level_progression(client: TestClient) -> None:
    # 9 закрытий по 10 XP = 90 — уровень 1; 10 закрытий = 100 — уровень 2
    for _ in range(9):
        task_id = _create_task(client)
        client.patch(f"/api/tasks/{task_id}", json={"status": "done"})
    assert client.get("/api/xp").json()["level"] == 1
    task_id = _create_task(client)
    client.patch(f"/api/tasks/{task_id}", json={"status": "done"})
    summary = client.get("/api/xp").json()
    assert summary["level"] == 2
    assert summary["level_xp"] == 0
    assert summary["level_span"] == 200
    assert summary["level_percent"] == 0
