"""admin_role 表(RBAC 角色 → 可见页面)+ 种子内建角色

新增后台 RBAC:角色持有一组页面 key,登录后左侧只展示这些页。super_admin 内建全权(pages 存空、
effective_pages 特判为全部)、不可编辑删除;operator/finance 播默认页集,可由 super_admin 增删改。
admin_user.role 弱引用本表 name。全新环境顺序应用即得三条内建角色。

Revision ID: admin_role_table
Revises: comparison_product_names
Create Date: 2026-07-04 00:00:00.000000
"""
from collections.abc import Sequence

import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

from alembic import op

revision: str = "admin_role_table"
down_revision: str | Sequence[str] | None = "comparison_product_names"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None

_JSON = sa.JSON().with_variant(postgresql.JSONB(), "postgresql")

# 与 app/admin/permissions.py 的 BUILTIN_ROLES 同口径(迁移内联一份,不耦合 app 常量)。
# 页集对齐 Prototypes/dashboard/permissions.md 的 ROLES。key 承重(require_role),label 为展示名。
_BUILTIN = [
    {"name": "super_admin", "label": "管理员", "pages": [], "is_builtin": True},
    {"name": "operator", "label": "运营", "pages": [
        "dashboard", "coupon-data", "ad-revenue-report", "comparison-records",
        "cps", "device-liveness", "price-reports", "feedbacks",
    ], "is_builtin": False},
    {"name": "finance", "label": "财务", "pages": [
        "dashboard", "ad-revenue-report", "cps", "withdraws",
    ], "is_builtin": False},
    {"name": "tech", "label": "技术", "pages": [
        "dashboard", "device-liveness", "config", "ad-revenue", "event-logs", "audit-logs",
    ], "is_builtin": False},
]


def upgrade() -> None:
    op.create_table(
        "admin_role",
        sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
        sa.Column("name", sa.String(length=32), nullable=False),
        sa.Column("label", sa.String(length=32), nullable=False, server_default=""),
        sa.Column("pages", _JSON, nullable=False),
        sa.Column("is_builtin", sa.Boolean(), nullable=False, server_default=sa.false()),
        sa.Column(
            "created_at", sa.DateTime(timezone=True),
            server_default=sa.func.now(), nullable=False,
        ),
    )
    op.create_index("ix_admin_role_name", "admin_role", ["name"], unique=True)

    tbl = sa.table(
        "admin_role",
        sa.column("name", sa.String),
        sa.column("label", sa.String),
        sa.column("pages", _JSON),
        sa.column("is_builtin", sa.Boolean),
    )
    op.bulk_insert(tbl, _BUILTIN)


def downgrade() -> None:
    op.drop_index("ix_admin_role_name", table_name="admin_role")
    op.drop_table("admin_role")
