# app/services/notificacao_service.rb
#
# Envia notificações aos motoristas quando uma consolidação é finalizada ou
# quando o pagamento é efetuado.
#
# Canais e credenciais vêm de ConfiguracaoNotificacao (tela /admin/
# configuracao_notificacao), com fallback para o .env.
#
# Falhas de envio NUNCA quebram o fluxo de finalização — apenas logam. Isso é
# intencional: um SMTP fora do ar não pode impedir o fechamento de um pagamento.
# Para DIAGNOSTICAR o envio, use os botões de teste da tela, que usam
# Notificacao::TesteEmail / Notificacao::TesteWhatsapp e mostram o erro real.
class NotificacaoService
  EVENTOS = {
    fechado: { mailer: :pagamento_fechado,
               emoji:  '🚚',
               titulo: 'Seu pagamento de entregas foi fechado.',
               cta:    'Acesse seu painel para baixar o extrato:' },
    pago:    { mailer: :pagamento_efetuado,
               emoji:  '✅',
               titulo: 'Seu pagamento foi efetuado.',
               cta:    'Acesse seu painel para conferir:' }
  }.freeze

  def self.notificar_finalizacao(consolidacao)
    new(consolidacao).notificar_todos
  end

  # Avisa UM motorista de que o pagamento dele foi efetuado.
  def self.notificar_pagamento(consolidacao, consolidacao_motorista)
    new(consolidacao).enviar_aviso_pagamento(consolidacao_motorista)
  end

  def initialize(consolidacao)
    @consolidacao = consolidacao
    @config       = ConfiguracaoNotificacao.instancia
  end

  def notificar_todos
    @consolidacao.consolidacao_motoristas.ativos.each { |cm| notificar(cm, :fechado) }
  end

  def enviar_aviso_pagamento(consolidacao_motorista)
    notificar(consolidacao_motorista, :pago)
  end

  private

  def notificar(cm, evento)
    user = motorista_de(cm)
    return unless user

    enviar_whatsapp(user, cm, evento) if @config.whatsapp_habilitado?
    enviar_email(user, cm, evento)    if @config.email_habilitado? && user.email.present?
  end

  def motorista_de(cm)
    User.motorista.ativos.find_by('LOWER(nome) = ?', cm.motorista_nome.downcase)
  end

  def enviar_whatsapp(user, cm, evento)
    # O telefone no cadastro pode estar como "(11) 92005-1157"; mandar esse
    # texto cru para o Twilio devolve erro 21211 (destino inválido), que o
    # rescue abaixo esconderia. Normalizar para E.164 é o que faz o envio
    # realmente funcionar.
    destino = ConfiguracaoNotificacao.canal(user.telefone)
    return if destino.blank?

    credenciais = @config.credenciais_whatsapp
    return if credenciais.blank? || credenciais[:from].blank?

    Notificacao::ClienteTwilio
      .montar(credenciais[:sid], credenciais[:token])
      .messages.create(from: credenciais[:from], to: destino, body: mensagem(user, cm, evento))

    Rails.logger.info("[Notificacao] WhatsApp (#{evento}) enviado para #{user.nome}")
  rescue StandardError => e
    Rails.logger.error("[Notificacao] Falha WhatsApp (#{evento}) #{user.nome}: #{e.class}: #{e.message}")
  end

  def enviar_email(user, cm, evento)
    ConsolidacaoMailer
      .public_send(EVENTOS.fetch(evento)[:mailer], user, @consolidacao, cm)
      .deliver_later
    Rails.logger.info("[Notificacao] Email (#{evento}) agendado para #{user.email}")
  rescue StandardError => e
    Rails.logger.error("[Notificacao] Falha email (#{evento}) #{user.email}: #{e.class}: #{e.message}")
  end

  def mensagem(user, cm, evento)
    evt = EVENTOS.fetch(evento)
    "Olá #{user.nome.split.first}! #{evt[:emoji]}\n" \
    "#{evt[:titulo]}\n" \
    "📋 #{@consolidacao.nome}\n" \
    "💰 Valor: #{moeda(cm.valor_total)}\n" \
    "#{evt[:cta]} https://#{ENV.fetch('APP_HOST', 'localhost:3000')}/motorista"
  end

  # Moeda BR com separador de milhar: R$ 1.234,56
  def moeda(valor)
    inteiro, decimais = format('%.2f', valor.to_f).split('.')
    inteiro = inteiro.reverse.gsub(/(\d{3})(?=\d)/, '\1.').reverse
    "R$ #{inteiro},#{decimais}"
  end
end
