"""Catálogo mestre de funções Ligbox — padrão Odoo res.groups aplicado à plataforma DevOps.

Uma função Desk (`desk_role`) é a **fonte de verdade**; cada serviço/VM recebe um
mapeamento explícito (grupo nativo, módulo, permissão API). Spec 027.

Analogia Odoo:
  res.users.role          → desk_users.role (VM122)
  res.groups              → PLATFORM_ROLE_CATALOG[*].bindings[*]
  ir.model.access         → permissions.py helpers + route guards
  record rules            → should_mask_sensitive, ticket assignee, …
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any

from app.modules.registry import ROLE_MODULE_DEFAULTS, role_module_defaults


@dataclass(frozen=True)
class ServiceBinding:
    """Como uma função se materializa num serviço concreto."""

    service: str  # desk | vm112 | vm123_foss | vm123_odoo | vm123_openpanel | infra
    binding_type: str  # group | module | permission | deep_link | ssh
    value: str
    access: str = "full"  # full | read | link | api | none


@dataclass(frozen=True)
class PlatformRole:
    id: str
    label: str
    category: str  # ops | commercial | business | platform | system
    description: str
    bindings: tuple[ServiceBinding, ...] = ()
    desk_modules: tuple[str, ...] | None = None  # None = legacy ops (global toggles)


def _desk_perms(*perms: str) -> tuple[ServiceBinding, ...]:
    return tuple(ServiceBinding("desk", "permission", p) for p in perms)


# ── Catálogo mestre (fonte única para docs, provisionamento e introspecção) ──

PLATFORM_ROLE_CATALOG: dict[str, PlatformRole] = {
    "super_admin": PlatformRole(
        id="super_admin",
        label="Super Admin",
        category="ops",
        description="Dono — users, tenants, purge, config global",
        desk_modules=None,
        bindings=(
            ServiceBinding("vm123_odoo", "group", "base.group_system"),
            ServiceBinding("vm123_foss", "group", "admin"),
            ServiceBinding("vm123_openpanel", "role", "Super Admin"),
            ServiceBinding("vm112", "permission", "assist.takeover"),
            ServiceBinding("vm112", "permission", "purge.domain"),
            ServiceBinding("infra", "access", "ssh", "full"),
            *_desk_perms("manage_users", "manage_billing", "run_audit", "manage_vm112_domains"),
        ),
    ),
    "ops_lead": PlatformRole(
        id="ops_lead",
        label="Chefe Ops",
        category="ops",
        description="Gestão operacional, audit, tickets, domínios VM112",
        desk_modules=None,
        bindings=(
            ServiceBinding("vm112", "permission", "assist.takeover"),
            ServiceBinding("vm112", "permission", "purge.domain"),
            ServiceBinding("infra", "access", "ssh", "link"),
            *_desk_perms("run_audit", "manage_vm112_domains", "manage_billing"),
        ),
    ),
    "technician": PlatformRole(
        id="technician",
        label="Suporte",
        category="ops",
        description="Tickets atribuídos, assist wizard, migração",
        desk_modules=None,
        bindings=(
            ServiceBinding("vm112", "permission", "assist.takeover"),
            ServiceBinding("vm123_openpanel", "permission", "autologin"),
            *_desk_perms("patch_assigned_tickets", "read_migration"),
        ),
    ),
    "noc": PlatformRole(
        id="noc",
        label="NOC",
        category="ops",
        description="Monitorização read-only — dados sensíveis mascarados",
        desk_modules=None,
        bindings=(
            ServiceBinding("desk", "permission", "mask_sensitive"),
            ServiceBinding("vm104", "permission", "wazuh.read"),
            *_desk_perms("read_tickets", "read_billing"),
        ),
    ),
    "sales_admin": PlatformRole(
        id="sales_admin",
        label="Sales Admin",
        category="commercial",
        description="Gerente comercial — pipeline, billing validation, FOSS+Odoo manager",
        desk_modules=tuple(ROLE_MODULE_DEFAULTS["sales_admin"]),
        bindings=(
            ServiceBinding("vm123_foss", "group", "ligbox-sales-admin"),
            ServiceBinding("vm123_odoo", "group", "sales_team.group_sale_manager"),
            ServiceBinding("vm123_openpanel", "role", "Admin"),
            *_desk_perms("validate_billing", "create_foss_order", "read_crm_leads"),
        ),
    ),
    "sales_support": PlatformRole(
        id="sales_support",
        label="Sales Support",
        category="commercial",
        description="Analista comercial — pedidos e CRM, sem validar billing",
        desk_modules=tuple(ROLE_MODULE_DEFAULTS["sales_support"]),
        bindings=(
            ServiceBinding("vm123_foss", "group", "ligbox-sales-support"),
            ServiceBinding("vm123_odoo", "group", "sales_team.group_sale_salesman"),
            ServiceBinding("vm123_openpanel", "permission", "autologin"),
            *_desk_perms("create_foss_order", "read_crm_leads"),
        ),
    ),
    "finance": PlatformRole(
        id="finance",
        label="Financeiro",
        category="business",
        description="FOSSBilling, Odoo fiscal, validação billing",
        desk_modules=tuple(ROLE_MODULE_DEFAULTS["finance"]),
        bindings=(
            ServiceBinding("vm123_foss", "group", "ligbox-finance-admin"),
            ServiceBinding("vm123_odoo", "group", "account.group_account_manager"),
            ServiceBinding("vm123_odoo", "group", "account.group_account_invoice"),
            *_desk_perms("validate_billing", "create_foss_order"),
        ),
    ),
    "marketing": PlatformRole(
        id="marketing",
        label="Marketing",
        category="business",
        description="Campanhas, leads, produtos FOSS",
        desk_modules=tuple(ROLE_MODULE_DEFAULTS["marketing"]),
        bindings=(
            ServiceBinding("vm123_foss", "group", "ligbox-marketing"),
            ServiceBinding("vm123_openpanel", "permission", "autologin"),
            *_desk_perms("read_crm_leads", "read_funnel"),
        ),
    ),
    "seo": PlatformRole(
        id="seo",
        label="SEO",
        category="business",
        description="DNS, Search Console, sites OpenPanel",
        desk_modules=tuple(ROLE_MODULE_DEFAULTS["seo"]),
        bindings=(
            ServiceBinding("vm123_openpanel", "permission", "autologin"),
            ServiceBinding("infra", "permission", "cloudflare_dns.read"),
            *_desk_perms("read_funnel", "read_crm_leads"),
        ),
    ),
    "developer": PlatformRole(
        id="developer",
        label="Developer",
        category="platform",
        description="Código wizard/Desk, GitHub, APIs",
        desk_modules=tuple(ROLE_MODULE_DEFAULTS["developer"]),
        bindings=(
            ServiceBinding("vm123_foss", "group", "ligbox-dev-api"),
            ServiceBinding("vm112", "permission", "api.dev_key"),
            ServiceBinding("infra", "access", "github", "full"),
            *_desk_perms("read_events"),
        ),
    ),
    "devops": PlatformRole(
        id="devops",
        label="DevOps",
        category="platform",
        description="Proxmox, Traefik, pfSense, OpenPanel admin",
        desk_modules=tuple(ROLE_MODULE_DEFAULTS["devops"]),
        bindings=(
            ServiceBinding("vm123_openpanel", "role", "Super Admin"),
            ServiceBinding("infra", "access", "ssh", "full"),
            ServiceBinding("infra", "permission", "proxmox", "full"),
            *_desk_perms("manage_vm112_domains"),
        ),
    ),
    "security_analyst": PlatformRole(
        id="security_analyst",
        label="Segurança / SOC",
        category="platform",
        description="Wazuh, incidentes, resposta",
        desk_modules=tuple(ROLE_MODULE_DEFAULTS["security_analyst"]),
        bindings=(
            ServiceBinding("vm104", "permission", "wazuh.manage"),
            *_desk_perms("read_audit_overview"),
        ),
    ),
    "content_editor": PlatformRole(
        id="content_editor",
        label="Conteúdo / CMS",
        category="platform",
        description="Sites clientes OpenPanel",
        desk_modules=tuple(ROLE_MODULE_DEFAULTS["content_editor"]),
        bindings=(
            ServiceBinding("vm123_openpanel", "permission", "autologin"),
        ),
    ),
    "agentic_operator": PlatformRole(
        id="agentic_operator",
        label="Operador Agentes IA",
        category="platform",
        description="Aprova runbooks A7 e acções agentes",
        desk_modules=tuple(ROLE_MODULE_DEFAULTS["agentic_operator"]),
        bindings=(
            ServiceBinding("desk", "permission", "approve_agent_remediation"),
        ),
    ),
    "api_service": PlatformRole(
        id="api_service",
        label="API Service",
        category="system",
        description="M2M webhooks e workers",
        desk_modules=("core",),
        bindings=(
            ServiceBinding("vm123_foss", "group", "ligbox-dev-api"),
            ServiceBinding("vm123_odoo", "group", "base.group_system"),
        ),
    ),
    "agent_system": PlatformRole(
        id="agent_system",
        label="Agent System",
        category="system",
        description="Conta dos agentes A0–A7",
        desk_modules=("core", "events"),
        bindings=(),
    ),
}


def catalog_for_role(role_id: str) -> PlatformRole | None:
    return PLATFORM_ROLE_CATALOG.get(role_id)


def bindings_for_service(role_id: str, service: str) -> list[ServiceBinding]:
    role = catalog_for_role(role_id)
    if not role:
        return []
    return [b for b in role.bindings if b.service == service]


def catalog_export() -> dict[str, Any]:
    """JSON para API / docs — visão unificada estilo Odoo groups."""
    out: dict[str, Any] = {"roles": {}, "services": ["desk", "vm112", "vm123_foss", "vm123_odoo", "vm123_openpanel", "infra", "vm104"]}
    for rid, role in PLATFORM_ROLE_CATALOG.items():
        mods = role.desk_modules
        if mods is None:
            mods_list = list(role_module_defaults(rid) or [])  # type: ignore[arg-type]
            legacy = True
        else:
            mods_list = list(mods)
            legacy = rid in ("super_admin", "ops_lead", "technician", "noc")
        out["roles"][rid] = {
            "id": rid,
            "label": role.label,
            "category": role.category,
            "description": role.description,
            "desk_modules": mods_list,
            "desk_modules_legacy_global": legacy,
            "bindings": [
                {"service": b.service, "type": b.binding_type, "value": b.value, "access": b.access}
                for b in role.bindings
            ],
        }
    return out
