"""Tests for the BotVegas HTTP client."""

import pytest
import httpx
from unittest.mock import AsyncMock, patch

from botvegas_mcp.client import BotVegasClient, BotVegasAPIError


@pytest.fixture
def mock_http_client():
    """Create a mock HTTP client."""
    return AsyncMock(spec=httpx.AsyncClient)


@pytest.fixture
def client(mock_http_client):
    """Create a BotVegasClient with mocked HTTP."""
    return BotVegasClient(http=mock_http_client)


class TestBotVegasClient:
    """Test the BotVegasClient class."""

    @pytest.mark.asyncio
    async def test_auth_headers(self, client):
        """Test authorization header generation."""
        headers = client._auth_headers("test-token")
        assert headers == {"Authorization": "Bearer test-token"}

    @pytest.mark.asyncio
    async def test_request_success(self, client, mock_http_client):
        """Test successful API request."""
        mock_response = AsyncMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {"success": True}
        mock_http_client.request.return_value = mock_response

        result = await client._request("GET", "/test")

        assert result == {"success": True}
        mock_http_client.request.assert_called_once()

    @pytest.mark.asyncio
    async def test_request_with_token(self, client, mock_http_client):
        """Test request with authentication token."""
        mock_response = AsyncMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {"data": "test"}
        mock_http_client.request.return_value = mock_response

        await client._request("GET", "/test", token="my-token")

        call_kwargs = mock_http_client.request.call_args
        assert call_kwargs.kwargs["headers"] == {"Authorization": "Bearer my-token"}

    @pytest.mark.asyncio
    async def test_request_error(self, client, mock_http_client):
        """Test API error handling."""
        mock_response = AsyncMock()
        mock_response.status_code = 400
        mock_response.json.return_value = {"detail": "Bad request"}
        mock_http_client.request.return_value = mock_response

        with pytest.raises(BotVegasAPIError) as exc_info:
            await client._request("GET", "/test")

        assert exc_info.value.status_code == 400
        assert "Bad request" in exc_info.value.message

    @pytest.mark.asyncio
    async def test_register_identity(self, client, mock_http_client):
        """Test identity registration."""
        mock_response = AsyncMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "id": "123",
            "name": "TestAgent",
            "description": "A test agent",
        }
        mock_http_client.request.return_value = mock_response

        result = await client.register_identity(
            name="TestAgent",
            description="A test agent",
        )

        assert result["name"] == "TestAgent"
        call_kwargs = mock_http_client.request.call_args
        assert call_kwargs.kwargs["json"] == {
            "name": "TestAgent",
            "description": "A test agent",
        }

    @pytest.mark.asyncio
    async def test_create_player(self, client, mock_http_client):
        """Test player creation."""
        mock_response = AsyncMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "id": "456",
            "handle": "TestPlayer",
            "token": "secret-token",
            "chips": 10000,
        }
        mock_http_client.request.return_value = mock_response

        result = await client.create_player(
            identity_id="123",
            handle="TestPlayer",
        )

        assert result["handle"] == "TestPlayer"
        assert "token" in result

    @pytest.mark.asyncio
    async def test_list_games(self, client, mock_http_client):
        """Test listing games."""
        mock_response = AsyncMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "games": [
                {"id": "game1", "status": "waiting"},
                {"id": "game2", "status": "in_progress"},
            ]
        }
        mock_http_client.request.return_value = mock_response

        result = await client.list_games(stake_tier="micro", limit=10)

        assert len(result["games"]) == 2
        call_kwargs = mock_http_client.request.call_args
        assert call_kwargs.kwargs["params"]["stake_tier"] == "micro"
        assert call_kwargs.kwargs["params"]["limit"] == 10

    @pytest.mark.asyncio
    async def test_create_game(self, client, mock_http_client):
        """Test game creation."""
        mock_response = AsyncMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "id": "new-game",
            "status": "waiting",
            "stake_tier": "micro",
        }
        mock_http_client.request.return_value = mock_response

        result = await client.create_game(
            token="my-token",
            stake_tier="micro",
            max_players=6,
            min_players_to_start=2,
            turn_timeout_seconds=30,
            buy_in=500,
        )

        assert result["id"] == "new-game"
        call_kwargs = mock_http_client.request.call_args
        assert call_kwargs.kwargs["json"]["stake_tier"] == "micro"
        assert call_kwargs.kwargs["json"]["buy_in"] == 500

    @pytest.mark.asyncio
    async def test_take_action(self, client, mock_http_client):
        """Test taking a poker action."""
        mock_response = AsyncMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "success": True,
            "action": "raise",
            "amount": 100,
            "pot_total": 250,
        }
        mock_http_client.request.return_value = mock_response

        result = await client.take_action(
            token="my-token",
            game_id="game-123",
            action="raise",
            amount=100,
            expression="I'm feeling lucky!",
        )

        assert result["success"] is True
        assert result["action"] == "raise"
        call_kwargs = mock_http_client.request.call_args
        assert call_kwargs.kwargs["json"]["action"] == "raise"
        assert call_kwargs.kwargs["json"]["amount"] == 100
        assert call_kwargs.kwargs["json"]["expression"] == "I'm feeling lucky!"

    @pytest.mark.asyncio
    async def test_get_stake_tiers(self, client):
        """Test getting stake tiers (static data)."""
        result = await client.get_stake_tiers()

        assert "tiers" in result
        assert len(result["tiers"]) == 5
        tier_names = [t["name"] for t in result["tiers"]]
        assert "micro" in tier_names
        assert "high_roller" in tier_names

    @pytest.mark.asyncio
    async def test_get_hand_history_stub(self, client):
        """Test hand history stub response."""
        result = await client.get_hand_history(
            token="my-token",
            game_id="game-123",
            hand_number=1,
        )

        # Should return stub response since endpoint not implemented
        assert result["game_id"] == "game-123"
        assert "message" in result


class TestBotVegasAPIError:
    """Test the BotVegasAPIError exception."""

    def test_error_message(self):
        """Test error message formatting."""
        error = BotVegasAPIError(404, "Not found", {"resource": "game"})

        assert error.status_code == 404
        assert error.message == "Not found"
        assert error.details == {"resource": "game"}
        assert "[404]" in str(error)
        assert "Not found" in str(error)

    def test_error_without_details(self):
        """Test error without details."""
        error = BotVegasAPIError(500, "Internal error")

        assert error.status_code == 500
        assert error.details == {}
