"""
Manuell status per deltaker (migrasjon 087, 2026-08-18). Bruker: "Vi må
manuelt kunne sette Dsq, Rtd, Dnf, og fns [DNS]." Tournament-bredt
(ikke per runde), overstyrer BÅDE det beregnede til-par-tallet og en
ev. Cut-status, og blokkerer videre score-registrering i ALLE runder
(strengere enn Cut, som kun blokkerer runder ETTER cut-punktet).
"""

import pytest
from fastapi import HTTPException

from app.auth import CurrentUser
from app.routers.individual_tournaments import (
    HoleUpdate as TournamentHoleUpdate,
    TournamentParticipantUpdate,
    individual_leaderboard,
    update_hole as tournament_update_hole,
    update_tournament_participant,
)

from tests.conftest import (
    add_membership,
    create_org,
    create_org_hole,
    create_course,
    create_player,
    create_tee,
    create_tournament,
    create_tournament_participant,
    create_tournament_round,
    create_tournament_round_participant,
    create_user,
)

import app.db as app_db


async def _score_holes(tournament_id, round_id, rp_id, org_id, user_id, scores: list[int]) -> None:
    user = CurrentUser(user_id=user_id)
    for n, gross in enumerate(scores, start=1):
        await tournament_update_hole(
            tournament_id, round_id, rp_id, n,
            TournamentHoleUpdate(gross_strokes=gross, expected_version=None),
            organization_id=org_id, user=user,
        )


async def _setup(org_id, owner_id, method="stroke_gross"):
    tournament_id = await create_tournament(org_id, name="Status-turnering")
    course_id = await create_course(org_id, name="Status Links")
    for n in range(1, 19):
        await create_org_hole(org_id, course_id, hole_number=n, par=4, stroke_index=n)
    tee_id = await create_tee(org_id, course_id)
    async with app_db.org_connection(org_id) as conn:
        await conn.execute(
            "UPDATE tournament SET format_type = 'individual', scoring_method = $2 WHERE id = $1",
            tournament_id, method,
        )
    round1_id = await create_tournament_round(org_id, tournament_id, course_id, sequence=1)
    round2_id = await create_tournament_round(org_id, tournament_id, course_id, sequence=2)
    return tournament_id, course_id, tee_id, round1_id, round2_id


@pytest.mark.parametrize("status", ["dsq", "rtd", "dnf", "dns"])
async def test_status_overrides_computed_total_label(pool, status):
    org_id = await create_org()
    owner_id = await create_user()
    await add_membership(org_id, owner_id, role="owner")
    tournament_id, course_id, tee_id, round1_id, round2_id = await _setup(org_id, owner_id)

    player_id = await create_player(org_id, display_name="Spiller")
    tp_id = await create_tournament_participant(org_id, tournament_id, player_id)
    rp_id = await create_tournament_round_participant(org_id, round1_id, tp_id, tee_id)
    await _score_holes(tournament_id, round1_id, rp_id, org_id, owner_id, [4] * 18)

    await update_tournament_participant(
        tournament_id, tp_id, TournamentParticipantUpdate(status=status), organization_id=org_id
    )

    entries = await individual_leaderboard(tournament_id, organization_id=org_id)
    entry = next(e for e in entries if e.tournament_participant_id == tp_id)
    assert entry.total_label == status.upper()
    assert entry.is_leader is False
    assert entry.position is None
    assert entry.status == status


async def test_status_overrides_even_a_cut_survivor(pool):
    """En DSQ-et spiller skal vises som DSQ, ikke CUT, selv om de
    tilfeldigvis også overlevde cutten."""
    org_id = await create_org()
    owner_id = await create_user()
    await add_membership(org_id, owner_id, role="owner")
    tournament_id, course_id, tee_id, round1_id, round2_id = await _setup(org_id, owner_id)

    from app.routers.tournaments import TournamentUpdate, update_tournament
    from app.routers.individual_tournaments import apply_cut

    await update_tournament(
        tournament_id, TournamentUpdate(cut_after_round=1, cut_size=5), organization_id=org_id,
    )

    player_id = await create_player(org_id, display_name="Spiller")
    tp_id = await create_tournament_participant(org_id, tournament_id, player_id)
    rp_id = await create_tournament_round_participant(org_id, round1_id, tp_id, tee_id)
    await _score_holes(tournament_id, round1_id, rp_id, org_id, owner_id, [4] * 18)

    await apply_cut(tournament_id, organization_id=org_id)
    await update_tournament_participant(
        tournament_id, tp_id, TournamentParticipantUpdate(status="dsq"), organization_id=org_id
    )

    entries = await individual_leaderboard(tournament_id, organization_id=org_id)
    entry = next(e for e in entries if e.tournament_participant_id == tp_id)
    assert entry.total_label == "DSQ"
    assert entry.cut is False  # var faktisk innenfor cut-grensen


async def test_status_blocks_scoring_in_any_round_not_just_after_a_point(pool):
    """Strengere enn Cut: en DSQ-et/RTD-et/DNF-et/DNS-et spiller er
    blokkert i ALLE runder, ikke bare etter et gitt punkt."""
    org_id = await create_org()
    owner_id = await create_user()
    await add_membership(org_id, owner_id, role="owner")
    tournament_id, course_id, tee_id, round1_id, round2_id = await _setup(org_id, owner_id)

    player_id = await create_player(org_id, display_name="Spiller")
    tp_id = await create_tournament_participant(org_id, tournament_id, player_id)
    rp1_id = await create_tournament_round_participant(org_id, round1_id, tp_id, tee_id)
    rp2_id = await create_tournament_round_participant(org_id, round2_id, tp_id, tee_id)

    await update_tournament_participant(
        tournament_id, tp_id, TournamentParticipantUpdate(status="dsq"), organization_id=org_id
    )

    user = CurrentUser(user_id=owner_id)
    with pytest.raises(HTTPException) as exc_round1:
        await tournament_update_hole(
            tournament_id, round1_id, rp1_id, 1,
            TournamentHoleUpdate(gross_strokes=4, expected_version=None),
            organization_id=org_id, user=user,
        )
    assert exc_round1.value.status_code == 403

    with pytest.raises(HTTPException) as exc_round2:
        await tournament_update_hole(
            tournament_id, round2_id, rp2_id, 1,
            TournamentHoleUpdate(gross_strokes=4, expected_version=None),
            organization_id=org_id, user=user,
        )
    assert exc_round2.value.status_code == 403


async def test_active_status_is_unaffected_default(pool):
    """Ingen regresjon -- default 'active' oppfører seg akkurat som før."""
    org_id = await create_org()
    owner_id = await create_user()
    await add_membership(org_id, owner_id, role="owner")
    tournament_id, course_id, tee_id, round1_id, round2_id = await _setup(org_id, owner_id)

    player_id = await create_player(org_id, display_name="Spiller")
    tp_id = await create_tournament_participant(org_id, tournament_id, player_id)
    rp_id = await create_tournament_round_participant(org_id, round1_id, tp_id, tee_id)
    await _score_holes(tournament_id, round1_id, rp_id, org_id, owner_id, [4] * 18)

    entries = await individual_leaderboard(tournament_id, organization_id=org_id)
    entry = next(e for e in entries if e.tournament_participant_id == tp_id)
    assert entry.status == "active"
    assert entry.total_label == "E"
    assert entry.position == "1"
