class Tableless::ElementoDeDespesa
	include ActiveModel::Model

	attr_accessor :categoria_economica_id
	attr_accessor :grupo_de_natureza_da_despesa_id
	attr_accessor :modalidade_de_aplicacao_id
	attr_accessor :elemento_de_despesa_id

	validates_presence_of :categoria_economica_id
	validates_presence_of :grupo_de_natureza_da_despesa_id
	validates_presence_of :modalidade_de_aplicacao_id
	validates_presence_of :elemento_de_despesa_id

	validate :grupo_belongs_to_categoria, if: Proc.new { grupo_de_natureza_da_despesa_id.present? }

	def gerar_elemento_de_despesa(modulo, base_elemento_de_despesa_para_atualizar = nil)
		ActiveRecord::Base.transaction do
			base_categoria_economica = Base::CategoriaEconomica.find_by( modulo_id: modulo.id, modulo_type: modulo.class.name, codigo: "#{categoria_economica.codigo}0000000" )
			base_grupo_de_natureza_da_despesa = Base::GrupoDeNaturezaDaDespesa.find_by( categoria_economica_id: base_categoria_economica.id, codigo: "#{categoria_economica.codigo}#{grupo_de_natureza_da_despesa.codigo}000000" )

			base_modalidade_de_aplicacao = criar_modalidade_de_aplicacao(base_grupo_de_natureza_da_despesa)

			if base_elemento_de_despesa_para_atualizar.present?
				atualizar_elemento_de_despesa(base_elemento_de_despesa_para_atualizar, base_modalidade_de_aplicacao.id)
			else
				criar_elemento_de_despesa(base_modalidade_de_aplicacao.id)
			end
		end
	end

	def tem_folha_de_pagamento
		['01', '03', '11', '16'].include? elemento_de_despesa.codigo
	end

	def categoria_economica
		NaturezaDaDespesa::CategoriaEconomica.find(categoria_economica_id)
	end

	def grupo_de_natureza_da_despesa
		NaturezaDaDespesa::GrupoDeNaturezaDaDespesa.find(grupo_de_natureza_da_despesa_id)
	end

	def modalidade_de_aplicacao
		NaturezaDaDespesa::ModalidadeDeAplicacao.find(modalidade_de_aplicacao_id)
	end

	def elemento_de_despesa
		NaturezaDaDespesa::ElementoDeDespesa.find(elemento_de_despesa_id)
	end

	private

	def criar_elemento_de_despesa(base_modalidade_de_aplicacao_id)
		dados_elemento_de_despesa = {
			modalidade_de_aplicacao_id: base_modalidade_de_aplicacao_id,
			codigo: "#{categoria_economica.codigo}#{grupo_de_natureza_da_despesa.codigo}#{modalidade_de_aplicacao.codigo}#{elemento_de_despesa.codigo}00",
			descricao: elemento_de_despesa.descricao,
			folha_de_pagamento: tem_folha_de_pagamento
		}

		base_elemento_de_despesa = Base::ElementoDeDespesa.ativos.where(dados_elemento_de_despesa.except(:descricao))

		unless base_elemento_de_despesa.present?
			return Base::ElementoDeDespesa.create!(dados_elemento_de_despesa)
		else
			adicionar_erro_de_duplicidade_de_elemento
		end
	end

	def atualizar_elemento_de_despesa(elemento_a_ser_atualizado, modalidade_de_aplicacao_id)
		dados_elemento_de_despesa = {
			modalidade_de_aplicacao_id: modalidade_de_aplicacao_id,
			codigo: "#{categoria_economica.codigo}#{grupo_de_natureza_da_despesa.codigo}#{modalidade_de_aplicacao.codigo}#{elemento_de_despesa.codigo}00",
			descricao: elemento_de_despesa.descricao,
			folha_de_pagamento: tem_folha_de_pagamento
		}

		elemento_a_ser_atualizado.modalidade_de_aplicacao_id = dados_elemento_de_despesa[:modalidade_de_aplicacao_id]
		elemento_a_ser_atualizado.codigo = dados_elemento_de_despesa[:codigo]
		elemento_a_ser_atualizado.descricao = dados_elemento_de_despesa[:descricao]

		if elemento_a_ser_atualizado.save
			return elemento_a_ser_atualizado
		else
			return adicionar_erro_de_duplicidade_de_elemento
		end
	end

	def adicionar_erro_de_duplicidade_de_elemento
		self.errors.add(:elemento_de_despesa_id, 'já está cadastrado')
		return false
	end

	def grupo_belongs_to_categoria
		if grupo_de_natureza_da_despesa.categoria_economica.id != categoria_economica_id.to_i
			self.errors.add(:categoria_economica_id, 'Esse grupo não pode ser cadastrado com essa categoria econômica')
		end
	end

	def criar_modalidade_de_aplicacao(base_grupo_de_natureza_da_despesa)
		dados_modalidade_de_aplicacao = {
			grupo_de_natureza_da_despesa_id: base_grupo_de_natureza_da_despesa.id,
			codigo: "#{categoria_economica.codigo}#{grupo_de_natureza_da_despesa.codigo}#{modalidade_de_aplicacao.codigo}0000",
			descricao: modalidade_de_aplicacao.descricao
		}

		base_modalidade_de_aplicacao = Base::ModalidadeDeAplicacao.find_by(dados_modalidade_de_aplicacao.except(:descricao))
		if !base_modalidade_de_aplicacao.present?
			base_modalidade_de_aplicacao = Base::ModalidadeDeAplicacao.create!(dados_modalidade_de_aplicacao)
		end

		return base_modalidade_de_aplicacao
	end
end
