from __future__ import annotations

import types

import ui.playback_controller as playback


class FakePlayer:
    def __init__(self):
        self.playing = False
        self.paused = False
        self.calls = []

    def play(self, file_path, start_pos=0.0):
        self.calls.append(("play", file_path, start_pos))
        self.playing = True
        self.paused = False

    def stop(self):
        self.calls.append(("stop",))
        self.playing = False
        self.paused = False

    def pause(self):
        self.calls.append(("pause",))
        self.playing = False
        self.paused = True

    def unpause(self):
        self.calls.append(("unpause",))
        self.playing = True
        self.paused = False

    def is_playing(self):
        return self.playing

    def is_paused(self):
        return self.paused

    def cleanup(self):
        self.calls.append(("cleanup",))


def test_playback_session_play_pause_seek_stop(monkeypatch):
    clock = {"value": 100.0}
    monkeypatch.setattr(playback.time, "monotonic", lambda: clock["value"])
    fake = FakePlayer()
    session = playback.PlaybackSession(player_factory=lambda: fake)
    session.set_source("track.wav", 120.0)

    assert session.toggle() is True
    clock["value"] = 105.5
    assert session.current_time() == 5.5

    assert session.toggle() is False
    assert session.is_paused
    assert session.position == 5.5

    session.seek(42.0)
    assert session.position == 42.0
    assert session.is_paused
    assert fake.calls[-2:] == [("play", "track.wav", 42.0), ("pause",)]

    assert session.toggle() is True
    clock["value"] = 108.0
    assert session.current_time() == 44.5

    session.stop()
    assert session.position == 0.0
    assert not session.is_playing


def test_playback_session_clamps_seek_and_clear():
    fake = FakePlayer()
    session = playback.PlaybackSession(player_factory=lambda: fake)
    session.set_source("track.wav", 10.0)
    assert session.seek(50.0) == 10.0
    assert session.seek(-2.0) == 0.0
    session.clear()
    assert session.file_path is None
    assert session.duration == 0.0
