module Base
	class Funcao < ApplicationRecord

		has_paper_trail

		belongs_to :modulo, polymorphic: true
		belongs_to :tipo_de_orcamento, required: true

		has_many :subfuncoes, dependent: :destroy
		has_many :subacoes, class_name: 'Loa::Subacao', dependent: :restrict_with_exception
		has_many :orcamentos_da_despesa, through: :subacoes

		validates_presence_of :codigo, :nome, :modulo_id, :modulo_type, :tipo_de_orcamento_id
		validates_uniqueness_of :codigo, scope: [:modulo_id, :modulo_type]
		validates_uniqueness_of :nome, scope: [:modulo_id, :modulo_type]

		validate :codigo_deve_ser_unico_para_um_orcamento
		validate :nome_deve_ser_unico_para_um_orcamento

		validates :modulo_id, immutable: true
		validates :modulo_type, immutable: true
		validates :tipo_de_orcamento_id, immutable: true

		def eh_da_saude?
			self.codigo == "10"
		end

		def eh_da_educacao?
			self.codigo == "12"
		end

		# VALORES POR SUBAÇÃO
		def valor_total_fixado_da_despesa
			self.subacoes.sum(:fixacao_da_despesa).to_f
		end

		def valor_total_realizado_da_despesa
			total = self.subacoes.inject(0) { |total, subacao|
				total + subacao.valor_total_realizado_da_despesa.to_f
			}
		end

		def valor_total_fixado_da_despesa_orcamentos_fiscal
			self.subacoes.orcamentos_fiscal.sum(:fixacao_da_despesa).to_f
		end

		def valor_total_fixado_da_despesa_seguridade_social
			self.subacoes.seguridade_social.sum(:fixacao_da_despesa).to_f
		end

		# VALORES POR SUBFUNÇÕES
		def valor_total_fixado_da_despesa_por_subfuncoes
			total = self.subfuncoes.inject(0) { |total, subfuncao|
				total + subfuncao.valor_total_fixado_da_despesa.to_f
			}

			return total
		end

		def valor_total_realizado_da_despesa_por_subfuncoes
			total = self.subfuncoes.inject(0) { |total, subfuncao|
				total + subfuncao.valor_total_realizado_da_despesa.to_f
			}

			return total
		end

		def valor_total_fixado_orcamento_fiscal
			self.orcamentos_da_despesa.select{ |orc| orc.tipo_de_orcamento == "F" }.sum(&:valor_fixado)
		end
		
		def valor_total_fixado_seguridade_social
			self.orcamentos_da_despesa.select{ |orc| orc.tipo_de_orcamento == "S" }.sum(&:valor_fixado)
		end

		def valor_total_fixado_geral
			self.orcamentos_da_despesa.sum(&:valor_fixado)
		end
		
		def valor_total_fixado_da_despesa_orcamentos_fiscal_por_subfuncoes
			total = self.subfuncoes.inject(0) { |total, subfuncao|
				total + subfuncao.subacoes.orcamentos_fiscal.map { |orcamento_fiscal| orcamento_fiscal[:fixacao_da_despesa].to_f }.sum.to_f
			}

			return total
		end

		def valor_total_fixado_da_despesa_seguridade_social_por_subfuncoes
			total = self.subfuncoes.inject(0) { |total, subfuncao|
				total + subfuncao.subacoes.seguridade_social.map { |seguridade_social| seguridade_social[:fixacao_da_despesa].to_f }.sum.to_f
			}

			return total
		end
		
		def valor_total_fixado_da_despesa_por_unidade(unidade = nil)
			total = 0
			if unidade.nil?
				total += self.subacoes.sum(:fixacao_da_despesa).to_f
			elsif unidade.class.name == 'Loa::UnidadeOrcamentaria'
				total += self.subacoes.where(unidade_orcamentaria_id: unidade.id).sum(:fixacao_da_despesa).to_f
			else
				unidade.each do |unidade|
					total += self.subacoes.where(unidade_orcamentaria_id: unidade.id).sum(:fixacao_da_despesa).to_f
				end
			end
			total
		end

		def codigo_e_nome
			"#{codigo} - #{nome}"
		end

		def codigo_deve_ser_unico_para_um_orcamento
			Base::Funcao.where(codigo: self.codigo).each do |funcao|
				next if funcao.eql?(self)
				if (
					self.modulo_type == 'Orcamento' &&
					funcao.modulo_type == 'Orcamento' &&
					self.modulo_id == funcao.modulo_id
				)
					errors.add(:codigo, "já está em uso")
					break
				end
			end
		end

		def nome_deve_ser_unico_para_um_orcamento
			Base::Funcao.where(nome: self.nome).each do |funcao|
				next if funcao.eql?(self)
				if (
					self.modulo_type == 'Orcamento' &&
					funcao.modulo_type == 'Orcamento' &&
					self.modulo_id == funcao.modulo_id
				)
					errors.add(:nome, "já está em uso")
					break
				end
			end
		end
	end
end
