require 'rails_helper'

RSpec.describe Base::Funcao, type: :model do

	it{ is_expected.to belong_to :modulo }
	it{ is_expected.to belong_to(:tipo_de_orcamento).required }
	it{ is_expected.to have_many(:subfuncoes).dependent(:destroy) }
	it{ is_expected.to have_many(:subacoes).class_name('Loa::Subacao').dependent(:restrict_with_exception) }

	it{ is_expected.to validate_presence_of :nome }
	it{ is_expected.to validate_presence_of :codigo }
	it{ is_expected.to validate_presence_of :modulo_id }
	it{ is_expected.to validate_presence_of :modulo_type }
	it{ is_expected.to validate_presence_of :tipo_de_orcamento_id }

	it{ is_expected.to validate_uniqueness_of(:codigo).scoped_to(:modulo_id, :modulo_type) }
	it{ is_expected.to validate_uniqueness_of(:nome).scoped_to(:modulo_id, :modulo_type) }

	describe "#codigo_e_nome" do
		it 'retorna "XX - DESCRICAO", onde XX é o código é a NOME é o nome da função' do
					funcao = Base::Funcao.new(codigo: '8794', nome: 'Descrição')
					expect(funcao.codigo_e_nome).to eq('8794 - Descrição')
			end
	end

	describe '#immutable' do
		it "não permite alterações no atributo modulo_id" do
			funcao = FactoryBot.create( :funcao_saude, :orcamento_2016 )
			funcao.modulo_id = funcao.modulo_id + 1
			funcao.save
			expect( funcao.errors[:modulo_id] ).to include "não pode ser alterado"
		end

		it "não permite alterações no atributo modulo_type" do
			funcao = FactoryBot.create( :funcao_saude, :orcamento_2016 )
			funcao.modulo_type = 'PPA'
			funcao.save
			expect( funcao.errors[:modulo_type] ).to include "não pode ser alterado"
		end

		it "não permite alterações no atributo tipo_de_orcamento_id" do
			funcao = FactoryBot.create( :funcao_saude, :orcamento_2016 )
			funcao.tipo_de_orcamento_id = Base::TipoDeOrcamento.find_or_create_by!( FactoryBot.attributes_for( :orcamento_fiscal, :orcamento_2016 ) ).id
			funcao.save
			expect( funcao.errors[:tipo_de_orcamento_id] ).to include "não pode ser alterado"
		end
	end

	describe '#valor_total_fixado_da_despesa' do
		it "retorna o valor total fixado das subações de uma ação" do
			subacao = FactoryBot.create :subacao_1005_0001, :orcamento_2016
			funcao = subacao.funcao
			outra_subacao = FactoryBot.create :subacao_1005_0002, :orcamento_2016, acao_id: subacao.acao.id, funcao_id: funcao.id
			elemento_id = Base::ElementoDeDespesa.find_or_create_by!( FactoryBot.attributes_for(:elemento_de_despesa_material_de_consumo) ).id
			fonte_id = Base::FonteDeRecursos.find_or_create_by!( FactoryBot.attributes_for(:taxas_vinculadas) ).id

			atributos_de_elementos_de_despesa_por_subacao =  {
				fixacao_da_despesa: 100.00,
				elementos_de_despesa_por_subacao_attributes: {
					"0" => {
						elemento_de_despesa_id: elemento_id,
						orcamentos_da_despesa_attributes: {
							"0" => {
								valor: 100.00,
								fonte_de_recursos_id: fonte_id
							}
						}
					}
				}
			}
			subacao.update(atributos_de_elementos_de_despesa_por_subacao)

			atributos_de_elementos_de_despesa_por_subacao =  {
				fixacao_da_despesa: 50.00,
				elementos_de_despesa_por_subacao_attributes: {
					"0" => {
						elemento_de_despesa_id: elemento_id,
						orcamentos_da_despesa_attributes: {
							"0" => {
								valor: 50.00,
								fonte_de_recursos_id: fonte_id
							}
						}
					}
				}
			}
			outra_subacao.update(atributos_de_elementos_de_despesa_por_subacao)

			expect(funcao.valor_total_fixado_da_despesa).to eq 150.0
		end
	end

	describe '#valor_total_realizado_da_despesa' do
		it "retorna a soma dos valores arrecadados dos orçamentos da despesa" do
			orcamento_da_saude = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_educacao, valor: 150.0 ) )
			empenho = FactoryBot.build( :empenho_22090001, orcamento_da_despesa: orcamento_da_saude, valor: 130.0, status: :confirmado, descriminacao_obrigatoria_de_itens: false )
			empenho.save(validate: false)
			orcamento_da_educacao = Loa::OrcamentoDaDespesa.create( FactoryBot.attributes_for( :orcamento_da_despesa_saude, valor: 50.0 ) )
			empenho = FactoryBot.build( :empenho_22090001, orcamento_da_despesa: orcamento_da_educacao, valor: 30.0, status: :confirmado, descriminacao_obrigatoria_de_itens: false )
			empenho.save(validate: false)
			funcao = orcamento_da_saude.elemento_de_despesa_por_subacao.subacao.funcao

			expect(funcao.valor_total_realizado_da_despesa).to eq 160.0
		end
	end

	describe '#valor_total_fixado_da_despesa_por_unidade' do
		it "retorna a soma dos valores fixados por unidade" do
			orcamento_saude = FactoryBot.create( :orcamento_da_despesa_saude )
			subacao = orcamento_saude.elemento_de_despesa_por_subacao.subacao
			subacao.fixacao_da_despesa = orcamento_saude.valor
 			subacao.save
			funcao = subacao.funcao
			expect(funcao.valor_total_fixado_da_despesa_por_unidade(subacao.unidade_orcamentaria)).to eq 12345.67
		end
	end

end
