"""Shared baseline-role seeding for a freshly-created tenant — used by both
scripts/provision_tenant.py (the CLI onboarding flow, which also creates a
first Administrator user) and POST /admin/tenants (the Super Admin UI's
"New tenant" flow, which doesn't collect user details so only seeds roles).
Kept in one place so the two flows can never drift apart on what a new
tenant's baseline roles actually are."""

import uuid

from sqlalchemy.ext.asyncio import AsyncSession

from app.models.identity import Role

# FlowFabric_SRS.docx Section 9.2 Action Matrix, translated from the Y/N
# tables into {module: [allowed actions]}. Administrator gets every action
# on every RBAC module (frontend/src/lib/types.ts::RBAC_MODULES) — FR-RBA-005
# ("fixed and non-reducible") — the other roles only the subset the SRS
# table actually specifies; everything else defaults to no access until an
# administrator configures it via Roles & Privileges.
BASELINE_ROLES: dict[str, dict[str, list[str]]] = {
    "Administrator": {
        m: ["view", "create", "edit", "delete", "publish"]
        for m in (
            "dashboard", "workflows", "forms", "masters", "pages", "tasks", "analytics",
            "reports", "connectors", "users_roles", "menus", "settings", "apps", "workspaces",
            "components", "secrets",
        )
    },
    "Process Owner": {
        "workflows": ["view", "create", "edit", "publish"],
        "forms": ["view", "create", "edit", "delete", "publish"],
        "masters": ["view", "create", "edit"],
        "connectors": ["view", "edit"],
    },
    "Approver": {
        "workflows": ["view", "publish"],
        "forms": ["view"],
    },
    "Form Designer": {
        "workflows": ["view"],
        "forms": ["view", "create", "edit", "delete", "publish"],
        "masters": ["view", "create", "edit", "delete"],
        # The natural owner of the shared component library — already has
        # full CRUD on both Forms and Masters, the two block/field sources
        # a saved component snapshots from. See routers/components.py.
        "components": ["view", "create", "edit", "delete"],
    },
    "Viewer": {
        "workflows": ["view"],
        "forms": ["view"],
    },
    # Not from the SRS table (that one only covers internal Studio roles) —
    # added once the Public Portal grew real self-registration (FR-PUB-*):
    # a freshly-approved vendor account needs a role with SOME access before
    # it can do anything the portal actually exposes, and every module here
    # maps to a route a portal account can already legitimately reach:
    # viewing/submitting Forms and Masters via a Menu link (routers/
    # form_submissions.py, masters.py's /records sub-routes), viewing Pages
    # and Dashboards (routers/pages.py, dashboards.py — neither deny_vendor-
    # gated for GETs), the dataset queries those Pages/Dashboards run on
    # (routers/datasets.py's "analytics" module), and starting a workflow
    # instance from a form/page's on_submit "trigger_workflow" event
    # (routers/workflow_instances.py). Deliberately no "edit"/"delete"/
    # "publish" anywhere, and no "users_roles"/"settings"/"connectors"/
    # "menus" at all — an admin escalates per-tenant if a given portal use
    # case needs more (Roles & Privileges already lets them edit this like
    # any other non-system role).
    "Portal": {
        "forms": ["view", "create"],
        "masters": ["view", "create"],
        "pages": ["view"],
        "dashboard": ["view"],
        "analytics": ["view"],
        "workflows": ["view", "create"],
    },
}


async def seed_baseline_roles(db: AsyncSession, tenant_id: uuid.UUID) -> dict[str, Role]:
    """Creates the 6 baseline roles for `tenant_id` (flushed, not committed —
    the caller's own transaction controls that) and returns them by name.
    Administrator is flagged is_system_role, matching FR-RBA-005. "Portal" is
    explicitly scope="portal" (every other role stays scope="internal", the
    Role column's own default) — without this it would silently default to
    "internal" and never actually be assignable to a Public Portal (vendor)
    user or show up on the Portal Roles & Privileges screen at all."""
    roles: dict[str, Role] = {}
    for role_name, action_matrix in BASELINE_ROLES.items():
        role = Role(
            tenant_id=tenant_id,
            name=role_name,
            is_system_role=(role_name == "Administrator"),
            scope="portal" if role_name == "Portal" else "internal",
            action_matrix=action_matrix,
        )
        db.add(role)
        roles[role_name] = role
    await db.flush()
    return roles
