require 'rails_helper'

RSpec.describe Base::ContaBancariaPorUnidadeOrcamentaria, type: :model do
	it{ is_expected.to belong_to( :conta_bancaria ) }
	it{ is_expected.to belong_to( :unidade_orcamentaria ).class_name( 'Loa::UnidadeOrcamentaria' ) }
	it{ is_expected.to have_many( :movimentacoes_da_conta_bancaria ).dependent(:restrict_with_exception) }

	it{ is_expected.to validate_presence_of :unidade_orcamentaria_id }

	it{ is_expected.to validate_uniqueness_of( :unidade_orcamentaria_id  ).scoped_to( :conta_bancaria_id ).with_message('já existe para essa conta.') }
	it{ is_expected.to validate_numericality_of(:saldo_atual).is_greater_than_or_equal_to(0).allow_nil }

	describe "#atualiza_saldo" do
		context "quando valor for positivo" do
			it "saldo aumenta" do
				conta_bancaria_por_unidade_orcamentaria = Base::ContaBancariaPorUnidadeOrcamentaria.create!(FactoryBot.attributes_for(:conta_bancaria_por_unidade_orcamentaria))
				conta_bancaria_por_unidade_orcamentaria.atualiza_saldo(2.98)

				expect(conta_bancaria_por_unidade_orcamentaria.saldo_atual.to_f).to eq 12.97
			end
		end

		context "quando valor for negativo" do
			it "saldo diminui" do
				conta_bancaria_por_unidade_orcamentaria = Base::ContaBancariaPorUnidadeOrcamentaria.create!(FactoryBot.attributes_for(:conta_bancaria_por_unidade_orcamentaria))
				conta_bancaria_por_unidade_orcamentaria.atualiza_saldo(-2.98)

				expect(conta_bancaria_por_unidade_orcamentaria.saldo_atual.to_f).to eq 7.01
			end
		end
	end

	it "#definir_como_principal" do
		conta_bancaria_por_unidade_orcamentaria = FactoryBot.create(:conta_bancaria_por_unidade_orcamentaria)
		conta_bancaria_por_unidade_orcamentaria_da_seduc = FactoryBot.create(:conta_bancaria_por_unidade_orcamentaria_da_seduc)
		conta_bancaria_por_unidade_orcamentaria_da_seduc.definir_como_principal

		conta_bancaria_por_unidade_orcamentaria.reload
		conta_bancaria_por_unidade_orcamentaria_da_seduc.reload

		expect(conta_bancaria_por_unidade_orcamentaria.principal).to eq false
		expect(conta_bancaria_por_unidade_orcamentaria_da_seduc.principal).to eq true

		conta_bancaria_por_unidade_orcamentaria.definir_como_principal

		conta_bancaria_por_unidade_orcamentaria.reload
		conta_bancaria_por_unidade_orcamentaria_da_seduc.reload

		expect(conta_bancaria_por_unidade_orcamentaria_da_seduc.principal).to eq false
		expect(conta_bancaria_por_unidade_orcamentaria.principal).to eq true
	end

	describe "#definir_valor_inicial_para_campo_principal" do
		context "ao criar a primeira unidade orçamentaria na conta" do
			it "cadastra como principal" do
				conta_bancaria_por_unidade_orcamentaria = FactoryBot.create(:conta_bancaria_por_unidade_orcamentaria)
				expect(conta_bancaria_por_unidade_orcamentaria.principal).to eq true
			end
		end

		context "caso já exista uma unidade cadastrada na conta" do
			it "não cadastra como principal" do
				conta_bancaria_por_unidade_orcamentaria = FactoryBot.create(:conta_bancaria_por_unidade_orcamentaria)
				conta_bancaria_por_unidade_orcamentaria_da_seduc = FactoryBot.create(:conta_bancaria_por_unidade_orcamentaria_da_seduc)
				expect(conta_bancaria_por_unidade_orcamentaria_da_seduc.principal).to eq false
			end
		end
	end

	describe "#atualizar_valor_para_campo_principal" do
		context "ao excluir uma unidade orcamentária pertencente a uma conta que possua duas unidades orcamentárias, contando a excluida" do
			it "atribui a outra como principal" do
				conta_bancaria_por_unidade_orcamentaria = FactoryBot.create(:conta_bancaria_por_unidade_orcamentaria)
				conta_bancaria_por_unidade_orcamentaria_da_seduc = FactoryBot.create(:conta_bancaria_por_unidade_orcamentaria_da_seduc)
				conta_bancaria_por_unidade_orcamentaria_da_seduc.definir_como_principal
				conta_bancaria_por_unidade_orcamentaria_da_seduc.destroy

				conta_bancaria_por_unidade_orcamentaria.reload
				expect(conta_bancaria_por_unidade_orcamentaria.principal).to eq true
			end
		end
	end

	describe "#valida_se_pode_excluir_de_acordo_com_campo_principal" do
		context "caso seja excluida uma unidade orçamentaria que seja principal pertencente a uma conta que possua mais de duas unidades orçamentarias, contando a excluida" do
			it "lança mensagem de exceção ao excluir" do
				conta_bancaria_por_unidade_orcamentaria = FactoryBot.create(:conta_bancaria_por_unidade_orcamentaria)
				conta_bancaria_por_unidade_orcamentaria_da_seduc = FactoryBot.create(:conta_bancaria_por_unidade_orcamentaria_da_seduc)
				conta_bancaria_por_unidade_orcamentaria_da_fes = FactoryBot.create(:conta_bancaria_por_unidade_orcamentaria_da_fes)
				conta_bancaria_por_unidade_orcamentaria_da_fes.definir_como_principal

				expect { conta_bancaria_por_unidade_orcamentaria_da_fes.destroy }.to raise_error('Defina uma outra unidade gestora como principal para poder excluir.')
			end
		end
	end

	describe "#gerar_movimentacao_para_primeira_unidade_principal" do
		context "ao criar pela primeira vez uma unidade orçamentária principal em uma conta com saldo" do
			it "cria uma nova movimentação para a unidade orçamentária principal" do
				conta_bancaria_por_unidade_orcamentaria = FactoryBot.create(:conta_bancaria_por_unidade_orcamentaria)
				expect(conta_bancaria_por_unidade_orcamentaria.movimentacoes_da_conta_bancaria.count).to eq(1)
			end

 			it "movimenta valor da conta para a unidade orçamentária principal" do
				conta_bancaria_por_unidade_orcamentaria = FactoryBot.create(:conta_bancaria_por_unidade_orcamentaria)
				conta_bancaria_por_unidade_orcamentaria.reload
				expect(conta_bancaria_por_unidade_orcamentaria.saldo_atual).to eq (9.99)
			end
		end
	end

	it "#barra_exclusao_caso_tenha_saldo" do
		conta_bancaria_por_unidade_orcamentaria = FactoryBot.create(:conta_bancaria_por_unidade_orcamentaria)
		conta_bancaria_por_unidade_orcamentaria_da_seduc = FactoryBot.create(:conta_bancaria_por_unidade_orcamentaria_da_seduc)
		conta_bancaria_por_unidade_orcamentaria_da_seduc.saldo_atual = 20

		expect { conta_bancaria_por_unidade_orcamentaria_da_seduc.destroy }.to raise_error('Não é possivel excluir conta com saldo.')
	end
end
