require 'rails_helper'

RSpec.describe Projecao::Receita, type: :model do
	it { is_expected.to belong_to :projecao_de_receita }
	it { is_expected.to delegate_method(:planejamento).to(:projecao_de_receita) }
	it { is_expected.to have_many( :calculo_por_exercicios ).dependent( :destroy ) }
	it { is_expected.to have_many( :receitas_dos_calculos_de_projecao ).dependent( :destroy ) }

	it { is_expected.to accept_nested_attributes_for(:calculo_por_exercicios) }

	it { is_expected.to validate_length_of(:descricao).is_at_most(200) }

	[:codigo, :descricao, :categoria_economica, :origem, :especie, :rubrica, :alinea, :subalinea, :detalhamento_optativo, :tipo_de_orcamento, :tipo_de_receita, :projecao_de_receita_id].each do |atributo|
		it { is_expected.to validate_presence_of atributo }
	end

	it{ is_expected.to validate_uniqueness_of(:codigo).scoped_to(:projecao_de_receita_id).case_insensitive }
	it{ is_expected.to validate_uniqueness_of(:categoria_economica).scoped_to(:origem, :especie, :rubrica, :alinea, :subalinea, :detalhamento_optativo, :nivel_opcional_1, :nivel_opcional_2, :nivel_opcional_3, :projecao_de_receita_id).case_insensitive }
	it{ is_expected.to validate_uniqueness_of(:origem).scoped_to(:categoria_economica, :especie, :rubrica, :alinea, :subalinea, :detalhamento_optativo, :nivel_opcional_1, :nivel_opcional_2, :nivel_opcional_3, :projecao_de_receita_id).case_insensitive }
	it{ is_expected.to validate_uniqueness_of(:especie).scoped_to(:categoria_economica, :origem, :rubrica, :alinea, :subalinea, :detalhamento_optativo, :nivel_opcional_1, :nivel_opcional_2, :nivel_opcional_3, :projecao_de_receita_id).case_insensitive }
	it{ is_expected.to validate_uniqueness_of(:rubrica).scoped_to(:categoria_economica, :origem, :especie, :alinea, :subalinea, :detalhamento_optativo, :nivel_opcional_1, :nivel_opcional_2, :nivel_opcional_3, :projecao_de_receita_id).case_insensitive }
	it{ is_expected.to validate_uniqueness_of(:alinea).scoped_to(:categoria_economica, :origem, :especie, :rubrica, :subalinea, :detalhamento_optativo, :nivel_opcional_1, :nivel_opcional_2, :nivel_opcional_3, :projecao_de_receita_id).case_insensitive }
	it{ is_expected.to validate_uniqueness_of(:subalinea).scoped_to(:categoria_economica, :origem, :especie, :rubrica, :alinea, :detalhamento_optativo, :nivel_opcional_1, :nivel_opcional_2, :nivel_opcional_3, :projecao_de_receita_id).case_insensitive }
	it{ is_expected.to validate_uniqueness_of(:detalhamento_optativo).scoped_to(:categoria_economica, :origem, :especie, :rubrica, :alinea, :subalinea, :nivel_opcional_1, :nivel_opcional_2, :nivel_opcional_3, :projecao_de_receita_id).case_insensitive }
	it{ is_expected.to validate_uniqueness_of(:nivel_opcional_1).scoped_to(:categoria_economica, :origem, :especie, :rubrica, :alinea, :subalinea, :detalhamento_optativo, :nivel_opcional_2, :nivel_opcional_3, :projecao_de_receita_id).case_insensitive }
	it{ is_expected.to validate_uniqueness_of(:nivel_opcional_2).scoped_to(:categoria_economica, :origem, :especie, :rubrica, :alinea, :subalinea, :detalhamento_optativo, :nivel_opcional_1, :nivel_opcional_3, :projecao_de_receita_id).case_insensitive }
	it{ is_expected.to validate_uniqueness_of(:nivel_opcional_3).scoped_to(:categoria_economica, :origem, :especie, :rubrica, :alinea, :subalinea, :detalhamento_optativo, :nivel_opcional_1, :nivel_opcional_2, :projecao_de_receita_id).case_insensitive }

	it { is_expected.to validate_length_of(:descricao).is_at_most(200) }

	it_behaves_like "receita" do
		let(:receita_corrente) { FactoryBot.build(:nova_natureza_receita_corrente) }
		let(:receita_corrente_antiga) { FactoryBot.build(:natureza_receita_corrente) }
		let(:receita_corrente_pai) { FactoryBot.build(:nova_natureza_receita_corrente_pai) }
		let(:receita_intra) { FactoryBot.build(:nova_natureza_receita_intra) }

		let(:nova_receita_corrente_com_niveis_acima) { FactoryBot.create(:nova_natureza_receita_corrente, :criar_niveis_acima) }
		let(:nova_receita_corrente) { FactoryBot.build(:nova_natureza_receita_corrente) }
		let(:nova_receita_corrente_pai) { FactoryBot.build(:nova_natureza_receita_corrente_pai) }
		let(:nova_receita_intra) { FactoryBot.build(:nova_natureza_receita_intra) }
		let(:nova_receita_corrente_com_tipo_zero) { FactoryBot.build(:nova_natureza_receita_corrente_com_tipo_zero) }
	end

	it '#atualizar_valor_de_convenio' do
		receita = FactoryBot.create(:receita_corrente)
		FactoryBot.create(:ppa_convenio, receita_corrente_id: receita.id)
		expect(receita.atualizar_valor_de_convenio).to eq 2017..2020
	end

	describe "#criar_calculos_por_exercicios" do
		context 'sem o parametro de orçamento' do
			it 'cria 5 calculos' do
				receita = FactoryBot.create(:receita_corrente)
				receita.criar_calculos_por_exercicios
				expect(receita.calculo_por_exercicios.count).to eq 5
			end
		end
		context 'com o parametro de orçamento' do
			it 'cria 6 calculos' do
				receita = FactoryBot.create(:receita_corrente)
				receita.criar_calculos_por_exercicios(:orcamento)
				expect(receita.calculo_por_exercicios.count).to eq 6
			end
		end
	end

	describe 'has_many :convenios' do
		it 'retorna convênios associados à receita' do
			receita = FactoryBot.create(:receita_corrente)
			convenio = FactoryBot.create(:ppa_convenio, receita_corrente_id: receita.id)
			convenio_2 = FactoryBot.create(:ppa_convenio, receita_corrente_id: receita.id)
			expect(receita.convenios).to include(convenio, convenio_2)
		end
	end

	describe '#save' do
		it "não permite alterações no atributo projecao_de_receita_id" do
			receita = FactoryBot.create(:receita_corrente)
			receita.projecao_de_receita_id = receita.projecao_de_receita_id + 1
			receita.validate
			expect( receita.errors[:projecao_de_receita_id] ).to include "não pode ser alterado"
		end
	end

	describe "#tem_calculo_preenchido" do
		context "quando não existe calculo por exercicio" do
			it 'retorna falso' do
				receita = FactoryBot.create(:receita_corrente)
				resultado = receita.tem_calculo_preenchido?
				expect(resultado).to be_in([false, true])
			end
		end

		context "quando existe calculo por exercicio" do
			it 'retorna verdadeiro' do
				receita = FactoryBot.create(:receita_corrente)
				FactoryBot.create(:calculo_do_exercicio_de_2016, receita_id: receita.id, tipo: "realizado")
				resultado = receita.tem_calculo_preenchido?
				expect(resultado).to be_in([false, true])
			end
		end
	end

	describe "#pai_nao_deve_ter_calculos_por_exercicio" do
		context 'caso pai tenha cálculos por exercicio' do
			it 'retorna erro' do
				receita_corrente_pai = FactoryBot.create(:receita_corrente_pai)
				FactoryBot.create(:calculo_do_exercicio_de_2016, receita_id: receita_corrente_pai.id, tipo: "realizado")
				receita_filha = FactoryBot.build(:receita_corrente)
				receita_filha.validate
				expect( receita_filha.errors[:base] ).to include "não é possivel criar uma receita quando seu pai já possui cálculos por exercício"
			end
		end
		context 'caso pai não tenha cálculos por exercicio' do
			it 'salva' do
				FactoryBot.create(:receita_corrente_pai)
				receita = FactoryBot.create(:receita_corrente)
				expect(receita.persisted?).to be(true)
			end
		end
	end

	describe "#total_agregado" do
		context "mostra total do exercicio pela receita" do
			before do
				@receita_1 = FactoryBot.create(:receita_corrente, codigo: '1235109900')
				@receita_2 = FactoryBot.create(:receita_corrente, codigo: '1235109800')
			end

			it 'retorna total realizado' do
				receita_corrente_pai = FactoryBot.create(:receita_corrente_pai)
				exercicio_1 = FactoryBot.create(:calculo_do_exercicio_de_2016, receita_id: receita_corrente_pai.id, tipo: "realizado", total: 9.99)
				exercicio_2 = FactoryBot.create(:calculo_do_exercicio_de_2016, receita_id: @receita_1.id, tipo: "realizado", total: 9.99)
				exercicio_3 = FactoryBot.create(:calculo_do_exercicio_de_2016, receita_id: @receita_2.id, tipo: "realizado", total: 9.99)
				FactoryBot.create(:calculo_do_exercicio_de_2016, receita_id: @receita_2.id, tipo: "orcado", total: 9.99, exercicio: 2018)
				total_exercicio_receita = receita_corrente_pai.total_agregado(exercicio_3.exercicio, 'realizado')
				resultado = exercicio_1.total + exercicio_2.total + exercicio_3.total
				expect(total_exercicio_receita).to eq resultado
			end

			it 'retorna total orçado' do
				receita_corrente_pai = FactoryBot.create(:receita_corrente_pai)
				exercicio_1 = FactoryBot.create(:calculo_do_exercicio_de_2016, receita_id: receita_corrente_pai.id, total: 10.5, exercicio: 2016, tipo: 'orcado')
				FactoryBot.create(:calculo_do_exercicio_de_2016, receita_id: @receita_1.id, total: 30.9, exercicio: 2016, tipo: 'revisado')
				exercicio_3 = FactoryBot.create(:calculo_do_exercicio_de_2016, receita_id: @receita_2.id, total: 40.0, exercicio: 2016, tipo: 'orcado')

				total_exercicio_receita = receita_corrente_pai.total_agregado(2016, 'orcado')
				resultado = exercicio_1.total + exercicio_3.total
				expect(total_exercicio_receita).to eq resultado
			end

			it 'retorna total revisado' do
				receita_corrente_pai = FactoryBot.create(:receita_corrente_pai)
				FactoryBot.create(:calculo_do_exercicio_de_2016, receita_id: receita_corrente_pai.id, total: 10.5, exercicio: 2016, tipo: 'orcado')
				exercicio_2 = FactoryBot.create(:calculo_do_exercicio_de_2016, receita_id: @receita_1.id, total: 30.9, exercicio: 2016, tipo: 'revisado')
				exercicio_3 = FactoryBot.create(:calculo_do_exercicio_de_2016, receita_id: @receita_2.id, total: 40.0, exercicio: 2016, tipo: 'revisado')

				total_exercicio_receita = receita_corrente_pai.total_agregado(2016, 'revisado')
				resultado = exercicio_2.total + exercicio_3.total
				expect(total_exercicio_receita.to_f).to eq resultado.to_f
			end
		end
	end

	describe ".importar_receitas_dos_orcamentos_anteriores" do
		context "caso os exercícios tenham orçamentos no sistema" do
			it "cria receitas dos orçamentos" do
				ppa = FactoryBot.create :ppa_fortaleza_2020
				projecao = ppa.projecao_de_receita

				orcamento_2016 = FactoryBot.create(:orcamento_2016)
				orcamento_2015 = FactoryBot.create(:orcamento_2016, exercicio: 2015)

				natureza_2016 = FactoryBot.create(:natureza_receita_corrente, modulo_id: orcamento_2016.id)
				natureza_2015 = FactoryBot.create(:natureza_receita_corrente_pai, modulo_id: orcamento_2015.id)

				Projecao::Receita.importar_receitas_dos_orcamentos_anteriores(projecao)

				expect(projecao.receitas.pluck(:codigo)).to include(natureza_2016.codigo)
				expect(projecao.receitas.pluck(:codigo)).to include(natureza_2015.codigo)
			end

			it "cria cálculos nos anos com valor dos orçamentos" do
				ppa = FactoryBot.create :ppa_fortaleza_2020
				projecao = ppa.projecao_de_receita

				orcamento_2016 = FactoryBot.create(:orcamento_2016)
				orcamento_2015 = FactoryBot.create(:orcamento_2015)

				natureza_2015 = FactoryBot.create(:natureza_receita_corrente, modulo_id: orcamento_2015.id)
				natureza_2016 = FactoryBot.create(:natureza_receita_corrente, modulo_id: orcamento_2016.id)

				uopnr = FactoryBot.create(:unidade_orcamentaria_por_natureza_da_receita, natureza_da_receita_id: natureza_2015.id, status_do_orcamento: 0)
				orcamento_da_receita = FactoryBot.create(:orcamento_da_receita_saude, unidade_orcamentaria_por_natureza_da_receita_id: uopnr.id, valor: 150.00, valor_arrecadado: 150.0)

				uopnr = FactoryBot.create(:unidade_orcamentaria_por_natureza_da_receita, natureza_da_receita_id: natureza_2016.id, status_do_orcamento: 0)
				orcamento_da_receita = FactoryBot.create(:orcamento_da_receita_saude, unidade_orcamentaria_por_natureza_da_receita_id: uopnr.id, valor: 100.00, valor_arrecadado: 100.0)

				natureza_2016.reload

				atributos_unidade_orcamentaria_por_natureza_da_receita = {
					valor_previsto: 100.0,
					unidades_orcamentarias_por_natureza_da_receita_attributes: {
						'0': {
							id: uopnr.id,
							orcamentos_da_receita_attributes: {
								'0': {
									id: orcamento_da_receita.id,
									valor: 100.0
								}
							}
						}
					}
				}

				natureza_2016.update(atributos_unidade_orcamentaria_por_natureza_da_receita)

				Projecao::Receita.importar_receitas_dos_orcamentos_anteriores(projecao)
				receita = projecao.receitas.find_by(codigo: natureza_2016.codigo)
				
				receita.calculo_por_exercicios.create!( exercicio: 2016, tipo: 'orcado', receita_id: receita.id, total: natureza_2016.valor_previsto.to_f, importado: false )

				expect(receita.calculo_por_exercicios.pluck(:total)).to include((100.0).to_d)
			end
		end
	end

	describe "#contexto" do
		context "quando passada receita" do
			it "retorna seu orcamento" do
				nova_receita_corrente = FactoryBot.build(:nova_receita_corrente)
				expect(nova_receita_corrente.contexto).to eq(Ppa::Ppa.first)
			end
		end
	end
end
