"""
Utslagsgrupper (migrasjon 084, 2026-08-18, ADR-088): hvem spiller med
hvem, klokka når -- for individuelle turneringer. Bruker: "Jeg må jo
kunne bulksjekke hvem som skal spille fra hvor, med hvem, klokka når?"
Design bekreftet: tradisjonelt utslag (samme starthull, staggerte
klokkeslett med fast intervall), manuell gruppesammensetning med et
forslag å justere, fast gruppestørrelse.
"""

from app.routers.individual_tournaments import (
    RoundGroupIn,
    SaveRoundGroupsIn,
    SuggestGroupsIn,
    TournamentRoundUpdate,
    list_round_groups,
    save_round_groups,
    suggest_round_groups,
    update_round,
)

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

import app.db as app_db


async def _setup(org_id, n_players=5):
    tournament_id = await create_tournament(org_id, name="Gruppe-turnering")
    course_id = await create_course(org_id, name="Gruppe Links")
    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 = 'stroke_gross' WHERE id = $1",
            tournament_id,
        )
    round_id = await create_tournament_round(org_id, tournament_id, course_id, sequence=1)

    rp_ids = []
    for i in range(n_players):
        player_id = await create_player(org_id, display_name=f"Spiller {i:02d}")
        tp_id = await create_tournament_participant(org_id, tournament_id, player_id)
        rp_ids.append(await create_tournament_round_participant(org_id, round_id, tp_id, tee_id))
    return tournament_id, round_id, rp_ids


async def test_update_round_sets_scheduling_fields(pool):
    org_id = await create_org()
    tournament_id, round_id, _ = await _setup(org_id, n_players=1)

    updated = await update_round(
        tournament_id, round_id,
        TournamentRoundUpdate(scheduled_at="2026-08-19T10:00:00", tee_interval_minutes=10, start_hole=1),
        organization_id=org_id,
    )
    assert updated.tee_interval_minutes == 10
    assert updated.start_hole == 1
    assert "2026-08-19" in (updated.scheduled_at or "")


async def test_suggest_round_groups_chunks_by_size_and_computes_tee_times_without_saving(pool):
    org_id = await create_org()
    tournament_id, round_id, rp_ids = await _setup(org_id, n_players=5)
    await update_round(
        tournament_id, round_id,
        TournamentRoundUpdate(scheduled_at="2026-08-19T10:00:00", tee_interval_minutes=10),
        organization_id=org_id,
    )

    suggestion = await suggest_round_groups(
        tournament_id, round_id, SuggestGroupsIn(group_size=2), organization_id=org_id
    )
    assert [len(g.participants) for g in suggestion.groups] == [2, 2, 1]
    assert [g.sequence for g in suggestion.groups] == [1, 2, 3]
    assert suggestion.groups[0].tee_time is not None and "10:00" in suggestion.groups[0].tee_time
    assert suggestion.groups[1].tee_time is not None and "10:10" in suggestion.groups[1].tee_time
    assert suggestion.groups[2].tee_time is not None and "10:20" in suggestion.groups[2].tee_time
    # Alle grupper i forslaget er usaved (id=None).
    assert all(g.id is None for g in suggestion.groups)

    # Ingenting skal faktisk ha blitt lagret av selve forslaget.
    saved = await list_round_groups(tournament_id, round_id, organization_id=org_id)
    assert saved.groups == []
    assert len(saved.ungrouped) == 5


async def test_save_round_groups_persists_and_fully_replaces_previous(pool):
    org_id = await create_org()
    tournament_id, round_id, rp_ids = await _setup(org_id, n_players=4)
    await update_round(
        tournament_id, round_id,
        TournamentRoundUpdate(scheduled_at="2026-08-19T10:00:00", tee_interval_minutes=10),
        organization_id=org_id,
    )

    first = await save_round_groups(
        tournament_id, round_id,
        SaveRoundGroupsIn(groups=[
            RoundGroupIn(sequence=1, round_participant_ids=[rp_ids[0], rp_ids[1]]),
            RoundGroupIn(sequence=2, round_participant_ids=[rp_ids[2], rp_ids[3]]),
        ]),
        organization_id=org_id,
    )
    assert len(first.groups) == 2
    assert len(first.ungrouped) == 0

    # Lagre på nytt med en HELT ANNEN sammensetning -- skal erstatte, ikke legge til.
    second = await save_round_groups(
        tournament_id, round_id,
        SaveRoundGroupsIn(groups=[
            RoundGroupIn(sequence=1, round_participant_ids=[rp_ids[0], rp_ids[2], rp_ids[3]]),
        ]),
        organization_id=org_id,
    )
    assert len(second.groups) == 1
    assert len(second.groups[0].participants) == 3
    assert len(second.ungrouped) == 1
    assert second.ungrouped[0].round_participant_id == rp_ids[1]

    async with app_db.org_connection(org_id) as conn:
        group_count = await conn.fetchval(
            "SELECT count(*) FROM tournament_round_group WHERE tournament_round_id = $1", round_id
        )
    assert group_count == 1  # den gamle gruppen faktisk slettet, ikke bare "løsrevet"


async def test_save_round_groups_leaves_unlisted_participants_ungrouped(pool):
    org_id = await create_org()
    tournament_id, round_id, rp_ids = await _setup(org_id, n_players=3)

    result = await save_round_groups(
        tournament_id, round_id,
        SaveRoundGroupsIn(groups=[RoundGroupIn(sequence=1, round_participant_ids=[rp_ids[0]])]),
        organization_id=org_id,
    )
    assert len(result.groups) == 1
    assert {p.round_participant_id for p in result.ungrouped} == {rp_ids[1], rp_ids[2]}


async def test_group_tee_time_override_wins_over_computed(pool):
    org_id = await create_org()
    tournament_id, round_id, rp_ids = await _setup(org_id, n_players=2)
    await update_round(
        tournament_id, round_id,
        TournamentRoundUpdate(scheduled_at="2026-08-19T10:00:00", tee_interval_minutes=10),
        organization_id=org_id,
    )

    result = await save_round_groups(
        tournament_id, round_id,
        SaveRoundGroupsIn(groups=[
            RoundGroupIn(sequence=1, tee_time_override="2026-08-19T09:15:00", round_participant_ids=rp_ids),
        ]),
        organization_id=org_id,
    )
    assert result.groups[0].tee_time is not None
    assert "09:15" in result.groups[0].tee_time  # override, IKKE den utledede 10:00
