"""The two-role capability matrix (spec admin-auth §2.2).

Two roles now, not three. What this file protects is the *shape* of the difference between
them: a Host is denied exactly three capabilities, and every other one they hold is bounded
by scope rather than by the matrix. Confusing those two is how a Host ends up either unable
to run their own event or able to read somebody else's.
"""

import pytest

from app.models.enums import AdminRole
from app.services.policy import Action, actions_for, can

SUPER, HOST = AdminRole.SUPER_ADMIN, AdminRole.HOST

#: The complete denial list. Written out rather than imported from `policy._HOST_DENIED`, so
#: that widening a Host's powers has to be done twice — once in the matrix and once here,
#: deliberately — instead of a one-line edit that no test notices.
HOST_DENIED = {
    Action.CONFIGURE_GATEWAYS,
    Action.MANAGE_ADMINS,
    Action.VIEW_AUDIT_LOG,
}


def test_there_are_exactly_two_roles() -> None:
    """`co_host` and `viewer` are gone; a stale reference should fail loudly, not silently."""
    assert set(AdminRole) == {SUPER, HOST}


@pytest.mark.parametrize("action", list(Action))
def test_super_admin_can_do_everything(action: Action) -> None:
    assert can(SUPER, action)


@pytest.mark.parametrize("action", sorted(HOST_DENIED))
def test_host_is_denied_the_system_wide_capabilities(action: Action) -> None:
    assert not can(HOST, action)


@pytest.mark.parametrize("action", [a for a in Action if a not in HOST_DENIED])
def test_host_can_run_their_own_events(action: Action) -> None:
    assert can(HOST, action)


def test_host_may_delete_guests() -> None:
    """A deliberate widening from the old Co-host, called out because it is a real change.

    The old denial made sense when one guest list was shared by every admin. A Host owns the
    event, so they own the mistake — and cannot reach anyone else's list to make it.
    """
    assert can(HOST, Action.DELETE_GUESTS)


def test_the_matrix_is_a_strict_hierarchy() -> None:
    assert actions_for(HOST) < actions_for(SUPER)


def test_the_denial_list_is_exactly_the_difference() -> None:
    """Guards against a capability being added to `Action` and quietly granted to a Host."""
    assert actions_for(SUPER) - actions_for(HOST) == frozenset(HOST_DENIED)
