"""Tests for websocket manager replay and per-session rate limits."""

from __future__ import annotations

import asyncio
from types import SimpleNamespace

from ieum.server.websocket.manager import WebSocketManager
from ieum.server.websocket.protocol import MessageType, WSMessage


class _FakeConnection:
    def __init__(self) -> None:
        self.sent: list[WSMessage] = []

    async def send(self, message: WSMessage) -> None:
        self.sent.append(message)


def test_replay_history_from_last_seq() -> None:
    async def _run() -> None:
        manager = WebSocketManager()
        session_id = "session-1"

        await manager.broadcast(
            session_id,
            WSMessage(type=MessageType.SYSTEM_MESSAGE, data={"content": "first"}),
        )
        await manager.broadcast(
            session_id,
            WSMessage(type=MessageType.SYSTEM_MESSAGE, data={"content": "second"}),
        )

        conn = _FakeConnection()
        await manager._replay_history(conn, session_id=session_id, last_seq=1)

        assert len(conn.sent) == 1
        replayed = conn.sent[0]
        assert replayed.type == MessageType.SYSTEM_MESSAGE
        assert replayed.data["content"] == "second"
        assert replayed.data["_seq"] == 2

    asyncio.run(_run())


def test_allow_session_message_rate_limit() -> None:
    async def _run() -> None:
        manager = WebSocketManager()
        session = SimpleNamespace(
            id="session-rl",
            rate_limit_max_requests=2,
            rate_limit_window_seconds=60,
        )

        assert await manager._allow_session_message(session) is True
        assert await manager._allow_session_message(session) is True
        assert await manager._allow_session_message(session) is False

    asyncio.run(_run())


def test_allow_session_message_without_limits() -> None:
    async def _run() -> None:
        manager = WebSocketManager()
        session = SimpleNamespace(
            id="session-open",
            rate_limit_max_requests=None,
            rate_limit_window_seconds=None,
        )
        assert await manager._allow_session_message(session) is True

    asyncio.run(_run())
