# retoor <retoor@molodetz.nl>

import requests

from tests.api.quizzes._helpers import (
    JSON,
    NUMERIC,
    answer_correctly,
    attempt_state,
    build_published,
    create_quiz,
    signup,
    start_attempt,
)
from tests.conftest import BASE_URL


def _play(session, slug, correct=True):
    attempt_uid = start_attempt(session, slug)
    state = attempt_state(session, slug, attempt_uid)
    for question in state["attempt"]["questions"]:
        if correct:
            answer_correctly(session, slug, attempt_uid, question)
        else:
            session.post(
                f"{BASE_URL}/quizzes/{slug}/attempts/{attempt_uid}/answer",
                data={"question_uid": question["uid"], "answer_text": "-1"},
                headers=JSON,
            )
    session.post(f"{BASE_URL}/quizzes/{slug}/attempts/{attempt_uid}/finish", headers=JSON)


def _entries(slug, limit=None):
    url = f"{BASE_URL}/quizzes/{slug}/leaderboard"
    if limit is not None:
        url = f"{url}?limit={limit}"
    return requests.get(url, headers=JSON).json()["entries"]


def test_the_leaderboard_is_public(app_server, seeded_db):
    owner, _ = signup()
    slug = build_published(owner, questions=(NUMERIC,), title="Public board quiz")
    response = requests.get(f"{BASE_URL}/quizzes/{slug}/leaderboard", headers=JSON)
    assert response.status_code == 200
    assert response.json()["entries"] == []


def test_the_leaderboard_reports_its_quiz(app_server, seeded_db):
    from devplacepy.database import get_table, refresh_snapshot

    owner, _ = signup()
    slug = build_published(owner, questions=(NUMERIC,), title="Board uid quiz")
    refresh_snapshot()
    quiz = get_table("quizzes").find_one(slug=slug)
    payload = requests.get(f"{BASE_URL}/quizzes/{slug}/leaderboard", headers=JSON).json()
    assert payload["quiz_uid"] == quiz["uid"]


def test_a_completed_attempt_appears(app_server, seeded_db):
    owner, _ = signup()
    slug = build_published(owner, questions=(NUMERIC,), title="Board entry quiz")
    player, player_name = signup()
    _play(player, slug)
    entries = _entries(slug)
    assert len(entries) == 1
    assert entries[0]["user"]["username"] == player_name
    assert entries[0]["score_percent"] == 100.0
    assert entries[0]["rank"] == 1


def test_an_unfinished_attempt_never_appears(app_server, seeded_db):
    owner, _ = signup()
    slug = build_published(owner, questions=(NUMERIC,), title="Board unfinished quiz")
    player, _ = signup()
    start_attempt(player, slug)
    assert _entries(slug) == []


def test_the_best_score_ranks_first(app_server, seeded_db):
    owner, _ = signup()
    slug = build_published(owner, questions=(NUMERIC,), title="Board ranking quiz")
    weak, weak_name = signup()
    strong, strong_name = signup()
    _play(weak, slug, correct=False)
    _play(strong, slug, correct=True)
    entries = _entries(slug)
    assert entries[0]["user"]["username"] == strong_name
    assert entries[-1]["user"]["username"] == weak_name


def test_ranks_are_gapless(app_server, seeded_db):
    owner, _ = signup()
    slug = build_published(owner, questions=(NUMERIC,), title="Board gapless quiz")
    for _ in range(3):
        player, _ = signup()
        _play(player, slug)
    ranks = [entry["rank"] for entry in _entries(slug)]
    assert ranks == list(range(1, len(ranks) + 1))


def test_the_limit_bounds_the_board(app_server, seeded_db):
    owner, _ = signup()
    slug = build_published(owner, questions=(NUMERIC,), title="Board limit quiz")
    for _ in range(3):
        player, _ = signup()
        _play(player, slug)
    assert len(_entries(slug, limit=2)) == 2


def test_the_pass_verdict_is_carried(app_server, seeded_db):
    owner, _ = signup()
    slug = build_published(
        owner, questions=(NUMERIC,), title="Board verdict quiz", pass_percent="50"
    )
    player, _ = signup()
    _play(player, slug)
    assert _entries(slug)[0]["passed"] is True


def test_the_board_projects_users_through_the_safe_schema(app_server, seeded_db):
    owner, _ = signup()
    slug = build_published(owner, questions=(NUMERIC,), title="Board safe user quiz")
    player, _ = signup()
    _play(player, slug)
    user = _entries(slug)[0]["user"]
    assert "email" not in user
    assert "api_key" not in user


def test_the_authors_own_attempt_is_on_the_quiz_board(app_server, seeded_db):
    owner, owner_name = signup()
    slug = build_published(owner, questions=(NUMERIC,), title="Board author quiz")
    _play(owner, slug)
    assert _entries(slug)[0]["user"]["username"] == owner_name


def test_a_draft_board_is_hidden_from_a_guest(app_server, seeded_db):
    session, _ = signup()
    slug = create_quiz(session, "Board draft quiz")
    response = requests.get(f"{BASE_URL}/quizzes/{slug}/leaderboard", headers=JSON)
    assert response.status_code == 404


def test_the_detail_page_embeds_the_board(app_server, seeded_db):
    owner, _ = signup()
    slug = build_published(owner, questions=(NUMERIC,), title="Board embedded quiz")
    player, player_name = signup()
    _play(player, slug)
    payload = requests.get(f"{BASE_URL}/quizzes/{slug}", headers=JSON).json()
    assert any(entry["user"]["username"] == player_name for entry in payload["leaderboard"])
