require 'rails_helper'

RSpec.describe Contabilidade::LiquidacaoDoControleDePagamento, type: :model do
  it{ is_expected.to belong_to(:liquidacao).required}
	it{ is_expected.to belong_to(:controle_de_pagamento).required}
	it{ is_expected.to belong_to(:conta_destino)}

	it { is_expected.to have_many(:contas_das_liquidacoes_do_controle_de_pagamento) }
	it { is_expected.to have_many(:erros_de_pagamento).dependent(:destroy) }

	it { is_expected.to accept_nested_attributes_for(:contas_das_liquidacoes_do_controle_de_pagamento).allow_destroy(true) }

  describe 'valor_liquido_da_liquidacao' do
    context 'quando a liquidação não possui retenções' do
      it 'retorna 10' do
        liquidacao = Contabilidade::Liquidacao.find_or_create_by!(FactoryBot.attributes_for(:liquidacao_001, valor: 10.00))
        liquidacao_do_controle_de_pagamento = Contabilidade::LiquidacaoDoControleDePagamento.new(liquidacao: liquidacao)
        expect(liquidacao_do_controle_de_pagamento.valor_liquido_da_liquidacao.to_f).to eq 10
      end
    end

    context 'quando a liquidação possui retenções' do
      it 'retorna 8' do
        liquidacao = Contabilidade::Liquidacao.find_or_create_by!(FactoryBot.attributes_for(:liquidacao_001, valor: 10.00))
        liquidacao.retencoes_folha.build(base_de_calculo: 10, aliquota: 20, valor_calculado: 2).save(validate: false)
        liquidacao_do_controle_de_pagamento = Contabilidade::LiquidacaoDoControleDePagamento.new(liquidacao: liquidacao)
        expect(liquidacao_do_controle_de_pagamento.valor_liquido_da_liquidacao.to_f).to eq 8
      end
    end
  end

  describe 'soma_dos_valores_das_contas' do
    context 'quando a liquidação não possui retenções' do
      context 'e o valor total é igual' do
        it 'possuí erro' do
          liquidacao = Contabilidade::Liquidacao.find_or_create_by!(FactoryBot.attributes_for(:liquidacao_001, valor: 10.00))
          liquidacao_do_controle_de_pagamento = Contabilidade::LiquidacaoDoControleDePagamento.new(liquidacao: liquidacao)
          liquidacao_do_controle_de_pagamento.save(validate: false)
          liquidacao_do_controle_de_pagamento.contas_das_liquidacoes_do_controle_de_pagamento.build(valor_da_conta_origem: 10.0).save(validate: false)
          liquidacao_do_controle_de_pagamento.validate
          expect(liquidacao_do_controle_de_pagamento.errors[:valor_da_conta_origem]).to_not include 'O valor colocado nas contas (R$ 10,00) deve ser igual ao valor líquido da liquidação (R$ 10,00)'
        end
      end

      context 'e o valor total é diferente' do
        it 'não possuí erro' do
          liquidacao = Contabilidade::Liquidacao.find_or_create_by!(FactoryBot.attributes_for(:liquidacao_001, valor: 10.00))
          liquidacao_do_controle_de_pagamento = Contabilidade::LiquidacaoDoControleDePagamento.new(liquidacao: liquidacao)
          liquidacao_do_controle_de_pagamento.save(validate: false)
          liquidacao_do_controle_de_pagamento.contas_das_liquidacoes_do_controle_de_pagamento.build(valor_da_conta_origem: 8.0).save(validate: false)
          liquidacao_do_controle_de_pagamento.validate
          expect(liquidacao_do_controle_de_pagamento.errors[:valor_da_conta_origem]).to include 'O valor colocado nas contas (R$ 8,00) deve ser igual ao valor líquido da liquidação (R$ 10,00)'
        end
      end
    end

    context 'quando a liquidação possui retenções' do
      context 'e o valor total é igual' do
        it 'não possuí erro' do
          liquidacao = Contabilidade::Liquidacao.find_or_create_by!(FactoryBot.attributes_for(:liquidacao_001, valor: 10.00))
          liquidacao.retencoes_folha.build(base_de_calculo: 10, aliquota: 20, valor_calculado: 2).save(validate: false)
          liquidacao_do_controle_de_pagamento = Contabilidade::LiquidacaoDoControleDePagamento.new(liquidacao: liquidacao)
          liquidacao_do_controle_de_pagamento.save(validate: false)
          liquidacao_do_controle_de_pagamento.contas_das_liquidacoes_do_controle_de_pagamento.build(valor_da_conta_origem: 8.0).save(validate: false)
          liquidacao_do_controle_de_pagamento.validate

          expect(liquidacao_do_controle_de_pagamento.errors[:valor_da_conta_origem]).to_not include 'O valor colocado nas contas (R$ 8,00) deve ser igual ao valor líquido da liquidação (R$ 8,00)'
        end
      end

      context 'e o valor total é diferente' do
        it 'não possuí erro' do
          liquidacao = Contabilidade::Liquidacao.find_or_create_by!(FactoryBot.attributes_for(:liquidacao_001, valor: 10.00))
          liquidacao.retencoes_folha.build(base_de_calculo: 10, aliquota: 20, valor_calculado: 2).save(validate: false)
          liquidacao_do_controle_de_pagamento = Contabilidade::LiquidacaoDoControleDePagamento.new(liquidacao: liquidacao)
          liquidacao_do_controle_de_pagamento.save(validate: false)
          liquidacao_do_controle_de_pagamento.contas_das_liquidacoes_do_controle_de_pagamento.build(valor_da_conta_origem: 6.0).save(validate: false)
          liquidacao_do_controle_de_pagamento.validate

          expect(liquidacao_do_controle_de_pagamento.errors[:valor_da_conta_origem]).to include 'O valor colocado nas contas (R$ 6,00) deve ser igual ao valor líquido da liquidação (R$ 8,00)'
        end
      end
    end
  end

  describe 'obriga_conta_destino?' do
    context 'quando não possui contas da liquidação e conta de destino não está informada' do
      it 'náo possui erro' do
        liquidacao_do_controle_de_pagamento = Contabilidade::LiquidacaoDoControleDePagamento.new
        liquidacao_do_controle_de_pagamento.validate
        expect(liquidacao_do_controle_de_pagamento.errors[:conta_destino]).to_not include 'É preciso informar a conta destino'
      end
    end

    context 'quando não possui contas da liquidação e conta de destino está informada' do
      it 'náo possui erro' do
        liquidacao_do_controle_de_pagamento = Contabilidade::LiquidacaoDoControleDePagamento.new(conta_destino_id: 1)
        liquidacao_do_controle_de_pagamento.validate
        expect(liquidacao_do_controle_de_pagamento.errors[:conta_destino]).to_not include 'É preciso informar a conta destino'
      end
    end

    context 'quando possui contas da liquidação e conta de destino não está informada' do
      it 'possui erro' do
        liquidacao_do_controle_de_pagamento = Contabilidade::LiquidacaoDoControleDePagamento.new
        liquidacao_do_controle_de_pagamento.contas_das_liquidacoes_do_controle_de_pagamento.build
        liquidacao_do_controle_de_pagamento.validate
        expect(liquidacao_do_controle_de_pagamento.errors[:conta_destino]).to include 'É preciso informar a conta destino'
      end
    end

    context 'quando possui contas da liquidação e conta de destino está informada' do
      it 'náo possui erro' do
        liquidacao_do_controle_de_pagamento = Contabilidade::LiquidacaoDoControleDePagamento.new(conta_destino_id: 1)
        liquidacao_do_controle_de_pagamento.contas_das_liquidacoes_do_controle_de_pagamento.build
        liquidacao_do_controle_de_pagamento.validate
        expect(liquidacao_do_controle_de_pagamento.errors[:conta_destino]).to_not include 'É preciso informar a conta destino'
      end
    end
  end

  describe 'possui_contas?' do
    context 'quando não possui' do
      it 'retorna false' do
        liquidacao_do_controle_de_pagamento = Contabilidade::LiquidacaoDoControleDePagamento.new
        expect(liquidacao_do_controle_de_pagamento.possui_contas?).to eq false
      end
    end

    context 'quando possui' do
      it 'retorna true' do
        liquidacao_do_controle_de_pagamento = Contabilidade::LiquidacaoDoControleDePagamento.new
        liquidacao_do_controle_de_pagamento.contas_das_liquidacoes_do_controle_de_pagamento.build
        expect(liquidacao_do_controle_de_pagamento.possui_contas?).to eq true
      end
    end
  end
end
