require 'rails_helper'

RSpec.describe Base::GrupoDeNaturezaDaDespesa, type: :model do
	it{ is_expected.to belong_to :categoria_economica }

	it { is_expected.to have_many :modalidades_de_aplicacao }
	it{ is_expected.to have_many(:elementos_de_despesa).through(:modalidades_de_aplicacao) }

	it{ is_expected.to validate_presence_of :codigo }
	it{ is_expected.to validate_presence_of :descricao }

	it{ is_expected.to validate_uniqueness_of(:codigo).scoped_to(:categoria_economica_id) }
	it{ is_expected.to validate_uniqueness_of(:descricao).scoped_to(:categoria_economica_id) }

	# describe "#save" do
	# 	context "quando código ou descrição não estão contigos no seed base de naturezas da despesa'" do
	# 		it "adiciona erros nos atributos" do
	# 			grupo_de_natureza_da_despesa = Base::GrupoDeNaturezaDaDespesa.new( codigo: 'A', descricao: 'qualquer uma' )
	# 			grupo_de_natureza_da_despesa.save
	#
	# 			expect( grupo_de_natureza_da_despesa.errors[:codigo] ).to include 'não existe grupo de natureza da despesa com esse código'
	# 			expect( grupo_de_natureza_da_despesa.errors[:descricao] ).to include 'não existe grupo de natureza da despesa com essa descrição'
	# 		end
	# 	end
	#
	# 	context "quando código ou descrição estão contigos no seed base de naturezas da despesa'" do
	# 		it "não adiciona erros nos atributos" do
	# 			grupo_de_natureza_da_despesa = FactoryBot.create(:outras_despesas_correntes)
	# 			expect( grupo_de_natureza_da_despesa.errors[:codigo] ).to_not include 'não existe grupo de natureza da despesa com esse código'
	# 			expect( grupo_de_natureza_da_despesa.errors[:descricao] ).to_not include 'não existe grupo de natureza da despesa com essa descrição'
	# 		end
	# 	end
	# end

	describe '#valor_total_fixado_dos_elementos' do
		it "retorna a soma de todos os orçamentos aliados a todos os elementos de despesa filhos" do

			grupo_de_natureza_da_despesa = Base::GrupoDeNaturezaDaDespesa.new( FactoryBot.attributes_for(:outras_despesas_correntes) )
			grupo_de_natureza_da_despesa.save

			elemento_de_despesa = Base::ElementoDeDespesa.find_or_create_by!( FactoryBot.attributes_for(:elemento_de_despesa_material_de_consumo, :com_modalidade_de_aplicacao) )
			elemento_de_despesa_por_subacao = FactoryBot.create(:elemento_de_despesa_por_subacao, elemento_de_despesa_id: elemento_de_despesa.id)
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_educacao, valor: 150.0 , elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao.id ) )
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_saude, valor: 50.0, elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao.id ) )

			expect(grupo_de_natureza_da_despesa.valor_total_fixado_dos_elementos).to eq 200.0
		end
	end

	describe '#valor_total_fixado_dos_elementos_intra_orcamentarios' do
		it "retorna a soma de todos os orçamentos aliados a todos os elementos de despesa cuja modalidade de aplicação é 91" do

			grupo_de_natureza_da_despesa = Base::GrupoDeNaturezaDaDespesa.new( FactoryBot.attributes_for(:outras_despesas_correntes) )
			grupo_de_natureza_da_despesa.save

			elemento_de_despesa_intra_orcamentario = Base::ElementoDeDespesa.find_or_create_by!( FactoryBot.attributes_for(:elemento_de_despesa_material_de_consumo, :com_modalidade_de_aplicacao_intra_orcamentaria) )
			elemento_de_despesa_por_subacao_intra_orcamentario = FactoryBot.create(:elemento_de_despesa_por_subacao, elemento_de_despesa_id: elemento_de_despesa_intra_orcamentario.id)
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_educacao, valor: 150.0 , elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao_intra_orcamentario.id ) )
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_saude, valor: 50.0, elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao_intra_orcamentario.id ) )

			elemento_de_despesa = Base::ElementoDeDespesa.find_or_create_by!( FactoryBot.attributes_for(:elemento_de_despesa_material_de_consumo, :com_modalidade_de_aplicacao) )
			elemento_de_despesa_por_subacao = FactoryBot.create(:elemento_de_despesa_por_subacao, elemento_de_despesa_id: elemento_de_despesa.id)
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_saude, valor: 50.0, elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao.id ) )
			expect(grupo_de_natureza_da_despesa.valor_total_fixado_dos_elementos_intra_orcamentarios).to eq 200.0
		end
	end

	describe '#valor_total_fixado_dos_elementos_exceto_intra_orcamentarios' do
		it "retorna a soma de todos os orçamentos aliados a todos os elementos de despesa cuja modalidade de aplicação não é 91" do

			grupo_de_natureza_da_despesa = Base::GrupoDeNaturezaDaDespesa.new( FactoryBot.attributes_for(:outras_despesas_correntes) )
			grupo_de_natureza_da_despesa.save

			elemento_de_despesa = Base::ElementoDeDespesa.find_or_create_by!( FactoryBot.attributes_for(:elemento_de_despesa_material_de_consumo, :com_modalidade_de_aplicacao) )
			elemento_de_despesa_por_subacao = FactoryBot.create(:elemento_de_despesa_por_subacao, elemento_de_despesa_id: elemento_de_despesa.id)
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_saude, valor: 50.0, elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao.id ) )

			elemento_de_despesa_intra_orcamentario = Base::ElementoDeDespesa.find_or_create_by!( FactoryBot.attributes_for(:elemento_de_despesa_material_de_consumo, :com_modalidade_de_aplicacao_intra_orcamentaria) )
			elemento_de_despesa_por_subacao_intra_orcamentario = FactoryBot.create(:elemento_de_despesa_por_subacao, elemento_de_despesa_id: elemento_de_despesa_intra_orcamentario.id)
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_educacao, valor: 150.0 , elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao_intra_orcamentario.id ) )
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_saude, valor: 50.0, elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao_intra_orcamentario.id ) )
			expect(grupo_de_natureza_da_despesa.valor_total_fixado_dos_elementos_exceto_intra_orcamentarios).to eq 50.0
		end
	end

	describe '#valor_total_realizado_dos_elementos' do
		it "retorna a soma dos valores empenhados de todos os orçamentos aliados aos elementos de despesa filhos" do
			grupo_de_natureza_da_despesa = Base::GrupoDeNaturezaDaDespesa.new( FactoryBot.attributes_for(:outras_despesas_correntes) )
			grupo_de_natureza_da_despesa.save

			elemento_de_despesa = Base::ElementoDeDespesa.find_or_create_by!( FactoryBot.attributes_for(:elemento_de_despesa_material_de_consumo, :com_modalidade_de_aplicacao_intra_orcamentaria) )
			elemento_de_despesa_por_subacao = FactoryBot.create(:elemento_de_despesa_por_subacao, elemento_de_despesa_id: elemento_de_despesa.id)
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_educacao, valor: 150.0 , elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao.id ) )
			empenho = FactoryBot.build( :empenho_22090001, orcamento_da_despesa: orcamento_da_despesa, valor: 130.0, status: :confirmado, descriminacao_obrigatoria_de_itens: false )
			empenho.save(validate: false)
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_saude, valor: 50.0, elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao.id ) )
			empenho = FactoryBot.build( :empenho_22090001, orcamento_da_despesa: orcamento_da_despesa, valor: 30.0, status: :confirmado, descriminacao_obrigatoria_de_itens: false )
			empenho.save(validate: false)

			expect(grupo_de_natureza_da_despesa.valor_total_realizado_dos_elementos).to eq 160.0
		end
	end

	describe '#valor_total_realizado_dos_elementos_intra_orcamentarios' do
		it "retorna a soma dos valores empenhados de todos os orçamentos aliados aos elementos de despesa cuja modalidade de aplicação é 91" do
			grupo_de_natureza_da_despesa = Base::GrupoDeNaturezaDaDespesa.new( FactoryBot.attributes_for(:outras_despesas_correntes) )
			grupo_de_natureza_da_despesa.save

			elemento_de_despesa_intra_orcamentario = Base::ElementoDeDespesa.find_or_create_by!( FactoryBot.attributes_for(:elemento_de_despesa_material_de_consumo, :com_modalidade_de_aplicacao_intra_orcamentaria) )
			elemento_de_despesa_por_subacao_intra_orcamentario = FactoryBot.create(:elemento_de_despesa_por_subacao, elemento_de_despesa_id: elemento_de_despesa_intra_orcamentario.id)

			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_educacao, valor: 150.0 , elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao_intra_orcamentario.id ) )
			empenho = FactoryBot.build( :empenho_22090001, orcamento_da_despesa: orcamento_da_despesa, valor: 130.0, status: :confirmado, descriminacao_obrigatoria_de_itens: false )
			empenho.save(validate: false)

			elemento_de_despesa = Base::ElementoDeDespesa.find_or_create_by!( FactoryBot.attributes_for(:elemento_de_despesa_material_de_consumo, :com_modalidade_de_aplicacao) )
			elemento_de_despesa_por_subacao = FactoryBot.create(:elemento_de_despesa_por_subacao, elemento_de_despesa_id: elemento_de_despesa.id)

			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_saude, valor: 50.0, elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao.id ) )
			empenho = FactoryBot.build( :empenho_22090001, orcamento_da_despesa: orcamento_da_despesa, valor: 30.0, status: :confirmado, descriminacao_obrigatoria_de_itens: false )
			empenho.save(validate: false)

			expect(grupo_de_natureza_da_despesa.valor_total_realizado_dos_elementos_intra_orcamentarios).to eq 130.0
		end
	end

	describe '#valor_total_realizado_dos_elementos_exceto_intra_orcamentarios' do
		it "retorna a soma dos valores empenhados de todos os orçamentos aliados aos elementos de despesa cuja modalidade de aplicação é 91" do
			grupo_de_natureza_da_despesa = Base::GrupoDeNaturezaDaDespesa.new( FactoryBot.attributes_for(:outras_despesas_correntes) )
			grupo_de_natureza_da_despesa.save

			elemento_de_despesa_intra_orcamentario = Base::ElementoDeDespesa.find_or_create_by!( FactoryBot.attributes_for(:elemento_de_despesa_material_de_consumo, :com_modalidade_de_aplicacao_intra_orcamentaria) )
			elemento_de_despesa_por_subacao_intra_orcamentario = FactoryBot.create(:elemento_de_despesa_por_subacao, elemento_de_despesa_id: elemento_de_despesa_intra_orcamentario.id)

			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_educacao, valor: 150.0 , elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao_intra_orcamentario.id ) )
			empenho = FactoryBot.build( :empenho_22090001, orcamento_da_despesa: orcamento_da_despesa, valor: 130.0, status: :confirmado, descriminacao_obrigatoria_de_itens: false )
			empenho.save(validate: false)

			elemento_de_despesa = Base::ElementoDeDespesa.find_or_create_by!( FactoryBot.attributes_for(:elemento_de_despesa_material_de_consumo, :com_modalidade_de_aplicacao) )
			elemento_de_despesa_por_subacao = FactoryBot.create(:elemento_de_despesa_por_subacao, elemento_de_despesa_id: elemento_de_despesa.id)

			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_saude, valor: 50.0, elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao.id ) )
			empenho = FactoryBot.build( :empenho_22090001, orcamento_da_despesa: orcamento_da_despesa, valor: 30.0, status: :confirmado, descriminacao_obrigatoria_de_itens: false )
			empenho.save(validate: false)

			expect(grupo_de_natureza_da_despesa.valor_total_realizado_dos_elementos_exceto_intra_orcamentarios).to eq 30.0
		end
	end

	describe 'codigo_formatado' do
		it 'retorna codigo com os pontos' do
			grupo = Base::GrupoDeNaturezaDaDespesa.new
			grupo.codigo = '30000000'
			expect(grupo.codigo_formatado).to eq("3.0.00.00.00")
		end
	end

	describe 'valor_previsto_por_mes(mes)' do
		it 'sem porcentagem cadastrada retorna valor total/12' do
			grupo_de_natureza_da_despesa = Base::GrupoDeNaturezaDaDespesa.new( FactoryBot.attributes_for(:outras_despesas_correntes) )
			grupo_de_natureza_da_despesa.save

			elemento_de_despesa = Base::ElementoDeDespesa.find_or_create_by!( FactoryBot.attributes_for(:elemento_de_despesa_material_de_consumo, :com_modalidade_de_aplicacao_intra_orcamentaria) )
			elemento_de_despesa_por_subacao = FactoryBot.create(:elemento_de_despesa_por_subacao, elemento_de_despesa_id: elemento_de_despesa.id)
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_educacao, valor: 120.0 , elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao.id ) )
			empenho = FactoryBot.build( :empenho_22090001, orcamento_da_despesa: orcamento_da_despesa, valor: 120.0, status: :confirmado, descriminacao_obrigatoria_de_itens: false )
			empenho.save(validate: false)
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_saude, valor: 120.0, elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao.id ) )
			empenho = FactoryBot.build( :empenho_22090001, orcamento_da_despesa: orcamento_da_despesa, valor: 120.0, status: :confirmado, descriminacao_obrigatoria_de_itens: false )
			empenho.save(validate: false)

			expect(grupo_de_natureza_da_despesa.valor_previsto_por_mes(1)).to eq (240/12)
		end
	end

	it 'valor_total' do
		orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_educacao) )
		expect(orcamento_da_despesa.elemento_de_despesa_por_subacao.elemento_de_despesa.modalidade_de_aplicacao.grupo_de_natureza_da_despesa.valor_total.to_f).to eq 20
	end

	it 'valor_total_por_subfuncao' do
		orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_educacao) )
		subfuncao = orcamento_da_despesa.elemento_de_despesa_por_subacao.subacao.subfuncao
		grupo = orcamento_da_despesa.elemento_de_despesa_por_subacao.elemento_de_despesa.modalidade_de_aplicacao.grupo_de_natureza_da_despesa
		expect(grupo.valor_total_por_subfuncao(subfuncao)).to eq 20
	end

	it 'valor_previsto_por_unidade_orcamentaria' do
		orcamento_da_despesa = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_educacao) )
		unidade_orcamentaria = orcamento_da_despesa.elemento_de_despesa_por_subacao.subacao.unidade_orcamentaria
		grupo = orcamento_da_despesa.elemento_de_despesa_por_subacao.elemento_de_despesa.modalidade_de_aplicacao.grupo_de_natureza_da_despesa
		expect(grupo.valor_previsto_por_unidade_orcamentaria(unidade_orcamentaria)).to eq 20
	end
end
