"""Tests for error handling and exception mapping."""

import httpx
import pytest

from duffelbag import (
    ApiError,
    AuthenticationError,
    Duffel,
    DuffelError,
    NotFoundError,
    RateLimitError,
    ValidationError,
)


def test_401_raises_authentication_error(client, mock_transport):
    mock_transport.queue_response(
        httpx.Response(401, json={
            "errors": [{
                "title": "Unauthorized",
                "message": "Missing access token",
                "type": "authentication_error",
                "code": "missing_authorization_header",
            }],
        })
    )

    with pytest.raises(AuthenticationError) as exc_info:
        client.airlines.get("arl_1")

    assert exc_info.value.status_code == 401
    assert len(exc_info.value.errors) == 1
    assert exc_info.value.errors[0].code == "missing_authorization_header"


def test_404_raises_not_found(client, mock_transport):
    mock_transport.queue_response(
        httpx.Response(404, json={
            "errors": [{
                "title": "Not Found",
                "message": "Resource not found",
                "type": "invalid_request_error",
                "code": "not_found",
            }],
        })
    )

    with pytest.raises(NotFoundError):
        client.airlines.get("arl_nonexistent")


def test_422_raises_validation_error(client, mock_transport):
    mock_transport.queue_response(
        httpx.Response(422, json={
            "errors": [{
                "title": "Validation Error",
                "message": "slices is required",
                "type": "validation_error",
                "code": "missing_data_param",
                "source": {"field": "slices", "pointer": "/data/slices"},
            }],
        })
    )

    with pytest.raises(ValidationError) as exc_info:
        client.offer_requests.create(slices=[], passengers=[])

    assert exc_info.value.errors[0].source.field == "slices"


def test_429_raises_rate_limit_error(client, mock_transport):
    mock_transport.queue_response(
        httpx.Response(429, json={
            "errors": [{
                "title": "Rate Limit",
                "message": "Too many requests",
                "type": "rate_limit_error",
                "code": "rate_limit_exceeded",
            }],
        }, headers={"ratelimit-reset": "Thu, 01 Jan 2099 00:00:00 GMT"})
    )
    # Queue a second 429 since the auto-retry won't fire (reset is far future)
    mock_transport.queue_response(
        httpx.Response(429, json={
            "errors": [{
                "title": "Rate Limit",
                "message": "Too many requests",
                "type": "rate_limit_error",
                "code": "rate_limit_exceeded",
            }],
        }, headers={"ratelimit-reset": "Thu, 01 Jan 2099 00:00:00 GMT"})
    )

    with pytest.raises(RateLimitError) as exc_info:
        client.airlines.get("arl_1")

    assert exc_info.value.reset_at is not None


def test_500_raises_api_error(client, mock_transport):
    mock_transport.queue_response(
        httpx.Response(500, json={
            "errors": [{
                "title": "Internal Error",
                "message": "Something went wrong",
                "type": "api_error",
                "code": "internal_server_error",
            }],
        })
    )

    with pytest.raises(ApiError) as exc_info:
        client.airlines.get("arl_1")

    assert exc_info.value.status_code == 500
