# app/controllers/admin/perfis_acesso_controller.rb
#
# CRUD dos perfis de acesso. É aqui que o ADM decide o que cada função enxerga,
# sem depender de deploy: o catálogo do que pode ser marcado é código
# (Permissao::TODAS), a escolha é dado (PerfilAcesso#permissoes).
module Admin
  class PerfisAcessoController < ApplicationController
    include Auditavel

    before_action :set_perfil, only: %i[edit update destroy]

    def index
      authorize PerfilAcesso
      @perfis = policy_scope(PerfilAcesso).ordenados.includes(:users)
    end

    def new
      @perfil = PerfilAcesso.new(ativo: true, permissoes: [])
      authorize @perfil
    end

    def create
      @perfil = PerfilAcesso.new(perfil_params)
      authorize @perfil

      if @perfil.save
        auditar!(:criar, @perfil, dados_novos: { nome: @perfil.nome, permissoes: @perfil.permissoes })
        redirect_to admin_perfis_path, notice: "Perfil #{@perfil.nome} criado."
      else
        render :new, status: :unprocessable_entity
      end
    end

    def edit; end

    def update
      anteriores = @perfil.permissoes

      # Ordem importa: aplicamos os valores em memória para a trava conferir o
      # que o ADM ESTÁ salvando, não o que está no banco.
      @perfil.assign_attributes(perfil_params)

      if travaria_o_sistema?
        @perfil.errors.add(:base, mensagem_da_trava)
        return render(:edit, status: :unprocessable_entity)
      end

      if @perfil.save
        auditar!(:editar, @perfil,
                 dados_anteriores: { permissoes: anteriores },
                 dados_novos:      { permissoes: @perfil.permissoes, ativo: @perfil.ativo })
        redirect_to admin_perfis_path, notice: "Perfil #{@perfil.nome} atualizado."
      else
        render :edit, status: :unprocessable_entity
      end
    end

    def destroy
      unless @perfil.apagavel?
        return redirect_to(admin_perfis_path, alert: motivo_para_nao_apagar)
      end

      @perfil.destroy
      auditar!(:excluir, @perfil, dados_anteriores: { nome: @perfil.nome })
      redirect_to admin_perfis_path, notice: 'Perfil excluído.'
    end

    private

    def set_perfil
      @perfil = PerfilAcesso.find(params[:id])
      authorize @perfil
    end

    def perfil_params
      dados = params.require(:perfil_acesso).permit(:nome, :descricao, :ativo, permissoes: [])
      # O form manda um campo vazio para o caso de NENHUMA caixa marcada (senão o
      # parâmetro some e "desmarcar tudo" viraria "não mexer em nada").
      dados[:permissoes] = Permissao.filtrar(dados[:permissoes])
      dados
    end

    # ── Trava do último administrador ────────────────────────
    # Mesma regra da tela de usuários (User.administradores_de_acesso): salvar um
    # perfil que perde `admin.perfis`/`admin.usuarios_gerenciar` (ou é desativado)
    # não pode deixar o sistema sem quem conserte.
    def travaria_o_sistema?
      return false if @perfil.administra_acesso?       # continua podendo: nada a checar
      return false unless @perfil.users.ativos.exists? # perfil vazio não tira acesso de ninguém

      # Quem está NESTE perfil perderá o acesso; sobra alguém fora dele?
      # Usuário sem perfil conta: cai no padrão do papel (admin legado administra).
      restantes = User.administradores_de_acesso.reject { |u| u.perfil_acesso_id == @perfil.id }
      restantes.empty?
    end

    def mensagem_da_trava
      'Esta alteração deixaria o sistema sem nenhum usuário ativo capaz de gerenciar ' \
        'perfis e usuários. Garanta que outra pessoa mantenha esse acesso antes de salvar.'
    end

    def motivo_para_nao_apagar
      if @perfil.sistema?
        'Perfis que vêm com o sistema não podem ser excluídos — desative-o ou edite as permissões.'
      else
        "Este perfil está em uso por #{@perfil.users.count} usuário(s). Mova essas pessoas para outro perfil antes de excluir."
      end
    end
  end
end
