"""/api/view-as flow: enter/exit with audit rows (T-AZ-030/031),
super-admin-only + strict target validation (T-VAS-01/12), no nesting
(T-VAS-11), read scoping under view-as incl. the imported_by clamp
(T-ENT-41, T-VAS-04), and logout clearing the state (T-VAS-13)."""

from sqlalchemy import select
from sqlalchemy.orm import Session

from app.models import AuditLog
from app.services.authz.view_as import VIEW_AS_COOKIE


def audit_actions(engine):
    with Session(engine) as s:
        return [
            (a.action, a.after) for a in s.scalars(select(AuditLog)).all()
        ]


def test_enter_view_as_swaps_context_and_audits(as_rian, rpt_engine):
    resp = as_rian.post("/api/view-as", json={"username": "adi"})
    assert resp.status_code == 200
    assert as_rian.cookies.get(VIEW_AS_COOKIE) == "adi"

    me = as_rian.get("/api/me").json()
    assert me["username"] == "rian"  # the REAL identity stays visible
    assert me["view_as"] == {"active": True, "label": "Adi Pramono"}
    assert me["effective"]["username"] == "adi"
    assert me["effective"]["role"] == "manager"
    assert me["capabilities"]["can_transfer"] is False
    assert me["capabilities"]["can_manage_imports"] is True
    assert me["capabilities"]["can_enter_view_as"] is False  # no nesting
    assert me["view_as_candidates"] == []

    entered = [a for a in audit_actions(rpt_engine) if a[0] == "view_as.enter"]
    assert entered and entered[-1][1] == {"real": "rian", "target": "adi"}


def test_t_ent_41_reads_scope_to_target_and_url_cannot_widen(as_rian, rpt_engine):
    as_rian.post("/api/view-as", json={"username": "adi"})
    body = as_rian.get("/api/entries", params={"status": "all"}).json()
    assert body["total_count"] == 4  # adi's batch only
    for row in body["rows"]:
        assert "billout" not in row  # money shaped to the effective role

    # the imported_by URL param cannot widen the scope back to rian's rows
    from tests.reporting.conftest import user_id

    with Session(rpt_engine) as s:
        rian_id = str(user_id(s, "rian"))
    clamped = as_rian.get(
        "/api/entries", params={"status": "all", "imported_by": rian_id}
    ).json()
    assert clamped["total_count"] == 4

    options = as_rian.get("/api/entries/options", params={"status": "all"}).json()
    assert options["importers"] == []  # dropdown hidden under view-as
    assert len(options["batches"]) == 1  # narrowed batch metadata (B48)


def test_exit_view_as_restores_and_audits(as_rian, rpt_engine):
    as_rian.post("/api/view-as", json={"username": "adi"})
    resp = as_rian.delete("/api/view-as")
    assert resp.status_code == 200
    assert not as_rian.cookies.get(VIEW_AS_COOKIE)
    me = as_rian.get("/api/me").json()
    assert me["view_as"]["active"] is False
    assert me["capabilities"]["can_transfer"] is True
    exits = [a for a in audit_actions(rpt_engine) if a[0] == "view_as.exit"]
    assert exits and exits[-1][1] == {"real": "rian", "target": "adi"}


def test_t_vas_01_non_super_admin_cannot_enter(as_adi):
    resp = as_adi.post("/api/view-as", json={"username": "rian"})
    assert resp.status_code == 403
    assert resp.json()["error_code"] == "VIEW_AS_FORBIDDEN"
    assert not as_adi.cookies.get(VIEW_AS_COOKIE)
    # a hand-forged cookie is ignored at resolve time
    as_adi.cookies.set(VIEW_AS_COOKIE, "rian")
    me = as_adi.get("/api/me").json()
    assert me["view_as"]["active"] is False
    assert me["capabilities"]["can_transfer"] is False


def test_t_vas_12_bogus_target_rejected(as_rian):
    resp = as_rian.post("/api/view-as", json={"username": "nobody"})
    assert resp.status_code == 404
    assert resp.json()["error_code"] == "VIEW_AS_TARGET_NOT_FOUND"
    assert not as_rian.cookies.get(VIEW_AS_COOKIE)


def test_t_vas_11_no_nesting(as_rian):
    as_rian.post("/api/view-as", json={"username": "adi"})
    resp = as_rian.post("/api/view-as", json={"username": "adi"})
    assert resp.status_code == 409
    assert resp.json()["error_code"] == "VIEW_AS_NESTED"


def test_self_target_rejected(as_rian):
    resp = as_rian.post("/api/view-as", json={"username": "rian"})
    assert resp.status_code == 400
    assert resp.json()["error_code"] == "VIEW_AS_BAD_TARGET"


def test_t_vas_13_logout_clears_view_as_state(as_rian):
    as_rian.post("/api/view-as", json={"username": "adi"})
    assert as_rian.cookies.get(VIEW_AS_COOKIE) == "adi"
    resp = as_rian.get("/auth/logout", follow_redirects=False)
    assert resp.status_code == 302
    assert not as_rian.cookies.get(VIEW_AS_COOKIE)
