require 'rails_helper'

RSpec.describe Contabilidade::SolicitacaoDeAlteracaoOrcamentaria, type: :model do
  it{ is_expected.to belong_to(:decreto) }
  it{ is_expected.to belong_to(:projeto) }
  it{ is_expected.to belong_to(:empenho) }
  it{ is_expected.to belong_to(:unidade_orcamentaria) }
  it{ is_expected.to belong_to(:orcamento) }
  it{ is_expected.to belong_to(:fonte_de_recursos) }
  it{ is_expected.to belong_to(:programa_de_governo_da_solicitacao) }


	it{ is_expected.to have_many(:dotacoes_destino).dependent(:destroy) }
	it{ is_expected.to have_many(:dotacoes_origem).dependent(:destroy) }

	[:origem_do_recurso].each { |atributo|
		it { is_expected.to validate_presence_of(atributo) }
	}

	[:tipo_de_credito].each do |atributo|
		before { allow(subject).to receive(:logado_no_administrativo).and_return(true) }

		it { is_expected.to validate_presence_of(atributo) }
	end

	[:tipo_de_credito].each do |atributo|
		before { allow(subject).to receive(:logado_na_alteracao_orcamentaria).and_return(true) }

		it { is_expected.to validate_presence_of(atributo) }
	end

	describe '#possui_dotacoes_de_origem?' do
		context 'tem dotaçõs de origem' do
			it 'retorna true' do
				solicitacao = FactoryBot.create :solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :anulacao_de_dotacao
				dotacao = FactoryBot.create :orcamento_da_despesa_saude
				dotacao_origem = FactoryBot.create :dotacao_origem, dotacao_id:dotacao.id, valor: 349.67, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				solicitacao.reload
				expect(solicitacao.possui_dotacoes_de_origem?).to be_truthy
			end
		end
		context 'não tem dotações de origem' do
			it 'retorna false' do
				solicitacao = FactoryBot.create :solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :anulacao_de_dotacao
				solicitacao.reload
				expect(solicitacao.possui_dotacoes_de_origem?).to be_falsey
			end
		end
	end

	describe '#possui_dotacoes_de_destino?' do
		context 'tem dotaçõs de destino' do
			it 'retorna true' do
				solicitacao = FactoryBot.create :solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :anulacao_de_dotacao
				dotacao = FactoryBot.create :orcamento_da_despesa_saude
				dotacao_destino = FactoryBot.create :dotacao_destino, dotacao_id: dotacao.id, valor: 349.67, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				solicitacao.reload
				expect(solicitacao.possui_dotacoes_de_destino?).to be_truthy
			end
		end
		context 'não tem dotações de destino' do
			it 'retorna false' do
				solicitacao = FactoryBot.create :solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :anulacao_de_dotacao
				solicitacao.reload
				expect(solicitacao.possui_dotacoes_de_destino?).to be_falsey
			end
		end
	end

	describe '#valida_fontes_de_recurso_devem_ser_iguais' do
		context 'Dotações de destino e origem devem ter pelo menos uma fonte de recurso igual' do
			it 'não retorna erro' do
				solicitacao = FactoryBot.create :solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :anulacao_de_dotacao
				dotacao = FactoryBot.create :orcamento_da_despesa_saude
				dotacao_destino = FactoryBot.create :dotacao_destino, dotacao_id: dotacao.id, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				dotacao_origem = FactoryBot.create :dotacao_origem, dotacao_id: dotacao.id, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				solicitacao.reload
				solicitacao.validate
				expect(solicitacao.errors[:na_reducao]).to_not include "pelo menos uma Fonte de Recursos deve ser igual à de Acréscimo."
			end

			it 'retorna erro' do
				solicitacao = FactoryBot.create :solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :anulacao_de_dotacao
				dotacao = FactoryBot.create :orcamento_da_despesa_saude
				fonte_de_recurso = FactoryBot.create :taxas_vinculadas
				segunda_dotacao = FactoryBot.build :orcamento_da_despesa_saude, elemento_de_despesa_por_subacao_id: 2, fonte_de_recursos_id: fonte_de_recurso.id
				segunda_dotacao.save(validate: false)
				dotacao_origem = FactoryBot.create :dotacao_origem, dotacao_id: dotacao.id, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				dotacao_destino = FactoryBot.create :dotacao_destino, dotacao_id: segunda_dotacao.id, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				solicitacao.reload
				solicitacao.validate
				expect(solicitacao.errors[:base]).to include "Na Reduçao pelo menos uma Fonte de Recurso deve ser igual a de Acréscimo."
			end
		end
	end

	describe '#fonte_de_recurso_maior_ou_menor' do
		context 'verifica se dotação' do
			it 'de destino é maior que dotação de origem' do
				solicitacao = FactoryBot.create :solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :anulacao_de_dotacao
				dotacao = FactoryBot.create :orcamento_da_despesa_saude
				dotacao_destino = FactoryBot.create :dotacao_destino, dotacao_id: dotacao.id, valor: 300.00, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				dotacao_origem = FactoryBot.create :dotacao_origem, dotacao_id: dotacao.id, valor: 200.00, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				solicitacao.reload
				solicitacao.validate
				expect(solicitacao.fonte_de_recurso_maior_ou_menor).to include 'destino_maior'
			end
			it 'de origem é maior que dotação de destino' do
				solicitacao = FactoryBot.create :solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :anulacao_de_dotacao
				dotacao = FactoryBot.create :orcamento_da_despesa_saude
				dotacao_destino = FactoryBot.create :dotacao_destino, dotacao_id: dotacao.id, valor: 200.00, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				dotacao_origem = FactoryBot.create :dotacao_origem, dotacao_id: dotacao.id, valor: 300.00, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				solicitacao.reload
				solicitacao.validate
				expect(solicitacao.fonte_de_recurso_maior_ou_menor).to include 'origem_maior'
			end
			it 'tem destino maior que origem e origem maior que destino' do
				solicitacao = FactoryBot.create :solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :anulacao_de_dotacao
				dotacao = FactoryBot.create :orcamento_da_despesa_saude

				dotacao_destino = FactoryBot.create :dotacao_destino, dotacao_id: dotacao.id, valor: 654.00, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				dotacao_origem = FactoryBot.create :dotacao_origem, dotacao_id: dotacao.id, valor: 950.00, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				segunda_dotacao_destino = FactoryBot.create :dotacao_destino, dotacao_id: dotacao.id, valor: 950.00, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				segunda_dotacao_origem = FactoryBot.create :dotacao_origem, dotacao_id: dotacao.id, valor: 654.00, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id

				solicitacao.reload
				solicitacao.validate

				expect(solicitacao.fonte_de_recurso_maior_ou_menor).to be_falsey
			end
		end
	end

	describe '#valor_dotacao_destino_menor_que_zero' do
		context 'valida se a dotação de destino' do
			it 'retorna erro' do
				solicitacao = FactoryBot.create :solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :anulacao_de_dotacao
				dotacao = FactoryBot.create :orcamento_da_despesa_saude
				dotacao_destino = FactoryBot.create :dotacao_destino, dotacao_id: dotacao.id, valor: 0, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				dotacao_origem = FactoryBot.create :dotacao_origem, dotacao_id: dotacao.id, valor: 340.67, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				solicitacao.reload
        solicitacao.validate
				expect(solicitacao.errors[:base]).to include 'O valor da dotação de Acréscimo não pode ser zero.'
			end
			it 'não retorna erro' do
				solicitacao = FactoryBot.create :solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :anulacao_de_dotacao
				dotacao = FactoryBot.create :orcamento_da_despesa_saude
				dotacao_destino = FactoryBot.create :dotacao_destino, dotacao_id: dotacao.id, valor: 349.67, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				dotacao_origem = FactoryBot.create :dotacao_origem, dotacao_id: dotacao.id, valor: 340.67, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				solicitacao.reload
        solicitacao.validate
				expect(solicitacao.errors[:base]).to_not include 'O valor da dotação de Acréscimo não pode ser zero.'
			end
		end
	end

	describe '#valores_das_dotacoes_sao_diferentes?' do
		context 'Dotações possuem valor diferente' do
			it 'retorna true' do
				solicitacao = FactoryBot.create :solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :anulacao_de_dotacao
				dotacao = FactoryBot.create :orcamento_da_despesa_saude
				dotacao_destino = FactoryBot.create :dotacao_destino, dotacao_id: dotacao.id, valor: 349.67, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				dotacao_origem = FactoryBot.create :dotacao_origem, dotacao_id: dotacao.id, valor: 340.67, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				solicitacao.reload
				expect(solicitacao.valores_das_dotacoes_sao_diferentes?).to be_truthy
			end
		end
		context 'Dotações tem o mesmo valor' do
			it 'retorna false' do
				solicitacao = FactoryBot.create :solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :anulacao_de_dotacao
				dotacao = FactoryBot.create :orcamento_da_despesa_saude
				dotacao_destino = FactoryBot.create :dotacao_destino, dotacao_id: dotacao.id, valor: 349.67, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				dotacao_origem = FactoryBot.create :dotacao_origem, dotacao_id: dotacao.id, valor: 349.67, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id
				solicitacao.reload
				expect(solicitacao.valores_das_dotacoes_sao_diferentes?).to be_falsey
			end
		end
	end


	describe '#valida_valor_dotacoes_origem' do
		context 'quando a dotação não possui saldo' do
			it 'retorna erro ao salvar' do
				solicitacao = FactoryBot.create(:solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :anulacao_de_dotacao, skip_validate_valida_valor_dotacoes_origem: false)
				dotacao = FactoryBot.create(:orcamento_da_despesa_saude, valor: 1000)
				dotacao_origem = FactoryBot.create(:dotacao_origem, dotacao_id: dotacao.id, valor: 1500, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id)
				solicitacao.reload
        solicitacao.validate
				# expect(solicitacao.valid?).to be false
				expect(solicitacao.errors[:dotacoes]).to include(dotacao_origem.orcamento_da_despesa)
			end
		end
		context 'quando a dotação possui saldo disponível' do
			it 'deixa salvar sem erros' do
				solicitacao = FactoryBot.create(:solicitacao_de_alteracao_orcamentaria, origem_do_recurso: :outros)
				dotacao = FactoryBot.create(:orcamento_da_despesa_saude, valor: 1000)
				dotacao_origem = FactoryBot.create(:dotacao_origem, dotacao_id: dotacao.id, valor: 500, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id)
				solicitacao.reload
				solicitacao.validate
				expect(solicitacao.errors[:dotacoes]).to_not include(dotacao_origem.orcamento_da_despesa)
			end
		end
	end

	describe '#enviado_para_o_sim' do
		context "Quando foi enviado" do
			it "Retorna true quando ambos os tipos de dotações foram enviadas ao sim" do
				solicitacao = FactoryBot.create(:solicitacao_de_alteracao_orcamentaria, :com_dotacao_origem_e_destino)
				solicitacao.reload
				solicitacao.update_attribute(:status, "confirmado")

				solicitacao.dotacoes_origem.last.update_attribute(:arquivo_id, 1)

				expect(solicitacao.enviado_para_o_sim?).to be_truthy
			end
		end
		context "Quando não foi enviado" do
			it "Retorna false quando dotação destino não foi enviada ao sim" do
				solicitacao = FactoryBot.create(:solicitacao_de_alteracao_orcamentaria, :com_dotacao_origem_e_destino)
				solicitacao.reload
				solicitacao.update_attribute(:status, "confirmado")

				solicitacao.dotacoes_origem.last.update_attribute(:arquivo_id, 1)
				solicitacao.dotacoes_destino.last.update_attribute(:arquivo_id, 1)

				expect(solicitacao.enviado_para_o_sim?).to be_falsey
			end
			it "Retorna false quando dotação origem não foi enviada ao sim" do
				solicitacao = FactoryBot.create(:solicitacao_de_alteracao_orcamentaria, :com_dotacao_origem_e_destino)
				solicitacao.reload
				solicitacao.update_attribute(:status, "confirmado")

				expect(solicitacao.enviado_para_o_sim?).to be_falsey
			end
			it "Retorna false quando não tem status confirmado" do
				solicitacao = FactoryBot.create(:solicitacao_de_alteracao_orcamentaria, :com_dotacao_origem_e_destino)
				solicitacao.reload
				solicitacao.update_attribute(:status, "solicitado")

				solicitacao.dotacoes_origem.last.update_attribute(:arquivo_id, 1)

				expect(solicitacao.enviado_para_o_sim?).to be_falsey
			end
		end
	end

	describe "dotacoes_origem_enviada_ao_sim" do
		context "Quando foi enviada" do
			it "Retorna true" do
				solicitacao = FactoryBot.create(:solicitacao_de_alteracao_orcamentaria)
				FactoryBot.create(:dotacao_origem, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id, arquivo_id: 1)

				expect(solicitacao.reload.dotacoes_origem_enviada_ao_sim?).to be_truthy
			end
		end
		context "Quado não foi enviada" do
			it "Retorna false quando não tem dotação de origem" do
				solicitacao = FactoryBot.create(:solicitacao_de_alteracao_orcamentaria)

				expect(solicitacao.reload.dotacoes_origem_enviada_ao_sim?).to be_falsey
			end
			it "Retorna false quando a dotação não foi enviada ao sim" do
				solicitacao = FactoryBot.create(:solicitacao_de_alteracao_orcamentaria)
				FactoryBot.create(:dotacao_origem, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id, arquivo_id: nil)

				expect(solicitacao.reload.dotacoes_origem_enviada_ao_sim?).to be_falsey
			end
		end
	end

	describe "dotacoes_destino_enviada_ao_sim" do
		context "Quando foi enviada" do
			it "Retorna true" do
				solicitacao = FactoryBot.create(:solicitacao_de_alteracao_orcamentaria)
				FactoryBot.create(:dotacao_destino, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id)

				expect(solicitacao.reload.dotacoes_destino_enviada_ao_sim?).to be_truthy
			end
		end
		context "Quado não foi enviada" do
			it "Retorna false quando não tem dotação de origem" do
				solicitacao = FactoryBot.create(:solicitacao_de_alteracao_orcamentaria)

				expect(solicitacao.reload.dotacoes_destino_enviada_ao_sim?).to be_falsey
			end
			it "Retorna false quando a dotação não foi enviada ao sim" do
				solicitacao = FactoryBot.create(:solicitacao_de_alteracao_orcamentaria)
				FactoryBot.create(:dotacao_destino, solicitacao_de_alteracao_orcamentaria_id: solicitacao.id, arquivo_id: 1)

				expect(solicitacao.reload.dotacoes_destino_enviada_ao_sim?).to be_falsey
			end
		end
	end
end
