import pytest
import httpx

from a3api import (
    AsyncA3Client,
    AssessAgeRequest,
    AssessAgeResponse,
    OsSignal,
    Verdict,
)
from a3api._errors import (
    A3AuthenticationError,
    A3RateLimitError,
    A3ValidationError,
)
from tests.conftest import MOCK_RESPONSE_JSON


class TestAsyncAssessAge:
    async def test_success(self, async_client: AsyncA3Client, mock_success, httpx_mock):
        req = AssessAgeRequest(os_signal=OsSignal.AGE_18_PLUS, user_country_code="US")
        resp = await async_client.assess_age(req)

        assert isinstance(resp, AssessAgeResponse)
        assert resp.verdict == Verdict.CONSISTENT

    async def test_400_raises_validation_error(self, async_client: AsyncA3Client, httpx_mock):
        httpx_mock.add_response(
            url="https://test.a3api.io/v1/assurance/assess-age",
            method="POST",
            status_code=400,
            json={
                "statusCode": 400,
                "message": ["os_signal must be a valid enum value"],
                "error": "Bad Request",
            },
        )
        req = AssessAgeRequest(os_signal=OsSignal.AGE_18_PLUS, user_country_code="US")
        with pytest.raises(A3ValidationError):
            await async_client.assess_age(req)

    async def test_401_raises_auth_error(self, async_client: AsyncA3Client, httpx_mock):
        httpx_mock.add_response(
            url="https://test.a3api.io/v1/assurance/assess-age",
            method="POST",
            status_code=401,
            json={"statusCode": 401, "message": "Unauthorized", "error": "Unauthorized"},
        )
        req = AssessAgeRequest(os_signal=OsSignal.AGE_18_PLUS, user_country_code="US")
        with pytest.raises(A3AuthenticationError):
            await async_client.assess_age(req)

    async def test_429_raises_rate_limit_error(self, async_client: AsyncA3Client, httpx_mock):
        httpx_mock.add_response(
            url="https://test.a3api.io/v1/assurance/assess-age",
            method="POST",
            status_code=429,
            headers={"retry-after": "5"},
            json={"statusCode": 429, "message": "Too Many Requests", "error": "Too Many Requests"},
        )
        req = AssessAgeRequest(os_signal=OsSignal.AGE_18_PLUS, user_country_code="US")
        with pytest.raises(A3RateLimitError) as exc_info:
            await async_client.assess_age(req)
        assert exc_info.value.retry_after == 5.0

    async def test_assess_age_raw(self, async_client: AsyncA3Client, mock_success, httpx_mock):
        req = AssessAgeRequest(os_signal=OsSignal.AGE_18_PLUS, user_country_code="US")
        raw = await async_client.assess_age_raw(req)
        assert isinstance(raw, dict)
        assert raw["verdict"] == "CONSISTENT"

    async def test_async_context_manager(self, mock_success, httpx_mock):
        async with AsyncA3Client("sk_test", base_url="https://test.a3api.io", max_retries=0) as client:
            req = AssessAgeRequest(os_signal=OsSignal.AGE_18_PLUS, user_country_code="US")
            resp = await client.assess_age(req)
            assert resp.verdict == Verdict.CONSISTENT

    async def test_retries_429_then_succeeds(self, httpx_mock):
        httpx_mock.add_response(
            url="https://test.a3api.io/v1/assurance/assess-age",
            method="POST",
            status_code=429,
            headers={"retry-after": "0"},
            json={"statusCode": 429, "message": "Rate limited", "error": "Too Many Requests"},
        )
        httpx_mock.add_response(
            url="https://test.a3api.io/v1/assurance/assess-age",
            method="POST",
            json=MOCK_RESPONSE_JSON,
        )
        async with AsyncA3Client("sk_test", base_url="https://test.a3api.io", max_retries=2) as client:
            req = AssessAgeRequest(os_signal=OsSignal.AGE_18_PLUS, user_country_code="US")
            resp = await client.assess_age(req)
            assert resp.verdict == Verdict.CONSISTENT
