import pytest

pytestmark = pytest.mark.anyio


async def test_liveness_and_readiness(client, state):
    assert (await client.get("/livez")).json() == {"status": "ok"}
    assert (await client.get("/readyz")).json() == {"status": "ready", "database": "ok"}
    state["health"].draining = True
    assert (await client.get("/readyz")).status_code == 503


async def test_request_ids_are_echoed_or_generated(client):
    echoed = await client.get("/livez", headers={"X-Request-ID": "checkout-7f3a9c21"})
    assert echoed.headers["x-request-id"] == "checkout-7f3a9c21"
    injected = await client.get("/livez", headers={"X-Request-ID": "bad id\nwith newline"})
    assert injected.headers["x-request-id"] != "bad id\nwith newline"


async def test_every_error_is_a_problem_document(client, asha):
    for r in (await client.get("/v1/nope"), await client.get("/v1/orders/999", headers=asha),
              await client.get("/v1/orders", params={"limit": 0}, headers=asha)):
        body = r.json()
        assert r.headers["content-type"] == "application/problem+json"
        assert {"type", "title", "status", "detail", "instance", "requestId"} <= body.keys()
        assert body["requestId"] == r.headers["x-request-id"]


async def test_unexpected_errors_hide_internals(app_and_state):
    import httpx
    app, state = app_and_state

    @app.get("/boom")
    async def boom():
        raise RuntimeError("database password is hunter2")

    async def with_state(scope, receive, send):
        scope["state"] = dict(state)
        await app(scope, receive, send)

    transport = httpx.ASGITransport(app=with_state, raise_app_exceptions=False)
    async with httpx.AsyncClient(transport=transport, base_url="http://api.test") as c:
        r = await c.get("/boom")
    assert r.status_code == 500 and "hunter2" not in r.text


async def test_openapi_contract(client):
    spec = (await client.get("/openapi.json")).json()
    operations = sorted(op["operationId"] for path in spec["paths"].values() for op in path.values())
    assert operations == ["auth-login", "auth-me", "orders-cancel", "orders-create", "orders-edit",
                          "orders-events", "orders-list_", "orders-read", "orders-set_status",
                          "products-list_products"]
    assert "Problem" in spec["components"]["schemas"]


async def test_products_are_public_and_cacheable(client):
    r = await client.get("/v1/products")
    assert r.headers["cache-control"] == "public, max-age=60"
    assert "pumpkin-spice" not in [p["sku"] for p in r.json()]
