import type { CompanyPermission, CompanyRole } from "./company-context";

/**
 * Catálogo de permissões — espelho de `permission_catalog` no banco.
 *
 * As mesmas decisões viviam em dois lugares: o CASE de `has_company_permission`
 * e o `getDefaultAllow` daqui. Estavam alinhadas, mas por vigilância, não por
 * construção — e cada módulo novo exigia lembrar dos dois.
 *
 * Agora existe uma origem só, e este arquivo é a cópia dela para o lado do
 * navegador, que precisa decidir sem ida ao banco (esconder botão, montar
 * menu). A tabela continua sendo a autoridade: quem protege o dado é o banco.
 *
 * Ao mexer aqui, mexa na migração junto. O teste ao lado compara os dois e
 * falha se divergirem — é o que substitui a vigilância por verificação.
 */

/**
 * A escada de acesso de um módulo inteiro.
 *
 * `nenhum` existe para fechar o módulo de uma vez, incluindo as ações que ainda
 * não foram criadas. Sem ele, fechar exigia negar ação por ação, e toda ação
 * nova nascia liberada porque ninguém voltava ali para negá-la também.
 */
export type NivelModulo = "nenhum" | "ver" | "operar" | "total";

export type AcaoCatalogo = {
  chave: CompanyPermission;
  modulo: string;
  acao: string;
  rotulo: string;
  descricao?: string;
  /* Nivel do modulo que ja concede esta acao quando o admin escolhe so o
     basico. Nulo = so por marcacao explicita no avancado. */
  nivelMinimo: NivelModulo | null;
  /* Papeis que recebem por padrao, sem ninguem configurar. */
  papeisPadrao: CompanyRole[];
  /* Chave consultada enquanto esta nao foi configurada. E o que deixa um modulo
     ganhar chave propria sem mudar o acesso de ninguem: `suppliers.read` nasce
     repassando a pergunta para `financial.read`, que era quem respondia antes,
     e so para de repassar quando o admin marcar Fornecedores no modal. */
  herdaDe?: CompanyPermission;
  /* A tela em que esta acao vive, quando o modulo tem mais de uma.
     Modulo grande com uma porta so era o limite do desenho anterior: abrir o
     Financeiro abria as onze telas dele, e fechar fechava todas. Com a pagina
     no meio, o admin decide tela por tela — e a acao continua sendo a unidade
     que o motor resolve, sem mudanca nenhuma na conta de quem pode o que. */
  pagina?: string;
  ordem: number;
};

/* Uma tela do modulo. So existe em modulo que tem varias; modulo de uma tela
   so continua sem pagina nenhuma, e o painel mostra as acoes direto. */
export type PaginaCatalogo = {
  chave: string;
  rotulo: string;
  descricao?: string;
  ordem: number;
};

export type ModuloCatalogo = {
  chave: string;
  rotulo: string;
  descricao?: string;
  paginas?: PaginaCatalogo[];
  acoes: AcaoCatalogo[];
};

const TODOS: CompanyRole[] = ["manager", "financial", "production", "sales", "viewer"];

/* Ordem e agrupamento pensados para a tela: o que a pessoa procura primeiro
   vem antes, e cada modulo carrega o nome que aparece no menu. */
export const CATALOGO: ModuloCatalogo[] = [
  {
    chave: "dashboard",
    rotulo: "Painel",
    descricao: "A tela inicial com os números do negócio.",
    acoes: [
      { chave: "dashboard.read", modulo: "dashboard", acao: "read", rotulo: "Ver o painel",
        descricao: "Abrir a tela inicial com os números do negócio.",
        nivelMinimo: "ver", papeisPadrao: [], ordem: 40 },
    ],
  },
  {
    chave: "orders",
    rotulo: "Pedidos",
    descricao: "Pedidos em produção, do aceite até a entrega.",
    acoes: [
      { chave: "orders.read", modulo: "orders", acao: "read", rotulo: "Ver pedidos",
        nivelMinimo: "ver", papeisPadrao: TODOS, ordem: 110 },
      { chave: "orders.write", modulo: "orders", acao: "write", rotulo: "Criar pedidos e mudar status",
        descricao: "Abrir pedido e avançar o estágio de produção.",
        nivelMinimo: "operar", papeisPadrao: ["manager", "sales", "production"], ordem: 111 },
      { chave: "orders.edit", modulo: "orders", acao: "edit", rotulo: "Alterar itens e prazos do pedido",
        descricao: "Mexer nos itens, na data de entrega e no rastreio de um pedido já aberto.",
        nivelMinimo: "total", papeisPadrao: [], ordem: 112 },
    ],
  },
  {
    chave: "chats",
    rotulo: "Chats",
    descricao: "As conversas com clientes, visitantes da loja e a equipe.",
    acoes: [
      { chave: "chats.read", modulo: "chats", acao: "read", rotulo: "Ver as conversas",
        descricao: "Abrir o Chats e acompanhar o que clientes e visitantes escrevem.",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "orders.read", ordem: 113 },
      { chave: "chats.write", modulo: "chats", acao: "write", rotulo: "Responder e encerrar",
        descricao: "Escrever nas conversas, puxar conversa com visitante e encerrar atendimento.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "orders.edit", ordem: 114 },
      { chave: "chats.settings", modulo: "chats", acao: "settings", rotulo: "Configurar o atendimento",
        descricao: "Horário de atendimento, respostas prontas, boas-vindas e o chat na loja online.",
        nivelMinimo: "total", papeisPadrao: [], herdaDe: "orders.edit", ordem: 115 },
    ],
  },
  {
    chave: "fiscal",
    rotulo: "Notas fiscais",
    descricao: "NF-e, NFC-e e NFS-e: emitir, acompanhar, cancelar e configurar.",
    acoes: [
      { chave: "fiscal.ver", modulo: "fiscal", acao: "ver", rotulo: "Ver notas fiscais",
        descricao: "Abrir as notas emitidas, baixar PDF e XML.",
        nivelMinimo: "ver", papeisPadrao: ["manager", "financial", "sales"], ordem: 116 },
      /* Gastar nota paga é de quem responde pelo caixa: gerente e financeiro.
         Vendedor emite quando o admin marcar aqui. */
      { chave: "fiscal.emitir", modulo: "fiscal", acao: "emitir", rotulo: "Emitir notas fiscais",
        descricao: "Emitir nota de pedido ou sem pedido, reenviar uma rejeitada e marcar o cupom no PDV. Gasta nota do pacote do mês.",
        nivelMinimo: "operar", papeisPadrao: ["manager", "financial"], ordem: 117 },
      { chave: "fiscal.cancelar", modulo: "fiscal", acao: "cancelar", rotulo: "Cancelar e corrigir notas",
        descricao: "Cancelar nota autorizada, carta de correção e inutilizar numeração.",
        nivelMinimo: "total", papeisPadrao: ["manager", "financial"], ordem: 118 },
      { chave: "fiscal.configurar", modulo: "fiscal", acao: "configurar", rotulo: "Configurar notas fiscais",
        descricao: "Dados fiscais da empresa, certificado, tributação e ambiente de emissão.",
        nivelMinimo: "total", papeisPadrao: [], ordem: 119 },
      { chave: "fiscal.recebidas", modulo: "fiscal", acao: "recebidas", rotulo: "Notas recebidas",
        descricao: "Ver as notas que outras empresas emitiram contra o CNPJ e responder a elas.",
        nivelMinimo: "operar", papeisPadrao: ["manager", "financial"], ordem: 120 },
    ],
  },
  /* Produtos digitais (09/10/2026): area nova, separada do resto do painel.
     Sem papel padrao e sem heranca de chave antiga: alem do dono e do admin,
     so entra quem receber o nivel do modulo ou for marcado em "Liberar". Aqui
     aparecem e-mails de alunos e o que cada um comprou. */
  {
    chave: "digital",
    rotulo: "Produtos digitais",
    descricao: "Conteúdos em vídeo, arquivos para baixar, links e a área de membros.",
    paginas: [
      { chave: "visao", rotulo: "Visão geral", descricao: "Vendas, clientes e espaço usado.", ordem: 1 },
      { chave: "produtos", rotulo: "Produtos e conteúdos em vídeo", descricao: "Cadastrar e editar o que se vende, inclusive os vídeos.", ordem: 2 },
      { chave: "alunos", rotulo: "Clientes e acessos", descricao: "Quem comprou, o progresso e o prazo de cada um.", ordem: 3 },
      { chave: "comentarios", rotulo: "Comentários", descricao: "As dúvidas que os clientes deixam nos vídeos.", ordem: 4 },
      { chave: "entregas", rotulo: "Entregas", descricao: "O que cada pedido recebeu e quando.", ordem: 5 },
      { chave: "arquivos", rotulo: "Arquivos e espaço", descricao: "Vídeos, PDFs e o espaço do plano.", ordem: 6 },
      { chave: "configuracoes", rotulo: "Configurações", descricao: "Área de membros, e-mail de entrega, player e certificado.", ordem: 7 },
    ],
    acoes: [
      { chave: "digital.overview.read", modulo: "digital", acao: "overview.read", pagina: "visao", rotulo: "Ver a visão geral",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "digital.read", ordem: 362 },
      { chave: "digital.products.read", modulo: "digital", acao: "products.read", pagina: "produtos", rotulo: "Ver os produtos digitais e os conteúdos em vídeo",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "digital.read", ordem: 363 },
      { chave: "digital.products.write", modulo: "digital", acao: "products.write", pagina: "produtos", rotulo: "Criar e editar produtos digitais e conteúdos em vídeo",
        descricao: "Inclui vídeos, materiais, preço e publicar na loja.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "digital.write", ordem: 364 },
      { chave: "digital.students.read", modulo: "digital", acao: "students.read", pagina: "alunos", rotulo: "Ver os clientes e os acessos",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "digital.read", ordem: 365 },
      { chave: "digital.students.write", modulo: "digital", acao: "students.write", pagina: "alunos", rotulo: "Dar, estender e bloquear acessos",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "digital.write", ordem: 366 },
      { chave: "digital.comments.read", modulo: "digital", acao: "comments.read", pagina: "comentarios", rotulo: "Ver os comentários dos vídeos",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "digital.read", ordem: 367 },
      { chave: "digital.comments.write", modulo: "digital", acao: "comments.write", pagina: "comentarios", rotulo: "Responder e ocultar comentários",
        descricao: "A resposta aparece para os clientes com o selo da loja.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "digital.write", ordem: 368 },
      { chave: "digital.deliveries.read", modulo: "digital", acao: "deliveries.read", pagina: "entregas", rotulo: "Ver as entregas",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "digital.read", ordem: 369 },
      { chave: "digital.deliveries.write", modulo: "digital", acao: "deliveries.write", pagina: "entregas", rotulo: "Reenviar e liberar entregas",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "digital.write", ordem: 370 },
      { chave: "digital.files.read", modulo: "digital", acao: "files.read", pagina: "arquivos", rotulo: "Ver os arquivos e o espaço",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "digital.read", ordem: 371 },
      { chave: "digital.files.write", modulo: "digital", acao: "files.write", pagina: "arquivos", rotulo: "Enviar e apagar arquivos",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "digital.write", ordem: 372 },
      { chave: "digital.settings.read", modulo: "digital", acao: "settings.read", pagina: "configuracoes", rotulo: "Ver as configurações dos digitais",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "digital.read", ordem: 373 },
      { chave: "digital.settings.write", modulo: "digital", acao: "settings.write", pagina: "configuracoes", rotulo: "Mudar as configurações dos digitais",
        descricao: "Área de membros, e-mail de entrega, segurança, player e certificado.",
        nivelMinimo: "total", papeisPadrao: [], herdaDe: "digital.write", ordem: 374 },

      { chave: "digital.read", modulo: "digital", acao: "read", rotulo: "Abrir os produtos digitais",
        descricao: "Ver a área de produtos digitais, os clientes e as entregas.",
        nivelMinimo: "ver", papeisPadrao: [], ordem: 360 },
      { chave: "digital.write", modulo: "digital", acao: "write", rotulo: "Mexer nos produtos digitais",
        descricao: "Criar e editar produtos e conteúdos em vídeo, atender clientes e cuidar das entregas.",
        nivelMinimo: "operar", papeisPadrao: [], ordem: 361 },
    ],
  },
  {
    chave: "quotes",
    rotulo: "Orçamentos",
    descricao: "Propostas enviadas ao cliente antes de virar pedido.",
    acoes: [
      { chave: "quotes.read", modulo: "quotes", acao: "read", rotulo: "Ver orçamentos",
        nivelMinimo: "ver", papeisPadrao: TODOS, ordem: 100 },
      { chave: "quotes.write", modulo: "quotes", acao: "write", rotulo: "Criar e editar orçamentos",
        nivelMinimo: "operar", papeisPadrao: ["manager", "sales"], ordem: 101 },
    ],
  },
  {
    chave: "clients",
    rotulo: "Clientes",
    descricao: "A base de clientes e os dados de contato.",
    paginas: [
      { chave: "lista", rotulo: "Meus clientes", descricao: "O cadastro e o histórico de cada cliente.", ordem: 1 },
      { chave: "ranking", rotulo: "Ranking de clientes", descricao: "Quem compra mais, com faturamento por cliente.", ordem: 2 },
    ],
    acoes: [
      { chave: "clients.list.read", modulo: "clients", acao: "list.read", pagina: "lista",
        rotulo: "Abrir a lista de clientes",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "clients.read", ordem: 332 },
      { chave: "clients.list.write", modulo: "clients", acao: "list.write", pagina: "lista",
        rotulo: "Cadastrar e editar clientes",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "clients.write", ordem: 333 },
      { chave: "clients.ranking.read", modulo: "clients", acao: "ranking.read", pagina: "ranking",
        rotulo: "Abrir o ranking de clientes", descricao: "Mostra quanto cada cliente já comprou.",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "clients.read", ordem: 334 },

      { chave: "clients.read", modulo: "clients", acao: "read", rotulo: "Ver clientes",
        nivelMinimo: "ver", papeisPadrao: TODOS, ordem: 90 },
      { chave: "clients.write", modulo: "clients", acao: "write", rotulo: "Criar e editar clientes",
        nivelMinimo: "operar", papeisPadrao: ["manager", "sales"], ordem: 91 },
    ],
  },
  {
    chave: "products",
    rotulo: "Produtos",
    descricao: "O cadastro interno de produtos.",
    paginas: [
      { chave: "catalogo", rotulo: "Catálogo de produtos", descricao: "O cadastro dos produtos e as oito abas de cada um.", ordem: 1 },
      { chave: "estoque", rotulo: "Estoque", descricao: "Produtos prontos e insumos, com saldo e histórico.", ordem: 2 },
    ],
    acoes: [
      { chave: "products.catalog.read", modulo: "products", acao: "catalog.read", pagina: "catalogo",
        rotulo: "Abrir o catálogo de produtos",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "products.read", ordem: 320 },
      { chave: "products.catalog.write", modulo: "products", acao: "catalog.write", pagina: "catalogo",
        rotulo: "Criar e editar produtos",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "products.write", ordem: 321 },
      { chave: "products.stock.read", modulo: "products", acao: "stock.read", pagina: "estoque",
        rotulo: "Abrir o estoque", descricao: "Produtos prontos e insumos, com saldo.",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "products.read", ordem: 322 },
      { chave: "products.stock.write", modulo: "products", acao: "stock.write", pagina: "estoque",
        rotulo: "Ajustar saldo e dar entrada", descricao: "Mexer no que o sistema conta que existe.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "products.write", ordem: 323 },

      { chave: "products.read", modulo: "products", acao: "read", rotulo: "Ver produtos",
        descricao: "Consultar o catálogo interno de produtos.",
        nivelMinimo: "ver", papeisPadrao: TODOS, ordem: 60 },
      { chave: "products.write", modulo: "products", acao: "write", rotulo: "Criar e editar produtos",
        descricao: "Cadastrar, alterar e remover produtos.",
        nivelMinimo: "operar", papeisPadrao: ["manager"], ordem: 61 },
    ],
  },
  {
    chave: "categories",
    rotulo: "Categorias",
    descricao: "Como os produtos são agrupados.",
    acoes: [
      { chave: "categories.read", modulo: "categories", acao: "read", rotulo: "Ver categorias",
        nivelMinimo: "ver", papeisPadrao: TODOS, ordem: 70 },
      { chave: "categories.write", modulo: "categories", acao: "write", rotulo: "Criar e editar categorias",
        nivelMinimo: "operar", papeisPadrao: ["manager"], ordem: 71 },
    ],
  },
  {
    chave: "pricing",
    rotulo: "Precificação",
    descricao: "Custos, margens e o preço sugerido.",
    paginas: [
      { chave: "configuracao", rotulo: "Configuração da precificação", descricao: "O caminho de cinco passos e o que falta em cada um.", ordem: 1 },
      { chave: "assistente", rotulo: "Assistente de preço", descricao: "Formar o preço de um produto, passo a passo.", ordem: 2 },
      { chave: "equilibrio", rotulo: "Ponto de Equilíbrio", descricao: "O placar do mês: quanto vender para pagar a casa.", ordem: 3 },
      { chave: "impostos", rotulo: "Impostos e taxas", descricao: "O que sai de cada venda antes de sobrar margem.", ordem: 4 },
    ],
    acoes: [
      { chave: "pricing.config.read", modulo: "pricing", acao: "config.read", pagina: "configuracao",
        rotulo: "Abrir a configuração",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "pricing.read", ordem: 314 },
      { chave: "pricing.config.write", modulo: "pricing", acao: "config.write", pagina: "configuracao",
        rotulo: "Mexer na configuração da precificação",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "pricing.write", ordem: 315 },
      { chave: "pricing.wizard.read", modulo: "pricing", acao: "wizard.read", pagina: "assistente",
        rotulo: "Usar o assistente de preço", descricao: "Formar preço de produto. Salvar ainda pede permissão de produtos.",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "pricing.read", ordem: 316 },
      { chave: "pricing.health.read", modulo: "pricing", acao: "health.read", pagina: "equilibrio",
        rotulo: "Abrir o Ponto de Equilíbrio", descricao: "O faturamento, a margem e o lucro do mês.",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "pricing.read", ordem: 317 },
      { chave: "pricing.health.write", modulo: "pricing", acao: "health.write", pagina: "equilibrio",
        rotulo: "Mexer no Ponto de Equilíbrio", descricao: "Salvar a meta do mês e os ajustes do placar.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "pricing.write", ordem: 342 },
      { chave: "pricing.taxes.read", modulo: "pricing", acao: "taxes.read", pagina: "impostos",
        rotulo: "Ver impostos e taxas da venda",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "pricing.read", ordem: 318 },
      /* Esta tela sempre foi gravada com `financial.write`, nao com
         `pricing.write`: e de imposto. Herda de la para o financeiro que
         edita isso hoje continuar editando. */
      { chave: "pricing.taxes.write", modulo: "pricing", acao: "taxes.write", pagina: "impostos",
        rotulo: "Alterar impostos e taxas", descricao: "Muda o preço de todo produto novo.",
        nivelMinimo: "total", papeisPadrao: [], herdaDe: "financial.write", ordem: 319 },

      { chave: "pricing.read", modulo: "pricing", acao: "read", rotulo: "Ver custos e margens",
        descricao: "Custo estimado, lucro bruto e margem nos produtos e orçamentos. Não afeta o preço de venda, que faz parte de criar o orçamento.",
        nivelMinimo: "ver", papeisPadrao: TODOS, ordem: 150 },
      { chave: "pricing.write", modulo: "pricing", acao: "write", rotulo: "Alterar a estrutura de custo",
        descricao: "Mexer no custo que forma a margem. O preço de venda continua com quem edita o produto ou o orçamento.",
        nivelMinimo: "operar", papeisPadrao: ["manager", "financial"], ordem: 151 },
    ],
  },
  {
    chave: "financial",
    rotulo: "Financeiro",
    descricao: "Contas a pagar e receber, caixa e conciliação.",
    paginas: [
      { chave: "overview", rotulo: "Visão geral", descricao: "O resumo do mês: entradas, saídas e o que está por vencer.", ordem: 1 },
      { chave: "payables", rotulo: "Contas a pagar", descricao: "As contas da empresa e o pagamento delas.", ordem: 2 },
      { chave: "fixedcosts", rotulo: "Custos fixos", descricao: "O que a empresa paga mesmo vendendo zero. Alimenta a precificação.", ordem: 3 },
      { chave: "receivables", rotulo: "Contas a receber", descricao: "A carteira de títulos e a baixa dos recebimentos.", ordem: 4 },
      { chave: "payments", rotulo: "Pagamentos recebidos", descricao: "O histórico do que entrou, por forma de pagamento.", ordem: 5 },
      { chave: "cashflow", rotulo: "Fluxo de caixa", descricao: "Entradas, saídas e resultado do período.", ordem: 6 },
      { chave: "bank", rotulo: "Contas bancárias", descricao: "Os bancos da empresa e os saldos deles.", ordem: 7 },
      { chave: "dre", rotulo: "DRE", descricao: "O resultado por caixa, simples e analítico.", ordem: 8 },
      { chave: "links", rotulo: "Links de pagamento", descricao: "Cobranças por link e o checkout delas.", ordem: 9 },
      { chave: "amounts", rotulo: "Os valores em dinheiro", descricao: "Ver os números, ou trabalhar nas telas com eles borrados.", ordem: 11 },
    ],
    acoes: [
      /* As duas chaves antigas continuam existindo e continuam sendo a porta
         do modulo inteiro. Toda chave de pagina HERDA de uma delas, entao
         ninguem perde nem ganha acesso hoje: quem tinha o Financeiro continua
         com as onze telas, e so muda quem for configurado tela a tela. */
      { chave: "financial.read", modulo: "financial", acao: "read", rotulo: "Ver o financeiro",
        descricao: "A porta do módulo. Vale para as telas que não tiverem regra própria.",
        nivelMinimo: "ver", papeisPadrao: ["financial"], ordem: 120 },
      { chave: "financial.write", modulo: "financial", acao: "write", rotulo: "Lançar e baixar no financeiro",
        descricao: "A porta de operar. Vale para as telas que não tiverem regra própria.",
        nivelMinimo: "operar", papeisPadrao: ["financial"], ordem: 121 },

      { chave: "financial.overview.read", modulo: "financial", acao: "overview.read", pagina: "overview",
        rotulo: "Abrir a visão geral", descricao: "O resumo do mês, com entradas, saídas e vencimentos.",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "financial.read", ordem: 122 },

      { chave: "financial.payables.read", modulo: "financial", acao: "payables.read", pagina: "payables",
        rotulo: "Abrir contas a pagar", nivelMinimo: "ver", papeisPadrao: [], herdaDe: "financial.read", ordem: 123 },
      { chave: "financial.payables.write", modulo: "financial", acao: "payables.write", pagina: "payables",
        rotulo: "Criar e editar contas a pagar", descricao: "Lançar conta nova, alterar valor, vencimento e categoria.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "financial.write", ordem: 124 },
      { chave: "financial.payables.settle", modulo: "financial", acao: "payables.settle", pagina: "payables",
        rotulo: "Registrar pagamento de conta", descricao: "Dar baixa numa conta a pagar, e estornar a baixa.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "financial.write", ordem: 125 },

      { chave: "financial.fixedcosts.read", modulo: "financial", acao: "fixedcosts.read", pagina: "fixedcosts",
        rotulo: "Ver os custos fixos", nivelMinimo: "ver", papeisPadrao: [], herdaDe: "financial.read", ordem: 126 },
      { chave: "financial.fixedcosts.write", modulo: "financial", acao: "fixedcosts.write", pagina: "fixedcosts",
        rotulo: "Editar custos fixos e horas produtivas",
        descricao: "Muda a hora da estrutura e, com ela, o preço de todo produto.",
        nivelMinimo: "total", papeisPadrao: [], herdaDe: "financial.write", ordem: 127 },

      { chave: "financial.receivables.read", modulo: "financial", acao: "receivables.read", pagina: "receivables",
        rotulo: "Abrir contas a receber", nivelMinimo: "ver", papeisPadrao: [], herdaDe: "financial.read", ordem: 128 },
      { chave: "financial.receivables.write", modulo: "financial", acao: "receivables.write", pagina: "receivables",
        rotulo: "Criar e editar contas a receber", nivelMinimo: "operar", papeisPadrao: [], herdaDe: "financial.write", ordem: 129 },
      { chave: "financial.receivables.settle", modulo: "financial", acao: "receivables.settle", pagina: "receivables",
        rotulo: "Baixar e estornar recebimento", descricao: "Registrar que o cliente pagou, e desfazer a baixa.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "financial.write", ordem: 130 },

      { chave: "financial.payments.read", modulo: "financial", acao: "payments.read", pagina: "payments",
        rotulo: "Abrir o histórico de pagamentos", nivelMinimo: "ver", papeisPadrao: [], herdaDe: "financial.read", ordem: 131 },

      { chave: "financial.cashflow.read", modulo: "financial", acao: "cashflow.read", pagina: "cashflow",
        rotulo: "Abrir o fluxo de caixa", nivelMinimo: "ver", papeisPadrao: [], herdaDe: "financial.read", ordem: 132 },
      { chave: "financial.cashflow.write", modulo: "financial", acao: "cashflow.write", pagina: "cashflow",
        rotulo: "Lançar movimentação no caixa", nivelMinimo: "operar", papeisPadrao: [], herdaDe: "financial.write", ordem: 133 },

      { chave: "financial.bank.read", modulo: "financial", acao: "bank.read", pagina: "bank",
        rotulo: "Ver as contas bancárias", nivelMinimo: "ver", papeisPadrao: [], herdaDe: "financial.read", ordem: 134 },
      { chave: "financial.bank.write", modulo: "financial", acao: "bank.write", pagina: "bank",
        rotulo: "Cadastrar e editar contas bancárias", nivelMinimo: "total", papeisPadrao: [], herdaDe: "financial.write", ordem: 135 },
        /* Mesmo caso: a integração é configurada em Contas bancárias, mas
           quem podia era quem tinha ajustes da empresa. Herda de lá. */
      { chave: "financial.bank.integrations", modulo: "financial", acao: "bank.integrations", pagina: "bank",
        rotulo: "Conectar o Mercado Pago", descricao: "A credencial que recebe o Pix e o cartão da empresa.",
        nivelMinimo: "total", papeisPadrao: [], herdaDe: "company.settings", ordem: 345 },

      { chave: "financial.dre.read", modulo: "financial", acao: "dre.read", pagina: "dre",
        rotulo: "Abrir o DRE", descricao: "O resultado da empresa, simples e analítico.",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "financial.read", ordem: 136 },

      { chave: "financial.links.read", modulo: "financial", acao: "links.read", pagina: "links",
        rotulo: "Ver os links de pagamento", nivelMinimo: "ver", papeisPadrao: [], herdaDe: "financial.read", ordem: 137 },
      { chave: "financial.links.write", modulo: "financial", acao: "links.write", pagina: "links",
        rotulo: "Criar e editar links de pagamento", nivelMinimo: "operar", papeisPadrao: [], herdaDe: "financial.write", ordem: 138 },


      /* A acao transversal: vale em todas as telas do modulo ao mesmo tempo.
         Negada, a pessoa abre a tela e trabalha, e os numeros aparecem
         borrados. E o caso de quem confere vencimento sem precisar saber
         quanto a empresa deve. */
      { chave: "financial.amounts.see", modulo: "financial", acao: "amounts.see", pagina: "amounts",
        rotulo: "Ver os valores em dinheiro",
        descricao: "Desmarcado, a pessoa continua abrindo as telas e os valores aparecem borrados.",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "financial.read", ordem: 140 },
    ],
  },
  {
    chave: "commissions",
    rotulo: "Comissões",
    descricao: "Regras, apuração e pagamento de comissão.",
    acoes: [
      { chave: "commissions.self", modulo: "commissions", acao: "self", rotulo: "Ver as próprias comissões",
        descricao: "Cada pessoa acompanha o que ela mesma tem a receber.",
        nivelMinimo: "ver", papeisPadrao: TODOS, ordem: 131 },
      { chave: "commissions.read", modulo: "commissions", acao: "read", rotulo: "Ver comissões da equipe",
        nivelMinimo: "ver", papeisPadrao: ["manager", "financial"], ordem: 130 },
      { chave: "commissions.write", modulo: "commissions", acao: "write", rotulo: "Configurar regras de comissão",
        nivelMinimo: "operar", papeisPadrao: ["manager"], ordem: 132 },
      { chave: "commissions.profile", modulo: "commissions", acao: "profile", rotulo: "Definir perfil de repasse",
        nivelMinimo: "operar", papeisPadrao: ["manager", "financial", "sales"], ordem: 133 },
      { chave: "commissions.adjust", modulo: "commissions", acao: "adjust", rotulo: "Ajustar valores de comissão",
        nivelMinimo: "total", papeisPadrao: ["financial"], ordem: 134 },
      { chave: "commissions.close", modulo: "commissions", acao: "close", rotulo: "Fechar período de comissão",
        nivelMinimo: "total", papeisPadrao: ["financial"], ordem: 135 },
      { chave: "commissions.approve", modulo: "commissions", acao: "approve", rotulo: "Aprovar comissões",
        nivelMinimo: "total", papeisPadrao: ["financial"], ordem: 136 },
      { chave: "commissions.pay", modulo: "commissions", acao: "pay", rotulo: "Pagar comissões",
        nivelMinimo: "total", papeisPadrao: ["financial"], ordem: 137 },
    ],
  },
  {
    chave: "agenda",
    rotulo: "Agenda",
    descricao: "Compromissos e prazos da equipe.",
    paginas: [
      { chave: "agenda", rotulo: "A agenda", descricao: "Os compromissos e prazos da equipe.", ordem: 1 },
      { chave: "relatorio", rotulo: "Relatório da agenda", descricao: "O que foi feito no período.", ordem: 2 },
    ],
    acoes: [
      { chave: "agenda.board.read", modulo: "agenda", acao: "board.read", pagina: "agenda",
        rotulo: "Abrir a agenda",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "agenda.read", ordem: 335 },
      { chave: "agenda.board.write", modulo: "agenda", acao: "board.write", pagina: "agenda",
        rotulo: "Criar e mexer em compromissos",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "agenda.write", ordem: 336 },
      { chave: "agenda.report.read", modulo: "agenda", acao: "report.read", pagina: "relatorio",
        rotulo: "Abrir o relatório da agenda",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "agenda.read", ordem: 337 },

      { chave: "agenda.read", modulo: "agenda", acao: "read", rotulo: "Ver a agenda",
        descricao: "Compromissos e prazos de todo o sistema.",
        nivelMinimo: "ver", papeisPadrao: TODOS, ordem: 140 },
      { chave: "agenda.write", modulo: "agenda", acao: "write", rotulo: "Marcar e remarcar compromissos",
        nivelMinimo: "operar", papeisPadrao: ["manager", "sales", "production"], ordem: 141 },
    ],
  },
  {
    chave: "catalog",
    rotulo: "Catálogo público",
    descricao: "A loja pública vista pelo cliente.",
    paginas: [
      { chave: "loja", rotulo: "A loja e a vitrine", descricao: "O desenho da loja, as seções e o tema.", ordem: 1 },
      { chave: "painel", rotulo: "Painel da loja", descricao: "Visitas, conversão e o que vendeu na loja.", ordem: 2 },
      { chave: "produtos", rotulo: "Produtos na loja", descricao: "Quais produtos aparecem e como.", ordem: 3 },
      { chave: "pedidos", rotulo: "Pedidos da loja", descricao: "Os pedidos que chegaram pela loja.", ordem: 4 },
      { chave: "banners", rotulo: "Banners", descricao: "As faixas da página inicial da loja.", ordem: 5 },
      { chave: "stories", rotulo: "Stories", descricao: "Os stories da loja.", ordem: 6 },
      { chave: "avaliacoes", rotulo: "Avaliações", descricao: "O que os clientes escreveram.", ordem: 7 },
    ],
    acoes: [
      { chave: "catalog.store.read", modulo: "catalog", acao: "store.read", pagina: "loja",
        rotulo: "Abrir a loja e a vitrine",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "catalog.read", ordem: 301 },
      { chave: "catalog.store.write", modulo: "catalog", acao: "store.write", pagina: "loja",
        rotulo: "Mexer no desenho da loja", descricao: "Seções, tema, cores e a página inicial.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "catalog.write", ordem: 302 },
      { chave: "catalog.dashboard.read", modulo: "catalog", acao: "dashboard.read", pagina: "painel",
        rotulo: "Abrir o painel da loja", descricao: "Visitas, conversão e faturamento da loja.",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "catalog.read", ordem: 303 },
      { chave: "catalog.products.read", modulo: "catalog", acao: "products.read", pagina: "produtos",
        rotulo: "Ver os produtos da loja",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "catalog.read", ordem: 304 },
      { chave: "catalog.products.write", modulo: "catalog", acao: "products.write", pagina: "produtos",
        rotulo: "Publicar e tirar produtos da loja",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "catalog.write", ordem: 305 },
      { chave: "catalog.orders.read", modulo: "catalog", acao: "orders.read", pagina: "pedidos",
        rotulo: "Ver os pedidos da loja",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "catalog.read", ordem: 306 },
      { chave: "catalog.orders.write", modulo: "catalog", acao: "orders.write", pagina: "pedidos",
        rotulo: "Mexer nos pedidos da loja", descricao: "Mudar situação e cancelar pedido feito na loja.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "catalog.write", ordem: 307 },
      { chave: "catalog.banners.read", modulo: "catalog", acao: "banners.read", pagina: "banners",
        rotulo: "Ver os banners",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "catalog.read", ordem: 308 },
      { chave: "catalog.banners.write", modulo: "catalog", acao: "banners.write", pagina: "banners",
        rotulo: "Criar e editar banners",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "catalog.write", ordem: 309 },
      { chave: "catalog.stories.read", modulo: "catalog", acao: "stories.read", pagina: "stories",
        rotulo: "Ver os stories",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "catalog.read", ordem: 310 },
      { chave: "catalog.stories.write", modulo: "catalog", acao: "stories.write", pagina: "stories",
        rotulo: "Criar e editar stories",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "catalog.write", ordem: 311 },
      { chave: "catalog.reviews.read", modulo: "catalog", acao: "reviews.read", pagina: "avaliacoes",
        rotulo: "Ver as avaliações",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "catalog.read", ordem: 312 },
      { chave: "catalog.reviews.write", modulo: "catalog", acao: "reviews.write", pagina: "avaliacoes",
        rotulo: "Aprovar e responder avaliações",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "catalog.write", ordem: 313 },

      { chave: "catalog.read", modulo: "catalog", acao: "read", rotulo: "Ver o catálogo público",
        nivelMinimo: "ver", papeisPadrao: TODOS, ordem: 80 },
      { chave: "catalog.write", modulo: "catalog", acao: "write", rotulo: "Editar o catálogo público",
        descricao: "Publicar produtos, banners e marketing da loja.",
        nivelMinimo: "operar", papeisPadrao: ["manager"], ordem: 81 },
    ],
  },
  {
    chave: "pdv",
    rotulo: "PDV",
    descricao: "Vendas no balcão e o caixa do dia.",
    acoes: [
      { chave: "pdv.read", modulo: "pdv", acao: "read", rotulo: "Abrir o PDV",
        descricao: "Abrir o ponto de venda. Fechar a venda depende também de criar pedidos e lançar no financeiro.",
        nivelMinimo: "ver", papeisPadrao: [], ordem: 50 },
    ],
  },
  {
    chave: "ia",
    rotulo: "Inteligência artificial",
    descricao: "Os recursos de inteligência artificial.",
    acoes: [
      { chave: "ia.read", modulo: "ia", acao: "read", rotulo: "Ver o assistente de IA",
        descricao: "Abrir o assistente que monta rascunhos de orçamento a partir da conversa com o cliente.",
        nivelMinimo: "ver", papeisPadrao: TODOS, ordem: 160 },
      { chave: "ia.write", modulo: "ia", acao: "write", rotulo: "Gerar conteúdo com IA",
        descricao: "Pedir para a IA escrever o rascunho ou a descrição. É o que as rotas de IA sempre exigiram.",
        nivelMinimo: "operar", papeisPadrao: ["manager"], ordem: 161 },
    ],
  },
  {
    chave: "suppliers",
    rotulo: "Fornecedores",
    descricao: "Fornecedores, compras e contas vinculadas.",
    /**
     * Fornecedores deixou de depender do Financeiro (09/09/2026).
     *
     * As duas chaves nasceram com `papeisPadrao: []`, so herdando de
     * `financial.*`. Na pratica isso trancava o modulo: em producao, dos 43
     * funcionarios com papel vendas, producao, gerente ou visualizador, um
     * unico tinha alguma permissao de fornecedor. Gerente e comprador nao
     * abriam a tela, e o menu fica sob "Operacao", onde ninguem adivinha que a
     * tranca e do financeiro.
     *
     * Agora cada acao tem os proprios papeis. O `herdaDe` fica de proposito:
     * ele e a rede que garante que quem hoje entra por `financial.*` continue
     * entrando, sem ninguem perder acesso na virada. Como a cadeia e lida da
     * chave mais especifica para a mais antiga, um ajuste explicito em
     * `suppliers.*` vence o do financeiro.
     */
    paginas: [
      { chave: "lista", rotulo: "Fornecedores e compras", descricao: "A lista, o cadastro, as compras de cada um e o histórico.", ordem: 1 },
      { chave: "xbz", rotulo: "XBZ", descricao: "O catálogo do fornecedor XBZ.", ordem: 3 },
    ],
    acoes: [
      { chave: "suppliers.list.read", modulo: "suppliers", acao: "list.read", pagina: "lista",
        rotulo: "Ver os fornecedores",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "suppliers.read", ordem: 325 },
      { chave: "suppliers.list.write", modulo: "suppliers", acao: "list.write", pagina: "lista",
        rotulo: "Cadastrar fornecedor e lançar compra",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "suppliers.write", ordem: 326 },
      { chave: "suppliers.xbz.read", modulo: "suppliers", acao: "xbz.read", pagina: "xbz",
        rotulo: "Abrir o catálogo XBZ",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "suppliers.read", ordem: 327 },
      { chave: "suppliers.xbz.write", modulo: "suppliers", acao: "xbz.write", pagina: "xbz",
        rotulo: "Comprar e sincronizar na XBZ", descricao: "Criar e cancelar pedido, e puxar o catálogo de lá.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "suppliers.write", ordem: 343 },

      { chave: "suppliers.read", modulo: "suppliers", acao: "read", rotulo: "Ver fornecedores",
        descricao: "Consultar a lista de fornecedores e os dados de contato.",
        nivelMinimo: "ver", papeisPadrao: ["manager", "financial", "production"], herdaDe: "financial.read", ordem: 200 },
      { chave: "suppliers.write", modulo: "suppliers", acao: "write", rotulo: "Cadastrar e editar fornecedores",
        descricao: "Criar, alterar e remover fornecedores, e registrar compras.",
        nivelMinimo: "operar", papeisPadrao: ["manager", "financial"], herdaDe: "financial.write", ordem: 201 },
    ],
  },
  {
    chave: "production",
    rotulo: "Produção",
    descricao: "Ordens de produção e o andamento na fábrica.",
    paginas: [
      { chave: "painel", rotulo: "Painel de produção", descricao: "O kanban, a ordem de produção e o cronômetro.", ordem: 1 },
      { chave: "processos", rotulo: "Processos e custos", descricao: "Máquinas, mão de obra e o custo da hora.", ordem: 2 },
    ],
    acoes: [
      { chave: "production.board.read", modulo: "production", acao: "board.read", pagina: "painel",
        rotulo: "Abrir o painel de produção",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "production.read", ordem: 328 },
      { chave: "production.board.write", modulo: "production", acao: "board.write", pagina: "painel",
        rotulo: "Mover pedidos e apontar produção", descricao: "Arrastar card, ligar cronômetro e registrar perda.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "production.write", ordem: 329 },
        /* Herda de `company.settings`, que era o que isto exigia: aparece em
           Produção, onde a pessoa entende, sem mudar quem pode hoje. */
      { chave: "production.board.columns", modulo: "production", acao: "board.columns", pagina: "painel",
        rotulo: "Mexer nas colunas do painel", descricao: "Criar, renomear e reordenar as etapas do kanban.",
        nivelMinimo: "total", papeisPadrao: [], herdaDe: "company.settings", ordem: 344 },
      { chave: "production.costs.read", modulo: "production", acao: "costs.read", pagina: "processos",
        rotulo: "Ver máquinas e mão de obra", descricao: "Inclui o custo por hora de cada recurso.",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "production.read", ordem: 330 },
      { chave: "production.costs.write", modulo: "production", acao: "costs.write", pagina: "processos",
        rotulo: "Cadastrar máquinas e funções", descricao: "Muda o custo de produção de todo produto.",
        nivelMinimo: "total", papeisPadrao: [], herdaDe: "production.write", ordem: 331 },

      { chave: "production.read", modulo: "production", acao: "read", rotulo: "Ver a produção",
        descricao: "Acompanhar as ordens e o andamento do que está sendo produzido.",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "products.read", ordem: 210 },
      { chave: "production.write", modulo: "production", acao: "write", rotulo: "Movimentar a produção",
        descricao: "Criar ordens de produção e avançar as etapas.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "products.write", ordem: 211 },
    ],
  },
  {
    chave: "materials",
    rotulo: "Insumos",
    descricao: "Insumos usados na produção e o custo de cada um.",
    acoes: [
      { chave: "materials.read", modulo: "materials", acao: "read", rotulo: "Ver insumos",
        descricao: "Consultar os insumos usados na produção e o custo de cada um.",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "products.read", ordem: 220 },
      { chave: "materials.write", modulo: "materials", acao: "write", rotulo: "Cadastrar e editar insumos",
        descricao: "Criar, alterar e remover insumos e suas medidas.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "products.write", ordem: 221 },
    ],
  },
  {
    chave: "reports",
    rotulo: "Relatórios",
    descricao: "Relatórios de vendas, produção e resultado.",
    acoes: [
      { chave: "reports.read", modulo: "reports", acao: "read", rotulo: "Ver relatórios",
        descricao: "Abrir os relatórios de vendas, produção e resultado.",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "financial.read", ordem: 230 },
    ],
  },
  {
    chave: "whatsapp",
    rotulo: "WhatsApp",
    descricao: "A conexão do número e as mensagens automáticas.",
    acoes: [
      { chave: "whatsapp.manage", modulo: "whatsapp", acao: "manage", rotulo: "Configurar o WhatsApp",
        descricao: "Conectar o número e definir as mensagens automáticas.",
        nivelMinimo: "total", papeisPadrao: [], herdaDe: "company.settings", ordem: 240 },
    ],
  },
  {
    chave: "marketing",
    rotulo: "Marketing",
    descricao: "Campanhas e materiais de divulgação.",
    acoes: [
      { chave: "marketing.read", modulo: "marketing", acao: "read", rotulo: "Ver o marketing",
        descricao: "Abrir as campanhas e materiais de divulgação da loja.",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "catalog.read", ordem: 250 },
      { chave: "marketing.manage", modulo: "marketing", acao: "manage", rotulo: "Editar o marketing",
        descricao: "Criar e publicar campanhas, banners e materiais de divulgação.",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "catalog.write", ordem: 251 },
    ],
  },
  {
    chave: "company",
    rotulo: "Empresa",
    descricao: "Dados da empresa, identidade e integrações.",
    paginas: [
      { chave: "dados", rotulo: "Dados da empresa", descricao: "Nome, documento, endereço e identidade visual.", ordem: 1 },
      { chave: "frete", rotulo: "Frete", descricao: "As regras de entrega e os valores cobrados.", ordem: 2 },
      { chave: "assistentes", rotulo: "Assistentes e Apps", descricao: "As chaves que ligam o Claude, o ChatGPT e outros programas à conta.", ordem: 3 },
    ],
    acoes: [
      { chave: "company.data.read", modulo: "company", acao: "data.read", pagina: "dados",
        rotulo: "Abrir os dados da empresa",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "company.settings", ordem: 338 },
      { chave: "company.data.write", modulo: "company", acao: "data.write", pagina: "dados",
        rotulo: "Alterar os dados da empresa",
        nivelMinimo: "total", papeisPadrao: [], herdaDe: "company.settings", ordem: 339 },
      { chave: "company.shipping.read", modulo: "company", acao: "shipping.read", pagina: "frete",
        rotulo: "Ver as regras de frete",
        nivelMinimo: "ver", papeisPadrao: [], herdaDe: "company.settings", ordem: 340 },
      { chave: "company.shipping.write", modulo: "company", acao: "shipping.write", pagina: "frete",
        rotulo: "Alterar as regras de frete",
        nivelMinimo: "operar", papeisPadrao: [], herdaDe: "company.settings", ordem: 341 },
      /* Sem nível mínimo, sem papel padrão e sem herança: além do dono e do
         admin, só entra quem for marcado em "Liberar". Gerente tem
         `company.settings` por padrão, e chave de acesso é coisa para dar de
         caso pensado, não por tabela. */
      { chave: "company.assistants.manage", modulo: "company", acao: "assistants.manage", pagina: "assistentes",
        rotulo: "Usar assistentes e apps",
        descricao: "Criar chaves de acesso e ligar o Claude, o ChatGPT e outros programas à conta, com as permissões da própria pessoa.",
        nivelMinimo: null, papeisPadrao: [], ordem: 346 },

      { chave: "company.settings", modulo: "company", acao: "settings", rotulo: "Configurações da empresa",
        descricao: "Dados da empresa, identidade e integrações.",
        nivelMinimo: "total", papeisPadrao: ["manager"], ordem: 30 },
    ],
  },
  {
    chave: "users",
    rotulo: "Funcionários",
    descricao: "Quem entra no sistema e o que cada um pode.",
    acoes: [
      { chave: "users.manage", modulo: "users", acao: "manage", rotulo: "Gerenciar funcionários",
        descricao: "Convidar, editar permissões e desativar pessoas da equipe.",
        nivelMinimo: "total", papeisPadrao: [], ordem: 10 },
    ],
  },
  {
    chave: "subscription",
    rotulo: "Assinatura",
    descricao: "O plano contratado e a cobrança.",
    acoes: [
      { chave: "subscription.manage", modulo: "subscription", acao: "manage", rotulo: "Gerenciar assinatura",
        descricao: "Ver e alterar o plano contratado.",
        nivelMinimo: "total", papeisPadrao: [], ordem: 20 },
    ],
  },
];

/** Busca direta por chave, para não varrer o catálogo a cada verificação. */
export const ACAO_POR_CHAVE: Map<string, AcaoCatalogo> = new Map(
  CATALOGO.flatMap((m) => m.acoes).map((a) => [a.chave, a])
);

export const ORDEM_NIVEL: Record<NivelModulo, number> = { nenhum: 0, ver: 1, operar: 2, total: 3 };

/** Rótulos da escada, como o admin lê no modal. */
export const ROTULO_NIVEL: Record<NivelModulo, string> = {
  nenhum: "Sem acesso",
  ver: "Só ver",
  operar: "Ver e operar",
  total: "Acesso total",
};

/**
 * Os degraus que fazem sentido oferecer para um módulo.
 *
 * Oferecer "Só ver" num módulo cujo trabalho todo é de operar seria mentira: a
 * escolha não mudaria nada. Então a escada é montada a partir das ações que o
 * módulo realmente tem, e "Sem acesso" entra sempre, porque fechar sempre faz
 * sentido.
 */
export function niveisDoModulo(modulo: ModuloCatalogo): NivelModulo[] {
  const presentes = new Set<NivelModulo>();
  for (const acao of modulo.acoes) {
    if (acao.nivelMinimo) presentes.add(acao.nivelMinimo);
  }
  const escada: NivelModulo[] = ["nenhum", "ver", "operar", "total"];
  return escada.filter((n) => n === "nenhum" || presentes.has(n));
}

/**
 * A chave pedida seguida das que ela herda, da mais específica para a mais
 * antiga: `suppliers.read` → `financial.read`.
 *
 * O limite de passos e o registro de visitadas não são defesa contra o catálogo
 * de hoje, onde nenhuma cadeia passa de dois elos — são contra a linha errada
 * que alguém escreva depois. Um ciclo aqui travaria o processo inteiro na
 * primeira verificação de permissão, e verificação de permissão roda em toda
 * página. Melhor parar e negar.
 */
export function cadeiaDe(chave: string): string[] {
  const cadeia: string[] = [];
  const vistas = new Set<string>();
  let atual: string | undefined = chave;

  while (atual && !vistas.has(atual) && cadeia.length < 6) {
    cadeia.push(atual);
    vistas.add(atual);
    atual = ACAO_POR_CHAVE.get(atual)?.herdaDe;
  }

  return cadeia;
}
