"""Covers app/routers/platform_admin.py::create_tenant seeding the same
baseline roles scripts/provision_tenant.py's CLI flow already seeds (see
app/crud/tenant_provisioning.py) — previously POST /admin/tenants created a
bare Tenant row with no roles at all."""

import uuid

from sqlalchemy import text

from app.core.auth import create_platform_admin_token, hash_password
from tests.conftest import AsyncSessionLocal
from app.crud.tenant_provisioning import BASELINE_ROLES
from app.models.platform_admin import PlatformAdmin


async def _platform_admin_token() -> tuple[str, uuid.UUID]:
    async with AsyncSessionLocal() as db:
        async with db.begin():
            admin = PlatformAdmin(
                name="Pytest Super Admin",
                email=f"pytest-super-{uuid.uuid4().hex[:8]}@example.com",
                password_hash=hash_password("pytest-password-123"),
                status="active",
            )
            db.add(admin)
            await db.flush()
            admin_id = admin.id
    return create_platform_admin_token(admin_id=admin_id), admin_id


async def test_create_tenant_seeds_baseline_roles(client):
    token, admin_id = await _platform_admin_token()
    headers = {"Authorization": f"Bearer {token}"}
    tenant_id = None
    try:
        resp = await client.post(
            "/admin/tenants", headers=headers, json={"name": f"Pytest Tenant {uuid.uuid4().hex[:6]}"}
        )
        assert resp.status_code == 201
        tenant_id = resp.json()["id"]

        roles_resp = await client.get(f"/admin/tenants/{tenant_id}/roles", headers=headers)
        assert roles_resp.status_code == 200
        roles = roles_resp.json()
        assert {r["name"] for r in roles} == set(BASELINE_ROLES.keys())

        admin_role = next(r for r in roles if r["name"] == "Administrator")
        assert admin_role["is_system_role"] is True
        assert admin_role["action_matrix"] == BASELINE_ROLES["Administrator"]
        # Every action on every module — the literal "all permissions
        # enabled" behavior being tested, not just "matches the dict".
        for actions in admin_role["action_matrix"].values():
            assert set(actions) == {"view", "create", "edit", "delete", "publish"}

        other_role = next(r for r in roles if r["name"] == "Viewer")
        assert other_role["is_system_role"] is False
        assert other_role["scope"] == "internal"

        # "Portal" must be scope="portal" specifically, or it would silently
        # default to "internal" (the Role column's own default) and never
        # actually be assignable to a vendor user — see
        # app/crud/tenant_provisioning.py::seed_baseline_roles.
        portal_role = next(r for r in roles if r["name"] == "Portal")
        assert portal_role["scope"] == "portal"
    finally:
        async with AsyncSessionLocal() as db:
            async with db.begin():
                if tenant_id:
                    await db.execute(text("DELETE FROM roles WHERE tenant_id = :tid"), {"tid": tenant_id})
                    await db.execute(text("DELETE FROM tenants WHERE id = :tid"), {"tid": tenant_id})
                await db.execute(text("DELETE FROM platform_admins WHERE id = :aid"), {"aid": str(admin_id)})


async def test_delete_tenant_removes_a_tenant_whose_users_hold_roles(client):
    """A role someone holds can't be deleted before them (user_roles is
    ON DELETE RESTRICT on role_id) — the delete used to fail with a 409 for
    any tenant with a role assigned, i.e. almost every real one."""
    token, admin_id = await _platform_admin_token()
    headers = {"Authorization": f"Bearer {token}"}
    tenant_id = (await client.post("/admin/tenants", headers=headers, json={"name": f"Pytest Tenant {uuid.uuid4().hex[:6]}"})).json()["id"]
    try:
        user = (
            await client.post(
                f"/admin/tenants/{tenant_id}/users", headers=headers,
                json={"name": "Holder", "email": f"holder-{uuid.uuid4().hex[:6]}@example.com", "password": "a-password-1"},
            )
        ).json()
        role = next(r for r in (await client.get(f"/admin/tenants/{tenant_id}/roles", headers=headers)).json() if r["name"] == "Administrator")
        assert (await client.put(f"/admin/tenants/{tenant_id}/users/{user['id']}/roles/{role['id']}", headers=headers)).status_code == 201
        # Something in its audit log too.
        assert (await client.put(f"/admin/tenants/{tenant_id}/license", headers=headers, json={"max_users": 5})).status_code == 200

        assert (await client.delete(f"/admin/tenants/{tenant_id}", headers=headers)).status_code == 204
        async with AsyncSessionLocal() as db:
            assert (await db.execute(text("SELECT count(*) FROM tenants WHERE id = :t"), {"t": tenant_id})).scalar() == 0
            assert (await db.execute(text("SELECT count(*) FROM users WHERE tenant_id = :t"), {"t": tenant_id})).scalar() == 0
    finally:
        async with AsyncSessionLocal() as db:
            async with db.begin():
                await db.execute(text("DELETE FROM user_roles WHERE role_id IN (SELECT id FROM roles WHERE tenant_id = :t)"), {"t": tenant_id})
                for table in ("audit_log_entries", "users", "roles"):
                    await db.execute(text(f"DELETE FROM {table} WHERE tenant_id = :t"), {"t": tenant_id})
                await db.execute(text("DELETE FROM tenants WHERE id = :t"), {"t": tenant_id})
                await db.execute(text("DELETE FROM platform_admins WHERE id = :id"), {"id": admin_id})
