require 'rails_helper'

RSpec.describe 'Admin::ConfiguracaoNotificacoes', type: :request do
  let(:config) { ConfiguracaoNotificacao.instancia }

  def patch_config(atributos, acao: 'salvar')
    patch admin_configuracao_notificacao_path,
          params: { acao: acao, configuracao_notificacao: atributos }
  end

  describe 'permissão' do
    it 'exige login' do
      get admin_configuracao_notificacao_path
      expect(response).to redirect_to(new_user_session_path)
    end

    it 'bloqueia gerente (só admin mexe em credenciais de envio)' do
      sign_in create(:gerente)
      get admin_configuracao_notificacao_path

      expect(response).to redirect_to(root_path)
      expect(flash[:alert]).to match(/permissão/i)
    end

    it 'bloqueia gerente também no update' do
      sign_in create(:gerente)
      patch_config(smtp_address: 'smtp.invasor.com')

      expect(response).to redirect_to(root_path)
      expect(config.reload.smtp_address).not_to eq('smtp.invasor.com')
    end

    it 'libera admin' do
      sign_in create(:admin)
      get admin_configuracao_notificacao_path
      expect(response).to have_http_status(:ok)
    end
  end

  context 'como admin' do
    let(:admin) { create(:admin) }

    before { sign_in admin }

    it 'salva as configurações' do
      patch_config(smtp_address: 'smtp.gmail.com', smtp_port: 465,
                   email_admin: 'Chefe@Reem.com.br', whatsapp_admin: '(11) 92005-1157')

      expect(response).to redirect_to(admin_configuracao_notificacao_path)
      config.reload
      expect(config.smtp_address).to eq('smtp.gmail.com')
      expect(config.smtp_port).to eq(465)
      expect(config.email_admin).to eq('chefe@reem.com.br')
      expect(config.whatsapp_admin).to eq('+5511920051157')
    end

    it 'mantém a senha gravada quando o campo vem em branco' do
      config.update!(smtp_password: 'senha-original')

      patch_config(smtp_address: 'smtp.outro.com', smtp_password: '')

      expect(config.reload.smtp_password).to eq('senha-original')
    end

    it 'substitui a senha quando o campo é preenchido' do
      config.update!(smtp_password: 'senha-original')

      patch_config(smtp_password: 'senha-nova')

      expect(config.reload.smtp_password).to eq('senha-nova')
    end

    it 'reexibe o formulário quando ativa o e-mail sem credenciais' do
      patch_config(smtp_ativo: '1', smtp_address: '', smtp_username: '')

      expect(response).to have_http_status(:unprocessable_entity)
      expect(config.reload.smtp_ativo).to be(false)
    end

    it 'registra auditoria sem vazar a senha nem o token' do
      patch_config(smtp_address: 'smtp.gmail.com', smtp_password: 'super-secreta',
                   twilio_auth_token: 'token-secreto')

      log = AuditoriaLog.where(entidade: 'ConfiguracaoNotificacao').last
      expect(log.acao).to eq('editar_notificacoes')
      expect(log.user_id).to eq(admin.id)

      serializado = [log.dados_anteriores, log.dados_novos].to_json
      expect(serializado).not_to include('super-secreta')
      expect(serializado).not_to include('token-secreto')
      expect(log.dados_novos['smtp_password_definida']).to be(true)
    end

    describe 'botões de teste' do
      it 'avisa quando o e-mail administrativo não foi preenchido' do
        patch_config({ email_admin: '' }, acao: 'testar_email')

        expect(response).to redirect_to(admin_configuracao_notificacao_path)
        expect(flash[:alert]).to match(/E-mail do administrador/i)
      end

      it 'avisa quando o SMTP não está pronto' do
        patch_config({ email_admin: 'chefe@reem.com.br' }, acao: 'testar_email')

        expect(flash[:alert]).to match(/Ativar envio de e-mail/i)
      end

      it 'envia o e-mail de teste quando o SMTP está configurado' do
        resultado = Notificacao::Resultado.sucesso('E-mail de teste enviado.')
        expect(Notificacao::TesteEmail).to receive(:new).and_return(double(executar: resultado))

        patch_config({ email_admin: 'chefe@reem.com.br' }, acao: 'testar_email')

        expect(flash[:notice]).to eq('E-mail de teste enviado.')
      end

      it 'avisa quando o WhatsApp administrativo não foi preenchido' do
        patch_config({ whatsapp_admin: '' }, acao: 'testar_whatsapp')

        expect(flash[:alert]).to match(/WhatsApp do administrador/i)
      end

      it 'reporta o erro traduzido do Twilio no flash' do
        resultado = Notificacao::Resultado.falha('Sandbox exige opt-in.', '[63015] detalhe')
        expect(Notificacao::TesteWhatsapp).to receive(:new).and_return(double(executar: resultado))

        patch_config({ whatsapp_admin: '11 920051157' }, acao: 'testar_whatsapp')

        expect(flash[:alert]).to include('Sandbox exige opt-in.')
        expect(flash[:alert]).to include('63015')
      end
    end
  end
end
