"""Integration tests for HTTP client with real RabbitMQ Management API."""

from __future__ import annotations

import time

import httpx
import pytest
from testcontainers.rabbitmq import RabbitMqContainer

from rabbitmq_mcp_connection.http_client import HTTPClientManager, PoolHealth


@pytest.fixture(scope="module")
def rabbitmq_container():
    """Start RabbitMQ container with Management API for integration tests."""
    container = RabbitMqContainer("rabbitmq:3.12-management")
    container.with_bind_ports(5672, 5672)
    container.with_bind_ports(15672, 15672)
    container.start()
    # Wait for Management API to be ready
    time.sleep(10)
    yield container
    container.stop()


@pytest.fixture
def http_client_manager(rabbitmq_container):
    """Create HTTP client manager connected to RabbitMQ container."""
    # Use localhost since we're binding to host ports
    return HTTPClientManager(
        host="localhost",
        port=15672,
        username="guest",
        password="guest",
        use_tls=False,
        timeout=30,
        pool_size=5,
    )


@pytest.mark.asyncio
@pytest.mark.integration
class TestHTTPClientIntegration:
    """Integration tests with real RabbitMQ Management API (Story 2.3)."""

    async def test_successful_get_overview(self, http_client_manager):
        """Test successful GET /api/overview request (AC #1, #2, #6)."""
        response = await http_client_manager.request("GET", "/overview")

        # AC #1: Connection succeeds with base URL format
        assert response.status_code == 200

        # Verify response structure
        data = response.json()
        assert "rabbitmq_version" in data
        assert "cluster_name" in data

        # Clean up
        await http_client_manager.close()

    async def test_authentication_failure(self, rabbitmq_container):
        """Test authentication failure with invalid credentials (AC #2, #8)."""
        client = HTTPClientManager(
            host="localhost",
            port=15672,
            username="invalid",
            password="invalid",
            timeout=10,
        )

        # AC #2, #8: Should raise HTTPStatusError with 401 Unauthorized
        with pytest.raises(httpx.HTTPStatusError) as exc_info:
            response = await client.request("GET", "/overview")
            response.raise_for_status()

        assert exc_info.value.response.status_code == 401
        await client.close()

    async def test_connection_timeout(self):
        """Test connection timeout with unreachable host (AC #5, #8)."""
        client = HTTPClientManager(
            host="192.0.2.1",  # Non-routable IP for timeout test
            port=15672,
            username="guest",
            password="guest",
            timeout=1,
        )

        # AC #5, #8: Should raise TimeoutException after 1 second
        with pytest.raises(httpx.TimeoutException):
            await client.request("GET", "/overview")

        await client.close()

    async def test_user_agent_header(self, http_client_manager):
        """Test User-Agent header includes version (AC #6)."""
        # We can't directly inspect headers, but we verify the request succeeds
        # and the client is configured with User-Agent
        response = await http_client_manager.request("GET", "/overview")
        assert response.status_code == 200

        # Verify version is set
        assert "3.1.0" in http_client_manager.version

        await http_client_manager.close()

    async def test_correlation_id_propagation(self, http_client_manager):
        """Test correlation ID is added to request headers (AC #6)."""
        # Make a request and verify it succeeds (correlation ID logged)
        response = await http_client_manager.request("GET", "/overview")
        assert response.status_code == 200

        # The correlation ID is generated and logged internally
        # Verify the request completed successfully
        await http_client_manager.close()

    async def test_connection_pool_concurrent_requests(self, http_client_manager):
        """Test connection pool with concurrent requests (AC #7)."""
        import asyncio

        # Make 10 concurrent requests with pool size 5
        tasks = [http_client_manager.request("GET", "/overview") for _ in range(10)]

        responses = await asyncio.gather(*tasks)

        # Verify all requests succeeded
        assert len(responses) == 10
        for response in responses:
            assert response.status_code == 200

        # Check pool health metrics
        pool_status = http_client_manager.get_pool_status()
        assert isinstance(pool_status, PoolHealth)
        assert pool_status.size == 5
        assert pool_status.health_score > 0.9  # High success rate

        await http_client_manager.close()

    async def test_tls_connection_disabled(self, rabbitmq_container):
        """Test HTTP connection without TLS (AC #3)."""
        client = HTTPClientManager(
            host=rabbitmq_container.get_container_host_ip(),
            port=int(rabbitmq_container.get_exposed_port(15672)),
            username="guest",
            password="guest",
            use_tls=False,  # AC #3: TLS disabled
        )

        response = await client.request("GET", "/overview")
        assert response.status_code == 200
        assert client.base_url.startswith("http://")

        await client.close()

    async def test_pool_health_metrics(self, http_client_manager):
        """Test pool health metrics tracking (AC #7)."""
        # Make some requests
        await http_client_manager.request("GET", "/overview")
        await http_client_manager.request("GET", "/overview")

        # Get pool status
        pool_status = http_client_manager.get_pool_status()

        assert isinstance(pool_status, PoolHealth)
        assert pool_status.size == 5
        assert pool_status.active == 0  # No active connections after await
        assert pool_status.idle == 5
        assert pool_status.health_score == 1.0  # All requests succeeded
        assert pool_status.avg_connection_age_seconds > 0

        await http_client_manager.close()

    async def test_fail_fast_no_retries(self, rabbitmq_container):
        """Test fail-fast behavior with no retries (AC #8)."""
        client = HTTPClientManager(
            host="192.0.2.1",  # Non-routable IP
            port=15672,
            username="guest",
            password="guest",
            timeout=1,
        )

        # AC #8: Should fail immediately without retries
        start_time = time.time()
        with pytest.raises(httpx.TimeoutException):
            await client.request("GET", "/overview")
        elapsed = time.time() - start_time

        # Should timeout close to 1 second (no retry delays)
        assert elapsed < 2.0

        await client.close()

    async def test_graceful_close(self, http_client_manager):
        """Test graceful HTTP client close."""
        # Make a request
        response = await http_client_manager.request("GET", "/overview")
        assert response.status_code == 200

        # Close client
        await http_client_manager.close()

        # Verify client is closed (further requests should fail)
        with pytest.raises(Exception):  # httpx.PoolTimeout or similar
            await http_client_manager.request("GET", "/overview")
