import httpx
import pytest

from easybill_client import AsyncEasybillClient, EasybillClient


class WorkflowTransport(httpx.MockTransport):
    def __init__(self):
        self.rate_limit_hits = 0
        super().__init__(self._handler)

    def _handler(self, request: httpx.Request) -> httpx.Response:
        if request.url.path == "/positions/5":
            return httpx.Response(
                200,
                json={
                    "id": 5,
                    "number": "ART-5",
                    "type": "PRODUCT",
                    "description": "Premium Support",
                    "price": 4900,
                },
            )

        if request.url.path == "/document-payments":
            if request.method == "POST":
                body = request.read().decode()
                assert "INV-1" in body
                return httpx.Response(
                    201,
                    json={
                        "id": 88,
                        "document_id": 10,
                        "amount": 1999,
                        "reference": "INV-1",
                        "type": "CASH",
                    },
                )

            return httpx.Response(
                200,
                json={
                    "page": 1,
                    "pages": 1,
                    "limit": 100,
                    "total": 1,
                    "items": [
                        {
                            "id": 88,
                            "document_id": 10,
                            "amount": 1999,
                            "reference": "INV-1",
                            "type": "CASH",
                        }
                    ],
                },
            )

        if request.url.path == "/customers":
            page = request.url.params.get("page", "1")
            if page == "1":
                return httpx.Response(
                    200,
                    json={
                        "page": 1,
                        "pages": 2,
                        "limit": 1,
                        "total": 2,
                        "items": [{"id": 1, "company_name": "ACME GmbH"}],
                    },
                )
            return httpx.Response(
                200,
                json={
                    "page": 2,
                    "pages": 2,
                    "limit": 1,
                    "total": 2,
                    "items": [{"id": 2, "company_name": "Example AG"}],
                },
            )

        if request.url.path == "/documents":
            if self.rate_limit_hits == 0:
                self.rate_limit_hits += 1
                return httpx.Response(429, headers={"Retry-After": "0"}, json={"error": "slow down"})

            return httpx.Response(
                200,
                json={
                    "page": 1,
                    "pages": 1,
                    "limit": 100,
                    "total": 1,
                    "items": [{"id": 10, "number": "RE-10", "amount": 1999}],
                },
            )

        return httpx.Response(404, json={"error": "not found"})


class AsyncWorkflowTransport(httpx.MockTransport):
    def __init__(self):
        super().__init__(self._handler)

    @staticmethod
    def _handler(request: httpx.Request) -> httpx.Response:
        if request.url.path == "/positions":
            return httpx.Response(
                200,
                json={
                    "page": 1,
                    "pages": 1,
                    "limit": 100,
                    "total": 1,
                    "items": [{"id": 7, "number": "ART-7", "description": "Hosting"}],
                },
            )
        return httpx.Response(404, json={"error": "not found"})


def test_sync_workflow_helpers_cover_positions_payments_pagination_and_retry():
    transport = WorkflowTransport()
    client = EasybillClient(api_key="token", transport=transport, max_retries=1, retry_backoff=0)
    try:
        position = client.get_position(5)
        payments = client.list_document_payments(document_id=10)
        created_payment = client.create_document_payment(document_id=10, amount=1999, reference="INV-1")
        all_customers = list(client.iter_all_customers(limit=1))
        all_payments = list(client.iter_all_document_payments(document_id=10))
        documents = client.list_documents()
    finally:
        client.close()

    assert position.id == 5
    assert position.price == 4900
    assert payments.items[0].reference == "INV-1"
    assert created_payment.id == 88
    assert [customer.id for customer in all_customers] == [1, 2]
    assert [payment.id for payment in all_payments] == [88]
    assert documents.items[0].number == "RE-10"


@pytest.mark.asyncio
async def test_async_workflow_helpers_list_positions_as_models():
    client = AsyncEasybillClient(api_key="token", transport=AsyncWorkflowTransport())
    try:
        positions = await client.list_positions()
        iterated = [item async for item in client.iter_all_positions()]
    finally:
        await client.aclose()

    assert positions.total == 1
    assert positions.items[0].number == "ART-7"
    assert iterated[0].id == 7
