import httpx
import pytest
import respx

from pinpout import (
    AsyncPinpout,
    AuthenticationError,
    ConnectionError,
    RateLimitError,
    ScanResult,
    TimeoutError,
)

BASE_URL = "https://api.pinpout.dev"
API_KEY = "pp_test_abc123"

SAFE_RESPONSE = {
    "is_safe": True,
    "confidence": 0.98,
    "scan_id": "scan_001",
    "normalized_text": None,
}


@pytest.fixture
async def client():
    c = AsyncPinpout(API_KEY)
    yield c
    await c.close()


@respx.mock
@pytest.mark.asyncio
async def test_async_scan_safe(client: AsyncPinpout):
    respx.post(f"{BASE_URL}/v1/scan").mock(
        return_value=httpx.Response(200, json=SAFE_RESPONSE)
    )
    result = await client.scan("What is the capital of France?")
    assert isinstance(result, ScanResult)
    assert result.is_safe is True


@respx.mock
@pytest.mark.asyncio
async def test_async_auth_error(client: AsyncPinpout):
    respx.post(f"{BASE_URL}/v1/scan").mock(
        return_value=httpx.Response(401, json={"detail": "Invalid API key"})
    )
    with pytest.raises(AuthenticationError):
        await client.scan("test")


@respx.mock
@pytest.mark.asyncio
async def test_async_rate_limit(client: AsyncPinpout):
    respx.post(f"{BASE_URL}/v1/scan").mock(
        return_value=httpx.Response(
            429,
            json={"detail": "Rate limited"},
            headers={"Retry-After": "10"},
        )
    )
    with pytest.raises(RateLimitError) as exc_info:
        await client.scan("test")
    assert exc_info.value.retry_after == 10.0


@respx.mock
@pytest.mark.asyncio
async def test_async_connection_error():
    respx.post(f"{BASE_URL}/v1/scan").mock(side_effect=httpx.ConnectError("refused"))
    async with AsyncPinpout(API_KEY) as client:
        with pytest.raises(ConnectionError):
            await client.scan("test")


@respx.mock
@pytest.mark.asyncio
async def test_async_timeout_error():
    respx.post(f"{BASE_URL}/v1/scan").mock(
        side_effect=httpx.ReadTimeout("timed out")
    )
    async with AsyncPinpout(API_KEY) as client:
        with pytest.raises(TimeoutError):
            await client.scan("test")


@pytest.mark.asyncio
async def test_async_context_manager():
    async with AsyncPinpout(API_KEY) as client:
        assert isinstance(client, AsyncPinpout)
