"""E2E tests for OAGW error handling (gateway vs upstream error source)."""
import httpx
import pytest

from .helpers import create_route, create_upstream, delete_upstream, unique_alias


@pytest.mark.asyncio
async def test_nonexistent_alias_returns_404_gateway(
    oagw_base_url, oagw_headers, mock_upstream,
):
    """Proxy to unknown alias returns 404 with X-OAGW-Error-Source: gateway."""
    _ = mock_upstream
    async with httpx.AsyncClient(timeout=10.0) as client:
        resp = await client.get(
            f"{oagw_base_url}/oagw/v1/proxy/nonexistent-alias-xyz-{unique_alias()}/v1/test",
            headers=oagw_headers,
        )
        assert resp.status_code == 404
        assert resp.headers.get("x-oagw-error-source") == "gateway"

        ct = resp.headers.get("content-type", "")
        assert "application/problem+json" in ct or "application/json" in ct

        body = resp.json()
        assert "type" in body
        assert "status" in body
        assert body["status"] == 404


@pytest.mark.asyncio
async def test_disabled_upstream_returns_503_gateway(
    oagw_base_url, oagw_headers, mock_upstream_url, mock_upstream,
):
    """Proxy to disabled upstream returns 503 with gateway error source."""
    _ = mock_upstream
    alias = unique_alias("err-disabled")
    async with httpx.AsyncClient(timeout=10.0) as client:
        upstream = await create_upstream(
            client, oagw_base_url, oagw_headers, mock_upstream_url,
            alias=alias, enabled=False,
        )
        uid = upstream["id"]

        resp = await client.get(
            f"{oagw_base_url}/oagw/v1/proxy/{alias}/v1/test",
            headers=oagw_headers,
        )
        assert resp.status_code == 503
        assert resp.headers.get("x-oagw-error-source") == "gateway"

        await delete_upstream(client, oagw_base_url, oagw_headers, uid)


@pytest.mark.asyncio
async def test_upstream_500_passthrough(
    oagw_base_url, oagw_headers, mock_upstream_url, mock_upstream,
):
    """Upstream 500 is passed through with X-OAGW-Error-Source: upstream."""
    _ = mock_upstream
    alias = unique_alias("err-500")
    async with httpx.AsyncClient(timeout=10.0) as client:
        upstream = await create_upstream(
            client, oagw_base_url, oagw_headers, mock_upstream_url, alias=alias,
        )
        uid = upstream["id"]
        await create_route(
            client, oagw_base_url, oagw_headers, uid, ["GET"], "/error",
        )

        resp = await client.get(
            f"{oagw_base_url}/oagw/v1/proxy/{alias}/error/500",
            headers=oagw_headers,
        )
        assert resp.status_code == 500
        assert resp.headers.get("x-oagw-error-source") == "upstream"

        # Body should be the upstream's original JSON, not Problem Details.
        body = resp.json()
        assert "error" in body, "Expected upstream's original error JSON"

        await delete_upstream(client, oagw_base_url, oagw_headers, uid)


@pytest.mark.asyncio
async def test_upstream_timeout_returns_504_gateway(
    oagw_base_url, oagw_headers, mock_upstream_url, mock_upstream,
):
    """Upstream timeout returns 504 with gateway error source.

    Requires OAGW proxy_timeout_secs configured to a small value (e.g., 2s).
    The mock upstream sleeps for 30s, so the gateway fires 504 well before that.
    """
    _ = mock_upstream
    alias = unique_alias("err-timeout")
    async with httpx.AsyncClient(timeout=10.0) as client:
        upstream = await create_upstream(
            client, oagw_base_url, oagw_headers, mock_upstream_url, alias=alias,
        )
        uid = upstream["id"]
        await create_route(
            client, oagw_base_url, oagw_headers, uid, ["GET"], "/error",
        )

        try:
            resp = await client.get(
                f"{oagw_base_url}/oagw/v1/proxy/{alias}/error/timeout",
                headers=oagw_headers,
            )
        except httpx.ReadTimeout:
            await delete_upstream(client, oagw_base_url, oagw_headers, uid)
            pytest.skip("OAGW did not return within 30s — timeout not enforced at gateway level")
            return

        try:
            if resp.status_code == 504:
                # Verify error source header if present; some builds may not set it.
                error_source = resp.headers.get("x-oagw-error-source")
                if error_source is not None:
                    assert error_source == "gateway"
            elif resp.status_code == 200:
                pytest.skip("OAGW returned 200 — timeout guard may not be configured")
            else:
                # Accept any response but log it.
                pass
        finally:
            await delete_upstream(client, oagw_base_url, oagw_headers, uid)
