# app/services/notificacao/teste_whatsapp.rb
#
# Dispara um WhatsApp de teste para o número administrativo, pelo provedor
# escolhido na tela (QR/Baileys ou Twilio).
#
# No Twilio, traduz o código de erro da API para uma instrução acionável em
# português — os erros de Sandbox (opt-in) são de longe os mais comuns e o
# código cru ("63003") não diz nada para quem está configurando.
module Notificacao
  class TesteWhatsapp
    MENSAGENS = {
      20003 => 'Account SID ou Auth Token inválidos: o Twilio recusou a autenticação.',
      20404 => 'Account SID não encontrado no Twilio. Confira se copiou o SID certo (começa com "AC").',
      21211 => 'Número de destino inválido. Informe com DDD, ex.: 11 92005-1157.',
      21606 => 'O número remetente não é um número Twilio habilitado para envio.',
      21608 => 'Conta trial do Twilio: só é possível enviar para números verificados no console da Twilio.',
      21610 => 'Este número pediu descadastro (enviou STOP). Ele precisa enviar START para voltar a receber.',
      63003 => 'O Twilio não encontrou o destinatário nesse canal. No Sandbox do WhatsApp o número ' \
               'precisa enviar "join <sua-palavra>" para o número do sandbox ANTES de conseguir receber.',
      63007 => 'O número remetente não está habilitado como canal de WhatsApp. Use exatamente o ' \
               'número do Sandbox (ou do Sender aprovado) do Twilio.',
      63015 => 'No Sandbox só dá para enviar a números que fizeram o opt-in ("join <sua-palavra>").',
      63016 => 'Passou da janela de 24h desde a última mensagem do destinatário — nesse caso o Twilio ' \
               'só aceita template aprovado. Peça para ele mandar qualquer mensagem e tente de novo.',
      63018 => 'Limite de mensagens do Twilio atingido. Aguarde e tente novamente.',
      63038 => 'Limite diário de mensagens da conta Twilio atingido.'
    }.freeze

    def initialize(config = ConfiguracaoNotificacao.instancia, destino: nil)
      @config  = config
      @numero  = ConfiguracaoNotificacao.normalizar_telefone(destino.presence || config.whatsapp_admin)
      @destino = @numero && ConfiguracaoNotificacao.canal(@numero)
    end

    def executar
      if @destino.blank?
        return Resultado.falha('Preencha o "WhatsApp do administrador" com DDD ' \
                               '(ex.: 11 92005-1157) antes de testar.')
      end

      @config.baileys? ? via_qr : via_twilio
    end

    private

    # Modo QR: quem responde é a ponte Baileys (container `whatsapp`). Os erros
    # dela já vêm traduzidos pelo ClienteWhatsapp.
    def via_qr
      resposta = ClienteWhatsapp.padrao.enviar(para: @numero, texto: corpo)
      return Resultado.falha(resposta.erro.to_s) unless resposta.ok?

      Resultado.sucesso("WhatsApp de teste enviado para #{@numero} pela ponte QR.")
    end

    def via_twilio
      credenciais = @config.credenciais_whatsapp
      if credenciais.blank?
        return Resultado.falha('Marque "Ativar WhatsApp" e preencha Account SID, Auth Token e o ' \
                               'número remetente do Twilio.')
      end
      if credenciais[:from].blank?
        return Resultado.falha('O número remetente do Twilio está vazio ou em formato inválido.')
      end

      msg = ClienteTwilio
            .montar(credenciais[:sid], credenciais[:token])
            .messages.create(from: credenciais[:from], to: @destino, body: corpo)

      Resultado.sucesso("WhatsApp de teste aceito pelo Twilio para " \
                        "#{@destino.sub('whatsapp:', '')} (SID #{msg.sid}, status \"#{msg.status}\"). " \
                        'Atenção: "queued"/"accepted" significa que a Twilio recebeu — ' \
                        'a entrega final ainda pode falhar depois.')
    rescue Twilio::REST::RestError => e
      Resultado.falha(MENSAGENS[e.code] || "O Twilio recusou o envio (código #{e.code}).",
                      "[#{e.code}] #{e.message}")
    rescue Twilio::REST::TwilioError => e
      Resultado.falha('Não foi possível falar com a API do Twilio (rede ou timeout). ' \
                      'Verifique a saída de internet do servidor.', e.message)
    rescue StandardError => e
      Rails.logger.error("[TesteWhatsapp] #{e.class}: #{e.message}")
      Resultado.falha("Falha inesperada ao enviar (#{e.class}).", e.message)
    end

    def corpo
      "✅ Teste do Reem Notas\n" \
      "Se você recebeu esta mensagem, o envio de WhatsApp está funcionando.\n" \
      "Enviado em #{Time.current.strftime('%d/%m/%Y às %H:%M')}."
    end
  end
end
