"""Default-deny with an explicit allowlist; no id-auth reserved routes;
headers never grant identity (mirrors with's T-AZ-041/042/045)."""

from fastapi.routing import APIRoute

from app.main import create_app


# ------------------------------------------------------------- the allowlist


def test_health_serves_without_session(client):
    resp = client.get("/health")
    assert resp.status_code == 200
    assert resp.json() == {"status": "ok"}


def test_api_version_serves_without_session(client):
    resp = client.get("/api/version")
    assert resp.status_code == 200
    assert "version" in resp.json()


def test_api_me_requires_session(client):
    resp = client.get("/api/me")
    assert resp.status_code == 401
    body = resp.json()
    assert body["error_code"] == "NOT_AUTHENTICATED"
    assert "summary" in body


def test_api_me_serves_with_session(authed_client):
    resp = authed_client.get("/api/me")
    assert resp.status_code == 200
    assert resp.json()["username"] == "rian"


def test_unknown_api_route_is_401_not_404(client):
    # Default-deny runs BEFORE routing: even a nonexistent /api path is 401.
    assert client.get("/api/nonexistent").status_code == 401


def test_api_events_requires_session(client):
    # The SSE stream is NOT allowlisted.
    assert client.get("/api/events").status_code == 401


def test_view_as_routes_require_session(client):
    resp = client.post("/view-as/start", json={"target": "x"}, follow_redirects=False)
    assert resp.status_code == 302  # page-route bounce into the flow
    assert resp.headers["location"].startswith("/auth/login")


def test_unknown_page_route_redirects_into_flow(client):
    resp = client.get("/some/deep/page?week=27", follow_redirects=False)
    assert resp.status_code == 302
    location = resp.headers["location"]
    assert location.startswith("/auth/login?next=")
    assert "%2Fsome%2Fdeep%2Fpage" in location
    assert "week%3D27" in location


def test_root_redirects_when_unauthenticated(client):
    resp = client.get("/", follow_redirects=False)
    assert resp.status_code == 302
    assert resp.headers["location"].startswith("/auth/login")


def test_static_prefixes_are_public(client):
    # No built SPA in the unit env, so these 404 — the point is the gate
    # does NOT intercept them (no 401, no 302-to-login).
    for path in ("/assets/index-abc123.js", "/sounds/serve.mp3"):
        resp = client.get(path, follow_redirects=False)
        assert resp.status_code == 404


# ------------------------------------------------- no id-auth reserved routes


def test_no_idauth_reserved_routes_defined():
    paths = {r.path for r in create_app().routes if isinstance(r, APIRoute)}
    assert paths, "route walk found nothing — walker broken?"
    assert not paths & {"/login", "/logout", "/authorize", "/_grant"}, (
        "id-auth's gate snippet owns /login /logout /authorize /_grant — "
        "the app must never define them (PATTERN-B.md §1b)"
    )
    auth_paths = {p for p in paths if p.startswith("/auth")}
    assert auth_paths == {"/auth/login", "/auth/callback", "/auth/logout"}


# --------------------------------------------------- headers grant NOTHING


def test_identity_headers_never_grant(client):
    for headers in (
        {"X-Auth-User": "rian"},
        {"X_Auth_User": "rian"},
        {"x-auth-user": "rian", "X-Auth-Email": "rian@rian.ca"},
        {"X-Auth-User": "rian", "X-Auth-Grant": "super_admin"},
        {"X-View-As": "rian"},
    ):
        assert client.get("/api/me", headers=headers).status_code == 401
        assert client.get("/api/events", headers=headers).status_code == 401


def test_spoofed_header_does_not_override_session(authed_client):
    resp = authed_client.get("/api/me", headers={"X-Auth-User": "mallory"})
    assert resp.status_code == 200
    assert resp.json()["username"] == "rian"  # session wins; header ignored


def test_x_view_as_header_ignored_outside_dev_stub(authed_client, db_session):
    from tests.conftest import make_player

    make_player(db_session, "zeina")
    resp = authed_client.get("/api/me", headers={"X-View-As": "zeina"})
    assert resp.status_code == 200
    body = resp.json()
    assert body["username"] == "rian"
    assert body["impersonating"] is False  # header is dev-stub-only
