"""Integration tests for MCP server.

These tests require a running FastAPI server to fully test the integration.
Some tests use mocks to avoid this dependency.
"""

from __future__ import annotations

from typing import Any
from unittest.mock import AsyncMock, MagicMock, patch

import pytest

from mcp_standalone.client import FastAPIClient
from mcp_standalone.config import MCPConfig
from mcp_standalone.server import create_server


def test_create_server() -> None:
    """Test creating an MCP server instance."""
    server = create_server()
    assert server is not None
    assert server.name == "gdsfactoryplus"


def test_create_server_with_custom_url() -> None:
    """Test creating an MCP server with custom API URL."""
    custom_url = "http://localhost:9999"
    server = create_server(api_url=custom_url)
    assert server is not None


@pytest.mark.anyio
async def test_fastapi_client_lifecycle() -> None:
    """Test FastAPI client start and close."""
    client = FastAPIClient()
    assert client._client is None  # noqa: SLF001

    await client.start()
    assert client._client is not None  # noqa: SLF001

    await client.close()
    assert client._client is None  # noqa: SLF001


@pytest.mark.anyio
async def test_fastapi_client_context_manager() -> None:
    """Test FastAPI client as context manager."""
    async with FastAPIClient() as client:
        assert client._client is not None  # noqa: SLF001
    # After exiting context, client should be closed
    assert client._client is None  # noqa: SLF001


@pytest.mark.anyio
@patch("httpx.AsyncClient")
async def test_fastapi_client_get_request(mock_client_class: Any) -> None:
    """Test GET request with mocked httpx client."""
    # Setup mock
    mock_response = MagicMock()
    mock_response.json.return_value = {"result": "success"}
    mock_response.raise_for_status = MagicMock()

    mock_client = AsyncMock()
    mock_client.request = AsyncMock(return_value=mock_response)
    mock_client_class.return_value = mock_client

    # Test
    client = FastAPIClient()
    await client.start()
    result = await client.get("/api/test", params={"param": "value"})

    assert result == {"result": "success"}
    mock_client.request.assert_called_once()
    await client.close()


@pytest.mark.anyio
@patch("httpx.AsyncClient")
async def test_fastapi_client_post_request(mock_client_class: Any) -> None:
    """Test POST request with mocked httpx client."""
    # Setup mock
    mock_response = MagicMock()
    mock_response.json.return_value = {"status": "created"}
    mock_response.raise_for_status = MagicMock()

    mock_client = AsyncMock()
    mock_client.request = AsyncMock(return_value=mock_response)
    mock_client_class.return_value = mock_client

    # Test
    client = FastAPIClient()
    await client.start()
    result = await client.post("/api/test", json_data={"key": "value"})

    assert result == {"status": "created"}
    await client.close()


@pytest.mark.anyio
@patch("httpx.AsyncClient")
async def test_fastapi_client_retry_on_failure(mock_client_class: Any) -> None:
    """Test retry logic on request failure."""
    import httpx

    # Setup mock to fail twice then succeed
    mock_response = MagicMock()
    mock_response.json.return_value = {"result": "success"}
    mock_response.raise_for_status = MagicMock()

    mock_client = AsyncMock()
    call_count = 0

    async def mock_request(*_args: Any, **_kwargs: Any) -> MagicMock:
        nonlocal call_count
        call_count += 1
        if call_count < 3:
            msg = "Connection failed"
            raise httpx.RequestError(msg, request=MagicMock())
        return mock_response

    mock_client.request = AsyncMock(side_effect=mock_request)
    mock_client_class.return_value = mock_client

    # Test
    client = FastAPIClient()
    await client.start()
    result = await client.get("/api/test")

    assert result == {"result": "success"}
    assert call_count == 3  # Should have retried twice
    await client.close()


def test_config_defaults() -> None:
    """Test configuration defaults."""
    assert MCPConfig.API_URL == "http://localhost:8787"
    assert MCPConfig.TIMEOUT == 300
    assert MCPConfig.MAX_RETRIES == 3


def test_config_get_api_url() -> None:
    """Test getting API URL from config."""
    url = MCPConfig.get_api_url()
    assert url == MCPConfig.API_URL

    override = "http://example.com:8080"
    url = MCPConfig.get_api_url(override)
    assert url == override


@pytest.mark.anyio
@patch("mcp_standalone.server.FastAPIClient")
async def test_server_list_tools(mock_client_class: Any) -> None:
    """Test listing tools through MCP server."""
    # Create server
    server = create_server()

    # Verify server has the required attributes
    assert server is not None
    assert hasattr(server, "request_handlers")
    assert mock_client_class is not None  # Use the mock parameter

    # Note: This is a simplified test. Full testing would require
    # setting up the MCP protocol communication and properly mocking
    # the MCP server internals.


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
