# Cria os perfis pré-prontos e atribui a cada usuário existente o perfil do papel
# que ele já tinha. Sem isso, o dia seguinte ao deploy seria "todo mundo no
# fallback" — funciona, mas a tela de perfis nasceria vazia e o ADM não teria de
# onde partir para montar o dele.
#
# ⚠️ A lista de chaves está DUPLICADA aqui e em Permissao::PADRAO_POR_ROLE, de
# propósito: migration não pode depender de model. Se o catálogo mudar daqui a
# seis meses, o histórico do banco não pode mudar junto — quem já rodou esta
# migration continua com o perfil que foi criado naquele dia.
#
# Idempotente (o teste e a produção migram em momentos diferentes, e a migration
# pode encontrar um banco onde o ADM já criou perfis à mão).
class SemearPerfisAcesso < ActiveRecord::Migration[7.1]
  TODAS = %w[
    dashboard.ver dashboard.financeiro dashboard.operacoes dashboard.exportar dashboard.metricas
    consolidacao.ver consolidacao.criar consolidacao.editar consolidacao.editar_finalizada
    consolidacao.finalizar consolidacao.arquivar consolidacao.excluir
    consolidacao.registrar_pagamento consolidacao.cancelar_pagamento
    consolidacao.gerir_motoristas consolidacao.exportar_pdf
    notificacao.contatos notificacao.contatos_gerenciar notificacao.contatos_excluir
    notificacao.eventos notificacao.eventos_gerenciar notificacao.disparar_manual
    notificacao.variaveis notificacao.envios notificacao.credenciais notificacao.whatsapp_sessao
    admin.usuarios admin.usuarios_gerenciar admin.perfis
    admin.configuracoes admin.configuracoes_editar admin.auditoria
    admin.edicao_lancamento admin.planilha_simpli_route
  ].freeze

  GERENTE = %w[
    dashboard.ver dashboard.financeiro dashboard.operacoes dashboard.exportar dashboard.metricas
    consolidacao.ver consolidacao.criar consolidacao.editar consolidacao.editar_finalizada
    consolidacao.finalizar consolidacao.arquivar consolidacao.excluir
    consolidacao.registrar_pagamento consolidacao.cancelar_pagamento
    consolidacao.gerir_motoristas consolidacao.exportar_pdf
    notificacao.contatos notificacao.contatos_gerenciar notificacao.envios
    admin.usuarios admin.configuracoes admin.auditoria admin.planilha_simpli_route
  ].freeze

  OPERADOR = %w[
    dashboard.ver dashboard.financeiro dashboard.operacoes dashboard.exportar dashboard.metricas
    consolidacao.ver consolidacao.criar consolidacao.editar consolidacao.finalizar
    consolidacao.gerir_motoristas consolidacao.exportar_pdf
  ].freeze

  EXTERNO = %w[dashboard.ver dashboard.operacoes].freeze

  # nome, descrição, permissões, role legada que recebe este perfil
  PERFIS = [
    ['Administrador', 'Acesso total ao sistema.',                                   :todas,   0],
    ['Gerente',       'Opera e paga; administra usuários, preços e destinatários.', GERENTE,  1],
    ['Operador',      'Monta e finaliza consolidações; não paga nem administra.',   OPERADOR, 2],
    ['Externo',       'Somente leitura dos indicadores de operação.',               EXTERNO,  4]
  ].freeze

  def up
    PERFIS.each do |nome, descricao, permissoes, role|
      lista = (permissoes == :todas ? TODAS : permissoes)

      id = select_value("SELECT id FROM perfis_acesso WHERE LOWER(nome) = #{quote(nome.downcase)}")
      if id.nil?
        execute(<<~SQL.squish)
          INSERT INTO perfis_acesso (nome, descricao, permissoes, sistema, ativo, created_at, updated_at)
          VALUES (#{quote(nome)}, #{quote(descricao)}, #{quote(lista.to_json)}::jsonb, true, true, NOW(), NOW())
        SQL
        id = select_value("SELECT id FROM perfis_acesso WHERE LOWER(nome) = #{quote(nome.downcase)}")
      end

      # Só quem ainda não tem perfil: se o ADM já ajustou alguém à mão entre o
      # deploy e a migration, a escolha dele vence.
      execute("UPDATE users SET perfil_acesso_id = #{id}, updated_at = NOW() " \
              "WHERE role = #{role} AND perfil_acesso_id IS NULL")
    end
  end

  def down
    execute('UPDATE users SET perfil_acesso_id = NULL')
    execute('DELETE FROM perfis_acesso WHERE sistema = true')
  end
end
