"""Shared test fixtures for the Duffel client test suite."""

import json
from typing import Any

import httpx
import pytest

from duffelbag import AsyncDuffel, Duffel


def make_json_response(
    data: Any = None,
    *,
    status_code: int = 200,
    meta: dict | None = None,
    headers: dict[str, str] | None = None,
) -> httpx.Response:
    """Build an httpx.Response with a JSON body."""
    body: dict[str, Any] = {}
    if data is not None:
        body["data"] = data
    if meta is not None:
        body["meta"] = meta

    return httpx.Response(
        status_code=status_code,
        json=body,
        headers=headers,
    )


class MockTransport(httpx.BaseTransport):
    """Records requests and returns canned responses for testing (sync)."""

    def __init__(self):
        self.requests: list[httpx.Request] = []
        self.responses: list[httpx.Response] = []
        self._response_queue: list[httpx.Response] = []

    def queue_response(self, response: httpx.Response) -> None:
        self._response_queue.append(response)

    def handle_request(self, request: httpx.Request) -> httpx.Response:
        self.requests.append(request)
        if self._response_queue:
            return self._response_queue.pop(0)
        # Default: empty 200
        return make_json_response({})

    @property
    def last_request(self) -> httpx.Request:
        return self.requests[-1]

    def last_request_json(self) -> dict:
        return json.loads(self.last_request.content)


class AsyncMockTransport(httpx.AsyncBaseTransport):
    """Records requests and returns canned responses for testing (async)."""

    def __init__(self):
        self.requests: list[httpx.Request] = []
        self._response_queue: list[httpx.Response] = []

    def queue_response(self, response: httpx.Response) -> None:
        self._response_queue.append(response)

    async def handle_async_request(self, request: httpx.Request) -> httpx.Response:
        self.requests.append(request)
        if self._response_queue:
            return self._response_queue.pop(0)
        return make_json_response({})

    @property
    def last_request(self) -> httpx.Request:
        return self.requests[-1]

    def last_request_json(self) -> dict:
        return json.loads(self.last_request.content)


@pytest.fixture
def mock_transport():
    return MockTransport()


@pytest.fixture
def client(mock_transport) -> Duffel:
    http_client = httpx.Client(transport=mock_transport)
    return Duffel(token="duffel_test_123", http_client=http_client)


@pytest.fixture
def async_mock_transport():
    return AsyncMockTransport()


@pytest.fixture
def async_client(async_mock_transport) -> AsyncDuffel:
    http_client = httpx.AsyncClient(transport=async_mock_transport)
    return AsyncDuffel(token="duffel_test_123", http_client=http_client)
