# tests vagues : WaveManager + WAVE_CONFIGS

from waves import WaveManager, WAVE_CONFIGS
from constants import PREPARATION_DURATION, TICK_DURATION


def _ticks(wm, n, enemy_count=0):
    events = []
    for _ in range(n):
        events.extend(wm.tick(lambda t: None, enemy_count))
    return events


def _complete_wave(wm):
    # avance jusqu'a la fin de la vague (preparation ou victory)
    for _ in range(100_000):
        wm.tick(lambda t: None, 0)
        if wm.state in ("preparation", "victory"):
            return
    raise AssertionError("vague jamais finie")


def _prep_ticks():
    return int(PREPARATION_DURATION / TICK_DURATION) + 1


def _skip_initial_prep(wm):
    while wm.state == "preparation":
        wm.tick(lambda t: None, 0)


def test_three_waves():
    assert len(WAVE_CONFIGS) == 3


def test_initial_state():
    wm = WaveManager()
    assert wm.wave_number == 1
    assert wm.state == "preparation"


def test_first_spawn():
    spawned = []
    wm = WaveManager()
    _skip_initial_prep(wm)
    wm.tick(spawned.append, 999)
    assert len(spawned) >= 1
    assert spawned[0] == WAVE_CONFIGS[0][0].groups[0].enemy_type


def test_phase_avance_quand_zero_ennemis():
    wm = WaveManager()
    for _ in range(100_000):
        if wm.enemies_remaining() == 0:
            break
        wm.tick(lambda t: None, 999)
    wm.tick(lambda t: None, 0)
    assert wm.phase_number == 2


def test_preparation_apres_vague():
    wm = WaveManager()
    _complete_wave(wm)
    assert wm.state == "preparation"


def test_pas_de_spawn_en_prep():
    wm = WaveManager()
    _complete_wave(wm)
    spawned = []
    wm.tick(spawned.append, 0)
    assert spawned == []


def test_vague_2_apres_timer_prep():
    wm = WaveManager()
    _skip_initial_prep(wm)
    _complete_wave(wm)
    _ticks(wm, _prep_ticks())
    assert wm.wave_number == 2
    assert wm.state == "combat"


def test_victory_apres_3_vagues():
    wm = WaveManager()
    _skip_initial_prep(wm)
    for _ in range(3):
        _complete_wave(wm)
        if wm.state == "preparation":
            _ticks(wm, _prep_ticks())
    assert wm.state == "victory"
