import pytest
import httpx
from unittest.mock import patch, MagicMock, AsyncMock
from vericorp import AsyncVeriCorp, Company, ValidationResult
from vericorp.errors import InvalidTaxIdError, RateLimitError


COMPANY_JSON = {
    "tax_id": "PT502011378",
    "country": "PT",
    "name": "UNIVERSIDADE DO MINHO",
    "address": {"street": "LG DO PACO", "city": "BRAGA", "postal_code": "4700-320", "country": "PT"},
    "source": "nifpt",
    "data_quality": "full",
    "cached": True,
    "fetched_at": "2026-01-01T00:00:00Z",
}

VALIDATION_JSON = {
    "tax_id": "PT502011378",
    "country": "PT",
    "format_valid": True,
    "vat_valid": True,
    "company_name": "UNIVERSIDADE DO MINHO",
}


def mock_response(status_code: int = 200, json_data: dict | None = None, headers: dict | None = None) -> MagicMock:
    response = MagicMock(spec=httpx.Response)
    response.status_code = status_code
    response.is_success = 200 <= status_code < 300
    response.json.return_value = json_data or {}
    response.headers = headers or {}
    return response


@pytest.mark.asyncio
class TestAsyncVeriCorp:
    async def test_lookup(self):
        client = AsyncVeriCorp("test-key")
        with patch.object(client._client, "request", new_callable=AsyncMock, return_value=mock_response(200, COMPANY_JSON)):
            result = await client.lookup("PT502011378")
            assert isinstance(result, Company)
            assert result.name == "UNIVERSIDADE DO MINHO"

    async def test_validate(self):
        client = AsyncVeriCorp("test-key")
        with patch.object(client._client, "request", new_callable=AsyncMock, return_value=mock_response(200, VALIDATION_JSON)):
            result = await client.validate("PT502011378")
            assert isinstance(result, ValidationResult)
            assert result.vat_valid is True

    async def test_invalid_tax_id(self):
        client = AsyncVeriCorp("test-key")
        with patch.object(client._client, "request", new_callable=AsyncMock, return_value=mock_response(400)):
            with pytest.raises(InvalidTaxIdError):
                await client.lookup("INVALID")

    async def test_rate_limit(self):
        client = AsyncVeriCorp("test-key", max_retries=0)
        with patch.object(client._client, "request", new_callable=AsyncMock, return_value=mock_response(429, headers={"Retry-After": "10"})):
            with pytest.raises(RateLimitError):
                await client.lookup("PT502011378")

    async def test_async_context_manager(self):
        async with AsyncVeriCorp("test-key") as client:
            assert client._client is not None
