require 'rails_helper'

RSpec.describe Ppa::ProjecaoDeDespesa, type: :model do
	cria_tipos_de_despesa

	it{ is_expected.to belong_to :orcador }
	it{ is_expected.to belong_to :tipo_de_despesa }
	it{ is_expected.to belong_to :unidade_orcamentaria }

	it{ is_expected.to have_db_column(:valor)
			.of_type(:decimal)
			.with_options(precision: 12, scale: 2)
	}

	[:exercicio, :tipo_de_despesa_id, :valor, :orcador_id, :unidade_orcamentaria_id].each do |atributo|
		it { is_expected.to validate_presence_of atributo }
	end

	it {
		allow_any_instance_of(Ppa::ProjecaoDeDespesa).to receive(:pertence_a_uma_iniciativa?).and_return( false )
		is_expected.to validate_uniqueness_of(:exercicio).scoped_to([
			:orcador_id, :orcador_type, :unidade_orcamentaria_id, :tipo_de_despesa_id
		])
	}

	it { validate_numericality_of(:valor).is_greater_than_or_equal_to(0) }

	context "quando pertence a uma iniciativa" do
		describe "#save" do

			it "deve ter a mesma unidade orçamentária da iniciativa" do
				iniciativa = FactoryBot.create(:ppa_iniciativa_para_ensino_fundamental)
				despesa = iniciativa.projecoes_de_despesa.new
				despesa.unidade_orcamentaria_id = iniciativa.unidade_orcamentaria_id+ 1
				despesa.save
				expect( despesa.errors[:unidade_orcamentaria_id] ).to include 'deve ser igual a unidade orçamentária da iniciativa da iniciativa'
			end
		end
	end

	describe ".recurso_por_programas_tematicos" do
		context "exibe descrição e valores por programas temáticos" do
			it 'retorna nome e total das projeções' do
				programa = FactoryBot.create :programa_escolar, :ppa_2014
				programa.projecoes_de_despesa.create(FactoryBot.attributes_for :projecao_de_despesa, :programa, :despesa_corrente, valor: 200)
				resultado_recurso_por_programa = Ppa::ProjecaoDeDespesa.recurso_por_programas_tematicos programa.ppa_id
				resultado = { nome: programa.nome, quantidade: 200 }
				expect(resultado_recurso_por_programa).to include resultado
			end
		end
	end

	describe ".recursos_por_tipo_de_programa" do
		context 'exibe descrição e valores por tipos de programas' do
			it 'retorna valores' do
				programa = FactoryBot.create :programa_escolar, :ppa_2014
				programa.projecoes_de_despesa.create(FactoryBot.attributes_for :projecao_de_despesa, :despesa_corrente, :programa, valor: 200)
				resultado_recursos_por_tipo_de_programa = Ppa::ProjecaoDeDespesa.recursos_por_tipo_de_programa programa.ppa_id
				resultado = { nome: programa.tipo_de_programa.nome, quantidade: 200.0 }
				expect(resultado_recursos_por_tipo_de_programa).to include (resultado)
			end
		end
	end

	describe ".recurso_por_funcao_de_despesa" do
		context 'exibe descrição e valores de recurso por função de despesa' do
			it 'retorna valores' do
				iniciativa = FactoryBot.create :ppa_iniciativa_com_proposta
				iniciativa.projecoes_de_despesa.create(FactoryBot.attributes_for :projecao_de_despesa, :despesa_corrente, :programa, valor: 200)
				valores = Ppa::ProjecaoDeDespesa.recurso_por_funcao_de_despesa(iniciativa.proposta.ppa_id)
				resultado = {nome: iniciativa.funcao.nome, quantidade: 200}
				expect(valores).to include (resultado)
			end
		end
	end

	describe "#esta_dentro_do_periodo_do_ppa" do
		context 'quando está no intervalo' do
			it "salva" do
				iniciativa = FactoryBot.create(:ppa_iniciativa_para_ensino_fundamental)
				despesa = iniciativa.projecoes_de_despesa.new(FactoryBot.attributes_for :projecao_de_despesa, :despesa_corrente, :iniciativa)
				despesa.exercicio = iniciativa.ppa.periodo.last
				despesa.save
				expect( despesa ).to be_persisted
			end
		end
		context 'quando está fora do intervalo' do
			it "retorna erro" do
				allow_any_instance_of( Ppa::Ppa ).to receive( :detalha_despesas_nas_iniciativas? ).and_return( true )
				iniciativa = FactoryBot.create(:ppa_iniciativa_para_ensino_fundamental)
				despesa = iniciativa.projecoes_de_despesa.last
				despesa.exercicio = iniciativa.ppa.periodo.last+1
				despesa.save
				expect( despesa.errors[:exercicio] ).to include 'deve estar dentro do período do PPA'
			end
		end
	end
end
