"""Tests for Fibinaci sync/async clients."""
from __future__ import annotations

import json

import httpx
import pytest

from fibinaci.client import Fibinaci, AsyncFibinaci, _handle_error
from fibinaci.errors import APIError, AuthError, RateLimitError


class TestErrorHandling:
    def test_401_raises_auth_error(self):
        resp = httpx.Response(
            401,
            json={"error": {"type": "authentication_error", "message": "Invalid key", "request_id": "req_1"}},
        )
        with pytest.raises(AuthError) as exc_info:
            _handle_error(resp)
        assert exc_info.value.status_code == 401
        assert "Invalid key" in str(exc_info.value)

    def test_429_raises_rate_limit_error(self):
        resp = httpx.Response(
            429,
            json={"error": {"type": "rate_limit_error", "message": "Too fast"}},
            headers={"Retry-After": "30"},
        )
        with pytest.raises(RateLimitError) as exc_info:
            _handle_error(resp)
        assert exc_info.value.retry_after == 30

    def test_500_raises_api_error(self):
        resp = httpx.Response(500, json={"error": {"type": "internal_error", "message": "Boom"}})
        with pytest.raises(APIError) as exc_info:
            _handle_error(resp)
        assert exc_info.value.status_code == 500

    def test_non_json_error_body(self):
        resp = httpx.Response(502, text="Bad Gateway")
        with pytest.raises(APIError) as exc_info:
            _handle_error(resp)
        assert "Bad Gateway" in str(exc_info.value)


class TestFibinaciClient:
    def test_config_from_constructor(self):
        c = Fibinaci(api_key="fib_live_sk_test", base_url="https://custom.api.com")
        assert c._config.api_key == "fib_live_sk_test"
        assert c._config.base_url == "https://custom.api.com"
        c.close()

    def test_config_strips_trailing_slash(self):
        c = Fibinaci(api_key="k", base_url="https://api.example.com/")
        assert c._config.base_url == "https://api.example.com"
        c.close()

    def test_context_manager(self):
        with Fibinaci(api_key="k") as c:
            assert c._config.api_key == "k"

    def test_lazy_resource_init(self):
        c = Fibinaci(api_key="k")
        assert c._spans is None
        _ = c.spans  # triggers init
        assert c._spans is not None
        c.close()


class TestAsyncFibinaciClient:
    @pytest.mark.asyncio
    async def test_async_context_manager(self):
        async with AsyncFibinaci(api_key="k") as c:
            assert c._config.api_key == "k"

    def test_lazy_resource_init(self):
        c = AsyncFibinaci(api_key="k")
        assert c._traces is None
        _ = c.traces
        assert c._traces is not None
