"""Assignability — an admin cannot mint another admin.

The kit (not the app route) enforces WHICH levels an actor may hand out: a level's
`assignable` list. The seed admin may assign only `member`, so an admin can grow the
member population but can never replicate its own authority — not onto someone else,
and not onto itself. The owner, being super admin, may assign anything that exists.
"""

from tests.conftest import as_user


def _code(resp):
    body = resp.json()
    d = body.get("detail")
    return d.get("error_code") if isinstance(d, dict) else body.get("error_code")


def test_admin_may_invite_a_member(client, kit):
    kit.member("alice", "admin")
    as_user(client, "alice")
    r = client.post("/api/bw/accounts/invite",
                    json={"username": "newbie", "level": "member",
                          "email": "newbie@example.com"})
    assert r.status_code == 200
    assert r.json()["success"] is True
    assert kit.bwa.member("newbie") is not None


def test_admin_cannot_invite_another_admin(client, kit):
    """admin's assignable is ['member'] — inviting at 'admin' is NOT_ASSIGNABLE."""
    kit.member("alice", "admin")
    as_user(client, "alice")
    r = client.post("/api/bw/accounts/invite",
                    json={"username": "wannabe", "level": "admin",
                          "email": "wannabe@example.com"})
    assert r.status_code == 403
    assert _code(r) == "NOT_ASSIGNABLE"
    assert kit.bwa.member("wannabe") is None


def test_admin_cannot_self_promote_to_admin(client, kit):
    """No self-escalation: an admin changing its OWN level to admin is refused,
    because admin is not in admin's assignable set."""
    kit.member("alice", "admin")
    as_user(client, "alice")
    r = client.post("/api/bw/accounts/alice/level", json={"level": "admin"})
    assert r.status_code == 403
    assert _code(r) == "NOT_ASSIGNABLE"
    assert kit.bwa.member("alice")["level"] == "admin"  # unchanged


def test_owner_may_assign_any_level(client, kit):
    """The owner may hand out 'admin' — the level an admin itself cannot assign."""
    as_user(client, "rian")
    r = client.post("/api/bw/accounts/invite",
                    json={"username": "trusted", "level": "admin",
                          "email": "trusted@example.com"})
    assert r.status_code == 200
    assert kit.bwa.member("trusted")["level"] == "admin"


def test_admin_may_change_a_members_level_within_its_grant(client, kit):
    """Sanity floor: the admin CAN do the assignable operation (member→member),
    so the refusals above are about assignability, not a blanket block."""
    kit.member("alice", "admin")
    kit.member("dave", "member")
    as_user(client, "alice")
    r = client.post("/api/bw/accounts/dave/level", json={"level": "member"})
    assert r.status_code == 200
