"""RBAC helpers for Ligbox Ops Desk — Spec 003 + 027."""

from __future__ import annotations

# Ops (Spec 003)
OPS_ROLES = frozenset({"super_admin", "ops_lead", "technician", "noc"})

# Comercial (Spec 027)
SALES_ROLES = frozenset({"sales_admin", "sales_support"})

# Negócio / plataforma (Spec 027)
BUSINESS_ROLES = frozenset(
    {
        "finance",
        "marketing",
        "seo",
        "developer",
        "devops",
        "security_analyst",
        "content_editor",
        "agentic_operator",
        "partner",
    }
)

# Sistema (não humanos)
SYSTEM_ROLES = frozenset({"api_service", "agent_system"})

ALL_ROLES = OPS_ROLES | SALES_ROLES | BUSINESS_ROLES | SYSTEM_ROLES

# Funções humanas (login Desk)
HUMAN_ROLES = OPS_ROLES | SALES_ROLES | BUSINESS_ROLES

# Atribuíveis no cadastro Spec 004 (exceto super_admin)
ASSIGNABLE_ROLES = HUMAN_ROLES - {"super_admin"}

# Compatibilidade com código existente
ROLES = HUMAN_ROLES

ROLE_LABELS: dict[str, str] = {
    "super_admin": "Super Admin",
    "ops_lead": "Chefe Ops",
    "technician": "Suporte",
    "noc": "NOC",
    "sales_admin": "Sales Admin",
    "sales_support": "Sales Support",
    "finance": "Financeiro",
    "marketing": "Marketing",
    "seo": "SEO",
    "developer": "Developer",
    "devops": "DevOps",
    "security_analyst": "Segurança / SOC",
    "content_editor": "Conteúdo / CMS",
    "agentic_operator": "Operador Agentes IA",
    "partner": "Partner",
    "api_service": "API Service",
    "agent_system": "Agent System",
}


def is_valid_role(role: str) -> bool:
    return role in ALL_ROLES


def is_assignable_role(role: str) -> bool:
    return role in ASSIGNABLE_ROLES


def can_read_tickets(role: str) -> bool:
    return role in HUMAN_ROLES


def can_patch_ticket(role: str, ticket: dict, username: str) -> bool:
    if role in ("super_admin", "ops_lead"):
        return True
    if role == "technician":
        assignee = ticket.get("assigned_to")
        return assignee is None or assignee == username
    return False


def can_assign_ticket(role: str, assignee: str | None, username: str) -> bool:
    if role in ("super_admin", "ops_lead"):
        return True
    if role == "technician":
        return assignee in (None, username)
    return False


def can_run_audit(role: str) -> bool:
    return role in ("super_admin", "ops_lead")


def can_read_audit_overview(role: str) -> bool:
    return role in (
        "super_admin",
        "ops_lead",
        "noc",
        "developer",
        "devops",
        "security_analyst",
        "agentic_operator",
    )


def can_read_audit_scorecard(role: str) -> bool:
    return role in (
        "super_admin",
        "ops_lead",
        "noc",
        "developer",
        "security_analyst",
        "agentic_operator",
    )


def can_read_cloudflare_dns(role: str) -> bool:
    return role in (
        "super_admin",
        "ops_lead",
        "technician",
        "noc",
        "seo",
        "devops",
        "developer",
    )


def can_read_dns_viewer(role: str) -> bool:
    """Spec 037-DNS-VIEWER — same read surface as Cloudflare DNS for V1."""
    return can_read_cloudflare_dns(role)


def can_open_cloudflare_dns_link(role: str) -> bool:
    return role in ("super_admin", "ops_lead", "devops", "seo")


def can_open_openpanel_link(role: str) -> bool:
    """Compat — prefer can_open_openpanel_admin_link."""
    return can_open_openpanel_admin_link(role)


def can_open_openpanel_admin_link(role: str) -> bool:
    """Staff suporte/admin — OpenAdmin, nunca painel cliente."""
    return role in (
        "super_admin",
        "ops_lead",
        "devops",
        "sales_admin",
        "sales_support",
        "seo",
        "technician",
        "noc",
    )


def can_open_openpanel_client_link(role: str) -> bool:
    """Gerente dono do domínio — painel cliente (futuro domain-admin JWT)."""
    return role in ("domain_manager",)


def can_read_funnel(role: str) -> bool:
    return role in (
        "super_admin",
        "ops_lead",
        "technician",
        "noc",
        "sales_admin",
        "sales_support",
        "finance",
        "marketing",
        "seo",
        "developer",
        "devops",
        "agentic_operator",
    )


def can_read_session_timeline(role: str) -> bool:
    return role in (
        "super_admin",
        "ops_lead",
        "technician",
        "sales_admin",
        "sales_support",
        "finance",
        "marketing",
        "seo",
        "developer",
        "devops",
        "agentic_operator",
    )


def can_list_webhook_events(role: str, source: str | None = None) -> bool:
    if role == "noc":
        return source in (None, "wazuh", "vm112-security")
    if role == "security_analyst":
        return source in (None, "wazuh", "vm112-security", "vm112")
    if role == "finance":
        return source in (None, "billing", "vm112")
    if role == "developer":
        return source in (None, "vm112", "wazuh")
    return role in HUMAN_ROLES


def can_read_crm_leads(role: str) -> bool:
    return role in (
        "super_admin",
        "ops_lead",
        "technician",
        "sales_admin",
        "sales_support",
        "marketing",
        "seo",
    )


def can_read_assist(role: str) -> bool:
    return role in ("super_admin", "ops_lead", "technician", "sales_admin", "sales_support")


def can_assist_takeover(role: str) -> bool:
    return role in ("super_admin", "ops_lead", "technician")


def can_assist_handoff(role: str, username: str) -> bool:
    return role in ("super_admin", "ops_lead", "technician")


def can_manage_users(role: str) -> bool:
    return role == "super_admin"


def can_approve_registration(role: str) -> bool:
    """Aprovar/rejeitar pedidos de cadastro — Spec 039 (SU + CO)."""
    return role in ("super_admin", "ops_lead")


def can_manage_vm112_domains(role: str) -> bool:
    """Admin Desk — domínios orquestrados VM112 (Spec 017)."""
    return role in ("super_admin", "ops_lead", "devops")


def should_mask_sensitive(role: str) -> bool:
    return role in ("noc", "sales_support")


def can_read_migration(role: str) -> bool:
    return role in ("super_admin", "ops_lead", "technician", "noc", "devops")


def can_manage_migration(role: str) -> bool:
    return role in ("super_admin", "ops_lead", "technician")


def can_read_billing(role: str) -> bool:
    return role in (
        "super_admin",
        "ops_lead",
        "noc",
        "finance",
        "sales_admin",
        "sales_support",
    )


def can_validate_billing(role: str) -> bool:
    """Transicionar billing_state — Spec 023 / FR-027-005 / FR-027-009."""
    return role in ("super_admin", "ops_lead", "finance", "sales_admin")


def can_manage_billing(role: str) -> bool:
    return can_validate_billing(role)


def can_create_foss_order(role: str) -> bool:
    return role in (
        "super_admin",
        "ops_lead",
        "finance",
        "sales_admin",
        "sales_support",
    )


def can_access_foss_admin(role: str) -> bool:
    return role in ("super_admin", "finance", "sales_admin")


def can_access_openadmin(role: str) -> bool:
    return role in ("super_admin", "devops", "sales_admin")


def can_openpanel_autologin(role: str) -> bool:
    return role in (
        "super_admin",
        "sales_admin",
        "sales_support",
        "marketing",
        "seo",
        "content_editor",
        "technician",
    )


def can_openpanel_provision(role: str) -> bool:
    return role in ("super_admin", "devops", "sales_admin", "sales_support")


def can_openpanel_delete(role: str) -> bool:
    """Deletar instância OpenPanel — Spec 039: apenas SU + CO."""
    return role in ("super_admin", "ops_lead")


def roles_meta() -> dict:
    """Metadados para UI — labels e funções atribuíveis no cadastro."""
    return {
        "labels": ROLE_LABELS,
        "assignable": sorted(ASSIGNABLE_ROLES),
        "human": sorted(HUMAN_ROLES),
    }
