"""
VELOCRIUM Tests
Author: Juste Elysée MALANDILA
LinkedIn: https://linkedin.com/in/juste-elysee-malandila
"""

import pytest
from velocrium import Client, Retry, Cache, RateLimit, Timeout
from velocrium.exceptions import VelocriumError, HTTPError


def test_client_initialization():
    """Test client can be initialized."""
    client = Client()
    assert client is not None
    assert client.base_url is None


def test_client_with_base_url():
    """Test client with base URL."""
    client = Client(base_url="https://api.github.com")
    assert client.base_url == "https://api.github.com"


def test_client_with_retry():
    """Test client with retry configuration."""
    retry = Retry(max_attempts=3, backoff="exponential")
    client = Client(retry=retry)
    assert client.retry is not None
    assert client.retry.max_attempts == 3


def test_client_with_cache():
    """Test client with cache configuration."""
    cache = Cache(ttl=300)
    client = Client(cache=cache)
    assert client.cache is not None
    assert client.cache.ttl == 300


def test_client_with_rate_limit():
    """Test client with rate limiting."""
    rate_limit = RateLimit("100/minute")
    client = Client(rate_limit=rate_limit)
    assert client.rate_limit is not None


def test_client_with_timeout():
    """Test client with timeout configuration."""
    timeout = Timeout(connect=5, read=30)
    client = Client(timeout=timeout)
    assert client.timeout is not None
    assert client.timeout.connect == 5


def test_retry_delay_calculation():
    """Test retry delay calculation."""
    retry = Retry(max_attempts=3, backoff="exponential", jitter=False, base_delay=1.0)
    
    # Test exponential backoff
    assert retry.get_delay(0) == 1.0  # 2^0
    assert retry.get_delay(1) == 2.0  # 2^1
    assert retry.get_delay(2) == 4.0  # 2^2


def test_retry_with_jitter():
    """Test retry with jitter adds randomness."""
    retry = Retry(max_attempts=3, backoff="exponential", jitter=True, base_delay=1.0)
    
    # Delay should be between 0.5 and 1.5 for first attempt
    delay = retry.get_delay(0)
    assert 0.5 <= delay <= 1.5


def test_client_context_manager():
    """Test client works as context manager."""
    with Client() as client:
        assert client is not None


@pytest.mark.asyncio
async def test_client_async_context_manager():
    """Test client works as async context manager."""
    async with Client() as client:
        assert client is not None


def test_timeout_to_httpx():
    """Test timeout conversion to httpx format."""
    timeout = Timeout(connect=5, read=30, write=10)
    httpx_timeout = timeout.to_httpx()
    assert httpx_timeout == (5, 30, 10, 10)


# Integration test (requires internet)
@pytest.mark.integration
def test_real_get_request():
    """Test real GET request to public API."""
    client = Client()
    try:
        response = client.get("https://httpbin.org/get")
        assert response.status_code == 200
        data = response.json()
        assert "url" in data
    finally:
        client.close()


# Async integration test
@pytest.mark.asyncio
@pytest.mark.integration
async def test_real_async_get_request():
    """Test real async GET request."""
    async with Client() as client:
        response = await client.aget("https://httpbin.org/get")
        assert response.status_code == 200
        data = response.json()
        assert "url" in data
