"""
Full sletting av en hel turnering (ADR-086) -- kritisk å teste med EKTE
populert data i begge formater, ikke bare en tom turnering, siden skjemaet
har to RESTRICT-FK-er MIDT INNI kaskade-grafen (match_participant.
team_roster_id, tournament_round_participant.tournament_participant_id) som
kan avvise en naiv enkelt-setnings-kaskade. Se delete_tournament() sin egen
kommentar i app/routers/tournaments.py for full begrunnelse.
"""

import pytest
from fastapi import HTTPException

from app.auth import CurrentUser
from app.routers.tournaments import delete_tournament

from tests.conftest import (
    add_membership,
    create_course,
    create_match,
    create_match_participant,
    create_org,
    create_org_hole,
    create_player,
    create_session,
    create_team,
    create_team_roster,
    create_tee,
    create_tournament,
    create_tournament_participant,
    create_tournament_round,
    create_tournament_round_participant,
    create_user,
)
from app import db as app_db


async def test_delete_team_tournament_with_real_matches_and_scores(pool):
    org_id = await create_org()
    owner_id = await create_user()
    await add_membership(org_id, owner_id, role="owner")
    tournament_id = await create_tournament(org_id)
    course_id = await create_course(org_id)
    tee_id = await create_tee(org_id, course_id)
    session_id = await create_session(org_id, tournament_id, course_id)
    team_a = await create_team(org_id, tournament_id)
    team_b = await create_team(org_id, tournament_id)
    match_id = await create_match(org_id, session_id, team_a, team_b)
    player_a = await create_player(org_id)
    player_b = await create_player(org_id)
    roster_a = await create_team_roster(org_id, team_a, player_a)
    roster_b = await create_team_roster(org_id, team_b, player_b)
    mp_a = await create_match_participant(org_id, match_id, "a", roster_a, tee_id)
    mp_b = await create_match_participant(org_id, match_id, "b", roster_b, tee_id)

    async with app_db.org_connection(org_id) as conn:
        await conn.execute(
            "INSERT INTO hole_score (organization_id, match_id, team_side, match_participant_id, "
            "hole_number, gross_strokes) VALUES ($1, $2, 'a', $3, 1, 4)",
            org_id, match_id, mp_a,
        )
        await conn.execute(
            "INSERT INTO hole_score (organization_id, match_id, team_side, match_participant_id, "
            "hole_number, gross_strokes) VALUES ($1, $2, 'b', $3, 1, 5)",
            org_id, match_id, mp_b,
        )

    user = CurrentUser(user_id=owner_id)
    await delete_tournament(tournament_id, organization_id=org_id, user=user)

    async with app_db.org_connection(org_id) as conn:
        assert await conn.fetchval("SELECT EXISTS(SELECT 1 FROM tournament WHERE id = $1)", tournament_id) is False
        assert await conn.fetchval("SELECT count(*) FROM session WHERE tournament_id = $1", tournament_id) == 0
        assert await conn.fetchval("SELECT count(*) FROM match WHERE id = $1", match_id) == 0
        assert await conn.fetchval("SELECT count(*) FROM match_participant WHERE match_id = $1", match_id) == 0
        assert await conn.fetchval("SELECT count(*) FROM hole_score WHERE match_id = $1", match_id) == 0
        assert await conn.fetchval("SELECT count(*) FROM team_roster WHERE team_id = $1", team_a) == 0
        assert await conn.fetchval("SELECT count(*) FROM team WHERE tournament_id = $1", tournament_id) == 0
        # Spillerne selv (org-scopet spillerpool) skal IKKE slettes -- kun
        # turneringens egne koblinger til dem.
        assert await conn.fetchval("SELECT EXISTS(SELECT 1 FROM player WHERE id = $1)", player_a) is True


async def test_delete_individual_tournament_with_real_rounds_and_scores(pool):
    org_id = await create_org()
    owner_id = await create_user()
    await add_membership(org_id, owner_id, role="owner")
    tournament_id = await create_tournament(org_id)
    course_id = await create_course(org_id)
    for n in range(1, 19):
        await create_org_hole(org_id, course_id, hole_number=n)
    tee_id = await create_tee(org_id, course_id)
    round_id = await create_tournament_round(org_id, tournament_id, course_id)
    player_id = await create_player(org_id)
    tp_id = await create_tournament_participant(org_id, tournament_id, player_id)
    rp_id = await create_tournament_round_participant(org_id, round_id, tp_id, tee_id)

    async with app_db.org_connection(org_id) as conn:
        await conn.execute(
            "INSERT INTO tournament_round_hole (organization_id, tournament_round_participant_id, "
            "hole_number, gross_strokes) VALUES ($1, $2, 1, 4)",
            org_id, rp_id,
        )
        # Utslagsgruppe (migrasjon 084) MED en deltaker faktisk koblet på --
        # egen RESTRICT-FK (tournament_round_participant.tournament_round_
        # group_id), samme klasse fallgruve som match_participant.team_
        # roster_id over. Deltaker slettes FØR runden (og dermed gruppen,
        # som kaskaderer fra runden) -- se delete_tournament sin kommentar.
        group_id = await conn.fetchval(
            "INSERT INTO tournament_round_group (organization_id, tournament_round_id, sequence) "
            "VALUES ($1, $2, 1) RETURNING id",
            org_id, round_id,
        )
        await conn.execute(
            "UPDATE tournament_round_participant SET tournament_round_group_id = $1 WHERE id = $2",
            group_id, rp_id,
        )

    user = CurrentUser(user_id=owner_id)
    await delete_tournament(tournament_id, organization_id=org_id, user=user)

    async with app_db.org_connection(org_id) as conn:
        assert await conn.fetchval("SELECT EXISTS(SELECT 1 FROM tournament WHERE id = $1)", tournament_id) is False
        assert await conn.fetchval("SELECT count(*) FROM tournament_round WHERE tournament_id = $1", tournament_id) == 0
        assert await conn.fetchval("SELECT count(*) FROM tournament_participant WHERE tournament_id = $1", tournament_id) == 0
        assert await conn.fetchval(
            "SELECT count(*) FROM tournament_round_participant WHERE tournament_round_id = $1", round_id
        ) == 0
        assert await conn.fetchval(
            "SELECT count(*) FROM tournament_round_hole WHERE tournament_round_participant_id = $1", rp_id
        ) == 0
        assert await conn.fetchval(
            "SELECT count(*) FROM tournament_round_group WHERE tournament_round_id = $1", round_id
        ) == 0


async def test_delete_requires_org_admin_not_just_member(pool):
    org_id = await create_org()
    member_id = await create_user()
    await add_membership(org_id, member_id, role="member")
    tournament_id = await create_tournament(org_id)

    user = CurrentUser(user_id=member_id)
    with pytest.raises(HTTPException) as exc_info:
        await delete_tournament(tournament_id, organization_id=org_id, user=user)
    assert exc_info.value.status_code == 403

    async with app_db.org_connection(org_id) as conn:
        assert await conn.fetchval("SELECT EXISTS(SELECT 1 FROM tournament WHERE id = $1)", tournament_id) is True


async def test_delete_nonexistent_tournament_is_404(pool):
    org_id = await create_org()
    owner_id = await create_user()
    await add_membership(org_id, owner_id, role="owner")

    user = CurrentUser(user_id=owner_id)
    with pytest.raises(HTTPException) as exc_info:
        await delete_tournament("00000000-0000-0000-0000-000000000000", organization_id=org_id, user=user)
    assert exc_info.value.status_code == 404
