"""Tests for BridgeConnection async WebSocket client."""

from __future__ import annotations

import pytest

from godotiq.bridge.connection import (
    BridgeConnection,
    BridgeConnectionError,
    BridgeError,
)


class TestBridgeConnectionInit:
    """Constructor and initial state."""

    def test_default_host_and_port(self) -> None:
        """Default host is 127.0.0.1 and port is 6007."""
        conn = BridgeConnection()
        assert conn._host == "127.0.0.1"
        assert conn._port == 6007

    def test_custom_host_and_port(self) -> None:
        """Custom host and port are stored correctly."""
        conn = BridgeConnection(host="192.168.1.1", port=9999)
        assert conn._host == "192.168.1.1"
        assert conn._port == 9999

    def test_initial_state_disconnected(self) -> None:
        """is_connected and is_game_running are False initially."""
        conn = BridgeConnection()
        assert conn.is_connected is False
        assert conn.is_game_running is False


class TestBridgeConnectionRequest:
    """Request behavior without connection."""

    async def test_request_without_connect_raises(self) -> None:
        """request() without connect() raises BridgeConnectionError."""
        conn = BridgeConnection()
        with pytest.raises(BridgeConnectionError):
            await conn.request("ping")


class TestBridgeConnectionEvents:
    """Game state tracking and event dispatch."""

    def test_on_game_started(self) -> None:
        """_on_game_started sets is_game_running to True."""
        conn = BridgeConnection()
        conn._on_game_started({})
        assert conn.is_game_running is True

    def test_on_game_stopped(self) -> None:
        """_on_game_stopped sets is_game_running to False."""
        conn = BridgeConnection()
        conn._game_running = True
        conn._on_game_stopped({})
        assert conn.is_game_running is False

    def test_event_handler_called(self) -> None:
        """Registered event handler is called with correct data."""
        conn = BridgeConnection()
        received = []
        conn.on_event("test_event", lambda data: received.append(data))
        conn._dispatch_event("test_event", {"key": "value"})
        assert len(received) == 1
        assert received[0] == {"key": "value"}

    def test_multiple_handlers_same_event(self) -> None:
        """Multiple handlers for same event are all called."""
        conn = BridgeConnection()
        results_a = []
        results_b = []
        conn.on_event("multi", lambda d: results_a.append(d))
        conn.on_event("multi", lambda d: results_b.append(d))
        conn._dispatch_event("multi", {"x": 1})
        assert len(results_a) == 1
        assert len(results_b) == 1


class TestBridgeConnectionErrorTypes:
    """Custom exception attributes."""

    def test_bridge_error_attributes(self) -> None:
        """BridgeError stores code and error_message attributes."""
        err = BridgeError("GAME_NOT_RUNNING", "Start the game first")
        assert err.code == "GAME_NOT_RUNNING"
        assert err.error_message == "Start the game first"

    def test_bridge_error_str_includes_code(self) -> None:
        """BridgeError str includes the error code."""
        err = BridgeError("TIMEOUT", "Request timed out")
        assert "TIMEOUT" in str(err)
