"""Covers app/routers/releases.py + app/crud/release.py — a release must
capture only what's actually published/active right now (not drafts), and
the endpoints must be RBAC-gated like every other mutating/viewing route."""

from app.core.auth import create_access_token
from tests.conftest import AsyncSessionLocal
from app.models.identity import Role, User, UserRole


async def test_create_release_captures_published_entities_only(client, auth_headers):
    draft_resp = await client.post(
        "/forms", headers=auth_headers, json={"name": "Draft Form", "field_definitions": []}
    )
    assert draft_resp.status_code == 201

    published_resp = await client.post(
        "/forms", headers=auth_headers, json={"name": "Published Form", "field_definitions": []}
    )
    form_id = published_resp.json()["form_id"]
    publish_resp = await client.post(f"/forms/{form_id}/publish", headers=auth_headers)
    assert publish_resp.status_code == 200

    release_resp = await client.post(
        "/releases", headers=auth_headers, json={"name": "First Release", "description": "throwaway"}
    )
    assert release_resp.status_code == 201
    body = release_resp.json()
    form_names = {f["name"] for f in body["snapshot"]["forms"]}
    assert "Published Form" in form_names
    assert "Draft Form" not in form_names


async def test_list_releases_returns_summary_with_counts(client, auth_headers):
    create_resp = await client.post("/releases", headers=auth_headers, json={"name": "Summary Release"})
    release_id = create_resp.json()["id"]

    list_resp = await client.get("/releases", headers=auth_headers)
    assert list_resp.status_code == 200
    match = next(r for r in list_resp.json() if r["id"] == release_id)
    assert "counts" in match
    assert set(match["counts"]) == {"workflows", "forms", "pages", "dashboards", "menus"}
    assert "snapshot" not in match


async def test_get_release_returns_full_snapshot(client, auth_headers):
    create_resp = await client.post("/releases", headers=auth_headers, json={"name": "Detail Release"})
    release_id = create_resp.json()["id"]

    get_resp = await client.get(f"/releases/{release_id}", headers=auth_headers)
    assert get_resp.status_code == 200
    assert "snapshot" in get_resp.json()
    assert "captured_at" in get_resp.json()["snapshot"]


async def test_release_creation_requires_settings_publish_permission(client, test_tenant):
    async with AsyncSessionLocal() as db:
        async with db.begin():
            role = Role(tenant_id=test_tenant["tenant_id"], name="Viewer Only", action_matrix={"settings": ["view"]})
            db.add(role)
            await db.flush()
            user = User(tenant_id=test_tenant["tenant_id"], name="Viewer", email=f"viewer-{role.id}@example.com", status="active")
            db.add(user)
            await db.flush()
            db.add(UserRole(user_id=user.id, role_id=role.id))
            await db.flush()
            user_id = user.id

    token = create_access_token(tenant_id=test_tenant["tenant_id"], user_id=user_id, vendor_id=None)
    headers = {"Authorization": f"Bearer {token}"}

    list_resp = await client.get("/releases", headers=headers)
    assert list_resp.status_code == 200

    create_resp = await client.post("/releases", headers=headers, json={"name": "Should Be Denied"})
    assert create_resp.status_code == 403
