"""Removing a person from the People panel revokes access, not just the member row.

The kit's own `remove_member` only flips `account_members.active`, which neither login nor
the session loader reads, while the panel's Remove button tells the owner it revokes access.
So the audit sink maps `remove_member` onto the same path as `accounts disable`: every
session is revoked (the old cookie is no session), a fresh login is refused like any other (the audit
row says `disabled`), and re-adding answers `DISABLED` until `accounts enable`, which never
re-adds the member row. In-process on SQLite.
"""

import pytest
from sqlalchemy import select

from app.models import Account, AccountLevel, AccountMember, AuditLog
from app.services import accounts, directory
from app.vendor import bw_accounts as bwa
from tests import _accounts as T
from tests.kit import _env


@pytest.fixture
def world(monkeypatch):
    T.fresh(monkeypatch)
    T.person("rian")
    with _env.TestSessionLocal() as db:
        db.add(AccountLevel(name="admin", permissions=list(accounts.SEED_LEVELS["admin"]["permissions"]), assignable=[]))
        db.commit()
    T.person("adam", level="admin")
    yield


def test_remove_from_the_panel_disables_and_signs_out(world):
    adam = T.client()
    T.login(adam, "adam")
    assert adam.get("/api/discussion").status_code == 200
    owner = T.client()
    T.as_user(owner, "rian")
    assert owner.delete("/api/bw/accounts/adam").status_code == 200

    # Every session of the account is revoked, so the old cookie is no session at all
    # (a session that somehow survived on a disabled account answers ACCOUNT_DISABLED:
    # tests/test_access.py).
    r = adam.get("/api/discussion")
    assert r.status_code == 401 and r.json()["detail"]["error_code"] == "NOT_SIGNED_IN"
    r = T.login(T.client(), "adam")
    assert r.status_code == 401 and r.json()["detail"]["error_code"] == "LOGIN_REFUSED"
    with _env.TestSessionLocal() as db:
        account = db.scalar(select(Account).where(Account.username == "adam"))
        member = db.get(AccountMember, "adam")
        actions = [a for (a,) in db.execute(select(AuditLog.action).order_by(AuditLog.id)).all()]
    assert account.status == "disabled" and account.disabled_at is not None
    assert member is not None and member.active is False  # the kit's soft delete, untouched
    assert "kit.remove_member" in actions and "account.disable" in actions
    assert actions[-1] == "login.refused"

    # Re-adding is refused until `accounts enable`; enable never re-adds the member row.
    with pytest.raises(bwa.AccountsError) as exc:
        bwa.add_member("rian", "adam", "admin")
    assert exc.value.code == "DISABLED"
    r = owner.post("/api/bw/accounts/invite", json={"username": "adam", "level": "admin"})
    assert r.status_code == 400 and r.json()["detail"]["error_code"] == "DISABLED"
    assert directory.enable_account("adam")
    with _env.TestSessionLocal() as db:
        assert db.scalar(select(Account.status).where(Account.username == "adam")) == "active"
        assert db.get(AccountMember, "adam").active is False
    assert T.login(T.client(), "adam").status_code == 200  # a way in again, no membership yet
    assert accounts.can("adam", accounts.PERM_CLIENT_VIEW) is False
    assert owner.post("/api/bw/accounts/invite", json={"username": "adam", "level": "admin"}).status_code == 200
    assert accounts.can("adam", accounts.PERM_CLIENT_VIEW) is True
