"""Integration tests for transport layer using respx."""

from __future__ import annotations

import pytest
import respx
from httpx import Response

from curadise_agent.transport.client import ClientConfig, TransportClient


@pytest.fixture
def client_config() -> ClientConfig:
    return ClientConfig(
        base_url="https://test.curadise.local",
        timeout=10.0,
        verify_ssl=False,
    )


class TestTransportClient:
    """Integration tests for TransportClient."""

    @respx.mock
    async def test_health_check_success(self, client_config: ClientConfig) -> None:
        """Test successful health check."""
        respx.get("https://test.curadise.local/health").mock(
            return_value=Response(200, json={"status": "healthy"})
        )

        client = TransportClient(config=client_config)
        await client.start()

        try:
            result = await client.health_check()
            assert result is True
        finally:
            await client.stop()

    @respx.mock
    async def test_health_check_failure(self, client_config: ClientConfig) -> None:
        """Test failed health check."""
        respx.get("https://test.curadise.local/health").mock(
            return_value=Response(500, json={"status": "error"})
        )

        client = TransportClient(config=client_config)
        await client.start()

        try:
            result = await client.health_check()
            assert result is False
        finally:
            await client.stop()

    @respx.mock
    async def test_register_success(self, client_config: ClientConfig) -> None:
        """Test successful registration."""
        respx.post("https://test.curadise.local/api/v1/agents/register").mock(
            return_value=Response(
                200,
                json={
                    "agent_id": "agent-abc-123",
                    "access_token": "jwt-token-here",
                    "refresh_token": "refresh-token",
                    "expires_in": 3600,
                },
            )
        )

        client = TransportClient(config=client_config)
        await client.start()

        try:
            result = await client.register(
                enrollment_token="enroll-token",
                system_info={"hostname": "test-host"},
                tags={"env": "test"},
            )

            assert result["agent_id"] == "agent-abc-123"
            assert "access_token" in result
        finally:
            await client.stop()

    @respx.mock
    async def test_send_heartbeat(self, client_config: ClientConfig) -> None:
        """Test sending heartbeat."""
        respx.post("https://test.curadise.local/api/v1/heartbeat").mock(
            return_value=Response(
                200,
                json={
                    "acknowledged": True,
                    "pending_commands": 0,
                },
            )
        )

        client = TransportClient(config=client_config)
        client.set_auth_token("test-token")
        await client.start()

        try:
            result = await client.send_heartbeat({"agent_id": "agent-123", "state": "running"})

            assert result["acknowledged"] is True
        finally:
            await client.stop()

    @respx.mock
    async def test_fetch_commands(self, client_config: ClientConfig) -> None:
        """Test fetching pending commands."""
        respx.get("https://test.curadise.local/api/v1/commands/pending").mock(
            return_value=Response(
                200,
                json={
                    "commands": [
                        {
                            "id": "cmd-001",
                            "command": "echo",
                            "args": ["hello"],
                        }
                    ]
                },
            )
        )

        client = TransportClient(config=client_config)
        client.set_auth_token("test-token")
        await client.start()

        try:
            commands = await client.fetch_commands()

            assert len(commands) == 1
            assert commands[0]["id"] == "cmd-001"
        finally:
            await client.stop()

    @respx.mock
    async def test_circuit_breaker_opens(self, client_config: ClientConfig) -> None:
        """Test that circuit breaker opens after failures."""
        from curadise_agent.utils.retry import CircuitBreakerConfig

        # Configure for quick testing
        client = TransportClient(
            config=client_config,
            circuit_breaker_config=CircuitBreakerConfig(
                failure_threshold=2,
                recovery_timeout=1.0,
            ),
        )

        # Mock repeated failures
        respx.get("https://test.curadise.local/health").mock(return_value=Response(500))

        await client.start()

        try:
            # First few failures should trigger circuit breaker
            for _ in range(3):
                await client.health_check()

            # Circuit should now be open
            assert client.circuit_state in ("open", "half_open")
        finally:
            await client.stop()
