"""API key lifecycle and scope-gated authentication."""

from __future__ import annotations


def _create_key(client, helpers, owner_token, *, name="ci", scopes=None, role=None):
    body = {"name": name}
    if scopes is not None:
        body["scopes"] = scopes
    if role is not None:
        body["role"] = role
    resp = client.post("/api-keys", json=body, headers=helpers.headers(owner_token))
    assert resp.status_code == 201, resp.text
    return resp.json()


def test_create_key_returns_plaintext_once(client, helpers):
    ctx = helpers.bootstrap_owner(client)
    created = _create_key(client, helpers, ctx["access_token"], scopes=["read"])
    assert created["plaintext"].startswith("lg_")
    assert created["api_key"]["scopes"] == ["read"]
    # Listing never exposes the plaintext.
    listed = client.get("/api-keys", headers=helpers.headers(ctx["access_token"]))
    assert listed.status_code == 200
    assert all("plaintext" not in k for k in listed.json())


def test_api_key_authenticates_with_scope(client, helpers):
    ctx = helpers.bootstrap_owner(client)
    created = _create_key(client, helpers, ctx["access_token"], scopes=["read"])
    resp = client.get("/audit", headers={"X-API-Key": created["plaintext"]})
    assert resp.status_code == 200


def test_api_key_without_scope_is_forbidden(client, helpers):
    ctx = helpers.bootstrap_owner(client)
    created = _create_key(client, helpers, ctx["access_token"], scopes=[])
    resp = client.get("/audit", headers={"X-API-Key": created["plaintext"]})
    assert resp.status_code == 403


def test_revoked_key_is_rejected(client, helpers):
    ctx = helpers.bootstrap_owner(client)
    created = _create_key(client, helpers, ctx["access_token"], scopes=["read"])
    key_id = created["api_key"]["id"]
    delete = client.delete(f"/api-keys/{key_id}", headers=helpers.headers(ctx["access_token"]))
    assert delete.status_code == 204
    resp = client.get("/audit", headers={"X-API-Key": created["plaintext"]})
    assert resp.status_code == 401


def test_invalid_api_key_rejected(client, helpers):
    helpers.bootstrap_owner(client)
    resp = client.get("/audit", headers={"X-API-Key": "lg_not-a-real-key"})
    assert resp.status_code == 401


def test_builder_cannot_manage_api_keys(client, helpers):
    ctx = helpers.bootstrap_owner(client)
    builder = helpers.add_member(
        client, ctx["access_token"], email="builder@example.com", role="builder"
    )
    resp = client.post(
        "/api-keys",
        json={"name": "x", "scopes": ["read"]},
        headers=helpers.headers(builder["access_token"]),
    )
    assert resp.status_code == 403


def test_key_scoped_by_role_can_manage_members(client, helpers):
    ctx = helpers.bootstrap_owner(client)
    created = _create_key(client, helpers, ctx["access_token"], role="admin")
    resp = client.post(
        "/members/invite",
        json={"email": "viakey@example.com", "role": "viewer"},
        headers={"X-API-Key": created["plaintext"]},
    )
    assert resp.status_code == 201
