from __future__ import annotations

import time
import uuid
from collections.abc import Callable

from openpoker.types import EngineEvent, EngineEventType, EventPayload, GameSnapshot

EventCallback = Callable[[EngineEvent], None]


class EventEmitter:
    def __init__(self) -> None:
        self._sequence = 0
        self._subscribers: list[EventCallback] = []
        self._history: list[EngineEvent] = []

    def subscribe(self, callback: EventCallback) -> Callable[[], None]:
        self._subscribers.append(callback)

        def unsubscribe() -> None:
            self.unsubscribe(callback)

        return unsubscribe

    def unsubscribe(self, callback: EventCallback) -> None:
        self._subscribers = [sub for sub in self._subscribers if sub is not callback]

    def emit(
        self,
        event_type: EngineEventType,
        game_id: str,
        hand_number: int,
        payload: EventPayload,
        snapshot: GameSnapshot | None = None,
    ) -> EngineEvent:
        self._sequence += 1
        event = EngineEvent(
            event_id=str(uuid.uuid4()),
            sequence=self._sequence,
            timestamp=time.time(),
            event_type=event_type,
            game_id=game_id,
            hand_number=hand_number,
            payload=payload,
            snapshot=snapshot,
        )
        self._history.append(event)
        for callback in list(self._subscribers):
            callback(event)
        return event

    def get_history(self) -> list[EngineEvent]:
        return list(self._history)
