require 'rails_helper'

RSpec.describe Contato do
  it 'normaliza o telefone digitado para E.164 na gravação' do
    # O ADM digita com máscara; mandar esse texto cru para o provedor devolve
    # erro de destino inválido que o rescue do envio esconderia.
    %w[(11)92005-1157 11920051157 011\ 92005\ 1157 +5511920051157].each do |digitado|
      contato = build(:contato, telefone: digitado)
      expect(contato).to be_valid
      expect(contato.telefone).to eq('+5511920051157')
    end
  end

  it 'exige ao menos um canal' do
    contato = build(:contato, telefone: nil, email: nil)
    expect(contato).not_to be_valid
    expect(contato.errors.full_messages.join).to include('WhatsApp ou um e-mail')
  end

  it 'aceita contato só de e-mail' do
    expect(build(:contato, telefone: nil, email: 'diretoria@reem.com')).to be_valid
  end

  it 'rejeita telefone que não dá para normalizar, devolvendo o valor digitado' do
    contato = build(:contato, telefone: '123')
    expect(contato).not_to be_valid
    expect(contato.errors[:telefone].join).to include('número brasileiro')
    # O ADM precisa ver o que digitou para corrigir.
    expect(contato.telefone).to eq('123')
  end

  describe '.com_canal' do
    let!(:so_zap)   { create(:contato, telefone: '11 92005-1157', email: nil) }
    let!(:so_email) { create(:contato, telefone: nil, email: 'a@b.com') }
    let!(:ambos)    { create(:contato, telefone: '11 93005-1157', email: 'c@d.com') }

    it 'filtra por quem tem o canal' do
      expect(Contato.com_canal('whatsapp')).to contain_exactly(so_zap, ambos)
      expect(Contato.com_canal('email')).to contain_exactly(so_email, ambos)
      expect(Contato.com_canal('ambos')).to contain_exactly(so_zap, so_email, ambos)
    end
  end
end

RSpec.describe Contato, 'grupo do WhatsApp' do
  let(:jid) { '120363012345678901@g.us' }

  def grupo(**extra)
    build(:contato, { tipo: 'grupo_whatsapp', nome: 'Motoristas SP',
                      whatsapp_grupo_jid: jid, telefone: nil }.merge(extra))
  end

  it 'aceita grupo sem telefone nem e-mail' do
    expect(grupo).to be_valid
    expect(grupo.destino_whatsapp).to eq(jid)
  end

  it 'recusa identificador que não é de grupo' do
    contato = grupo(whatsapp_grupo_jid: '5511920051157')
    expect(contato).not_to be_valid
    expect(contato.errors[:whatsapp_grupo_jid].join).to include('@g.us')
  end

  # Cadastro meio pessoa, meio grupo mandaria a mesma mensagem duas vezes.
  it 'limpa telefone e e-mail ao virar grupo' do
    contato = grupo(telefone: '11 92005-1157', email: 'x@y.com')
    contato.validate
    expect(contato.telefone).to be_nil
    expect(contato.email).to be_nil
  end

  it 'limpa o grupo ao voltar a ser pessoa' do
    contato = build(:contato, tipo: 'pessoa', telefone: '11 92005-1157',
                    whatsapp_grupo_jid: jid, whatsapp_grupo_nome: 'Motoristas')
    contato.validate
    expect(contato.whatsapp_grupo_jid).to be_nil
  end

  # Cortar "Motoristas SP" em "Motoristas" no {{contato}} só empobreceria o texto.
  it '{{contato}} usa o nome inteiro do grupo' do
    expect(grupo.primeiro_nome).to eq('Motoristas SP')
    expect(build(:contato, nome: 'Carlos Matheus').primeiro_nome).to eq('Carlos')
  end

  it 'entra no canal whatsapp e fica fora do canal e-mail' do
    salvo = grupo.tap(&:save!)
    expect(Contato.com_canal('whatsapp')).to include(salvo)
    expect(Contato.com_canal('email')).not_to include(salvo)
  end
end
