class Controladoria::CentroDeCusto < ApplicationRecord
	include Rails.application.routes.url_helpers

	has_paper_trail

	enum status: { ativo: 1, inativo: 2 }

	attr_default :status, :ativo

	belongs_to :unidade_gestora, class_name: 'Loa::UnidadeGestora'
	belongs_to :centro_de_custos_mae, class_name: 'Controladoria::CentroDeCusto', foreign_key: "centro_de_custos_mae_id"
	belongs_to :centro_de_custos_mae_principal, class_name: 'Controladoria::CentroDeCusto', foreign_key: "mae_principal_id"

	has_many :centro_de_custos_filhos, class_name: 'Controladoria::CentroDeCusto', foreign_key: "centro_de_custos_mae_id", dependent: :restrict_with_error
	has_many :centro_de_custos_filhos_todos, class_name: 'Controladoria::CentroDeCusto', foreign_key: "mae_principal_id", dependent: :restrict_with_error
	has_many :responsaveis_do_centro_de_custos, class_name: 'Controladoria::ResponsavelDoCentroDeCusto'
	has_many :transferencias, class_name: 'Patrimonio::Transferencia'
	has_many :baixas_dos_bens_em_massa, class_name: 'Patrimonio::BaixaDoBemEmMassa'
	has_many :dados_dos_destinos_das_transferencias, class_name: 'Patrimonio::DadosDoDestinoDaTransferencia', foreign_key: "centro_de_custo_destino_id"
	has_many :dados_dos_destinos_das_requisicoes, class_name: 'Patrimonio::DadosDoDestinoDaRequisicaoPatrimonial', foreign_key: "centro_de_custo_id"

	accepts_nested_attributes_for :centro_de_custos_filhos, reject_if: :all_blank, allow_destroy: true

	validates_presence_of :descricao

	before_validation :preenche_mae_principal
	after_save :gerar_codigo_dos_filhos
	after_save :gerar_codigo
	validate :verifica_se_pode_inativar

	scope :ativos, lambda { where(status: :ativo) }
	scope :inativos, lambda { where(status: :inativo) }

	def pode_inativar?
		self.ativo?
	end

	def verifica_se_pode_inativar
		if self.persisted? and self.will_save_change_to_status? and self.status == "inativo"
		  errors.add(:status, "O centro de custo não pode ser inativado pois tem centros de custos filhos ativos") if self.centro_de_custos_filhos.any?(&:ativo?)
		end
	end

	def bens_patrimoniais_nesse_centro_de_custo
		bens_patrimoniais = Patrimonio::BemPatrimonial.find_by_sql(" SELECT bem.* FROM patrimonio_bens_patrimoniais bem
			INNER JOIN patrimonio_localizacoes_dos_bens loc ON loc.id = bem.localizacao_atual_id 
			INNER JOIN controladoria_centro_de_custos centro ON centro.id = loc.centro_de_custo_id WHERE bem.status = 1 AND centro.id = #{self.id}
		")

		return bens_patrimoniais
	end

	def houve_bem_patrimonial?
		Patrimonio::BemPatrimonial.joins(:localizacoes_dos_bens).where('patrimonio_localizacoes_dos_bens.centro_de_custo_id = ?', self.id).present?
	end

	def codigo_e_descricao
		"#{self.try(:codigo)} - #{self.try(:descricao)}"
	end

	def codigo_e_descricao_e_mae_principal
		if self.unidade_gestora.present?
			"#{self.try(:codigo)} - #{self.try(:descricao)}"
		else
			"#{self.try(:codigo)} - #{self.try(:descricao)} (#{self.try(:centro_de_custos_mae_principal).try(:descricao)})"
		end
	end

	def descricao_e_mae_principal
		if self.unidade_gestora.present?
			"#{self.descricao}"
		else
			"#{self.descricao} (#{self.centro_de_custos_mae_principal.descricao})"
		end
	end

	def codigo_e_descricao_da_gestora
		if self.unidade_gestora.present?
			"#{self.unidade_gestora.codigo_e_nome}"
		else
			"#{self.centro_de_custos_mae_principal.unidade_gestora.codigo_e_nome}"
		end
	end

	def carregar_familia_da_ug
		maior_nivel = self.retorna_ultimo_nivel

		if self.nivel == 1
			familia = { text: {name: self.unidade_gestora.codigo_e_nome}, stackChildren: true , link: { href: "#{controladoria_centro_de_custo_path(self.id)}", target: '_self' }, children: buscar_filhos(self, nil, 1, maior_nivel) }
		else
			familia = { text: {name: self.centro_de_custos_mae_principal.unidade_gestora.codigo_e_nome}, stackChildren: true , link: { href: "#{controladoria_centro_de_custo_path(self.centro_de_custos_mae_principal.id)}", target: '_self' }, children: buscar_filhos(self.centro_de_custos_mae_principal, nil, self.nivel.to_i, maior_nivel) }
		end


		return familia
	end

	def retorna_ultimo_nivel
		if self.nivel == 1
			self.centro_de_custos_filhos_todos.present? ? self.centro_de_custos_filhos_todos.order(nivel: :desc).first.nivel.to_i : self.nivel.to_i
		else
			self.centro_de_custos_mae_principal.centro_de_custos_filhos_todos.order(nivel: :desc).first.nivel.to_i
		end
	end

	def buscar_filhos(mae_principal, centro_de_custo_mae, nivel_atual, maior_nivel)
		filhos = Array.new
		if mae_principal.present?
			mae_principal.centro_de_custos_filhos.where(nivel: 2, status: 1).each do |centro_de_custo|
				filhos << { text: { name: centro_de_custo.descricao }, stackChildren: true , HTMLclass: "#{'selecionado' if self == centro_de_custo}", link: { href: "#{controladoria_centro_de_custo_path(centro_de_custo.id)}", target: '_self' }, children: buscar_filhos(nil, centro_de_custo, nivel_atual, maior_nivel) }
			end
		else
			centro_de_custo_mae.centro_de_custos_filhos.where(status: 1).each do |centro_de_custo|
				if centro_de_custo.nivel <= maior_nivel
					filhos << { text: { name: centro_de_custo.descricao }, stackChildren: true , HTMLclass: "#{'selecionado' if self == centro_de_custo}", link: { href: "#{controladoria_centro_de_custo_path(centro_de_custo.id)}", target: '_self' }, children: buscar_filhos(nil, centro_de_custo, nivel_atual, maior_nivel) }
				end
			end
		end
		return filhos
	end

	def responsavel_do_centro_de_custos
		if self.responsavel_atual.present?
			self.responsavel_atual
		else
			self.centro_de_custos_mae_principal.responsavel_atual
		end
	end

	def responsavel_do_centro_de_custos_patrimonial
		if self.unidade_gestora.present?
			self.responsavel_atual
		else
			self.centro_de_custos_mae_principal.responsavel_atual
		end
	end

	def retorna_nivel
		if self.centro_de_custos_mae.present?
			nivel = self.centro_de_custos_mae.nivel.to_i + 1
		else
			nivel = 1
		end
		nivel.to_i
	end

	def responsavel_atual
		self.responsaveis_do_centro_de_custos.where('data_inicial >= ? and (data_final >= ? or data_final is null) and responsavel_gestora = ?', Date.today.beginning_of_year, Date.today, false).first
	end

	def responsavel_atual_patrimonial
		self.responsaveis_do_centro_de_custos.where('data_inicial >= ? and (data_final >= ? or data_final is null) and responsavel_gestora = ?', Date.today.beginning_of_year, Date.today, true).first
	end

	def responsavel_no_periodo(data_inicial, data_final)
		self.responsaveis_do_centro_de_custos.where('(data_inicial <= ? and data_final >= ?) or (data_inicial <= ? and data_final >= ?) or (data_inicial < ? and data_final is null)', data_inicial, data_inicial, data_final, data_final, data_final).first
	end
	
	def responsavel_ate_data(data)
		self.responsaveis_do_centro_de_custos.where('(data_inicial < ? and data_final is null)', data).first rescue nil
	end
	
	def responsavel_no_periodo_a_partir(data_inicial)
		self.responsaveis_do_centro_de_custos.where('(data_inicial <= ? and data_final >= ?) or (data_inicial <= ? and data_final is null)', data_inicial, data_inicial, data_inicial).order('data_inicial ASC').first
	end

	def existe_responsavel_periodo?(data_inicial, data_final)
		responsavel_no_periodo(data_inicial, data_final) && self.responsaveis_do_centro_de_custos.where('responsavel_gestora = ?', false).present?
	end

	def gerar_codigo_dos_filhos
		self.centro_de_custos_filhos.order(:id).each do |centro_de_custo|
			centro_de_custo.gerar_codigo
		end
	end

	def preenche_mae_principal
		if self.nivel.to_i >= 2
			if self.nivel == 2
				self.mae_principal_id = self.centro_de_custos_mae_id
			else
				self.mae_principal_id = self.centro_de_custos_mae.mae_principal_id
			end
		end
	end

	def gerar_codigo
		if self.codigo.blank?
			if self.nivel == 1
				ultimo_codigo = Controladoria::CentroDeCusto.where('nivel = 1').order("COALESCE(codigo, '0') DESC").first
				unless ultimo_codigo.present?
					self.codigo = '1'
				else
					self.codigo = ultimo_codigo.try(:codigo).to_i + 1
				end
			else
				if self.centro_de_custos_mae.present?
					i = self.nivel.to_i - 1
					ultimo_codigo = self.centro_de_custos_mae.centro_de_custos_filhos.where('codigo is not null').sort_by { |cod| cod.codigo.split('.')[-1].to_i }.reverse.first

					unless ultimo_codigo.present?
						self.codigo = self.centro_de_custos_mae.codigo + '.1'
					else
						a = ultimo_codigo.codigo.split(".")
						a[i] = a[i].to_i + 1
						self.codigo = a.join(".")
					end
				end
			end
			self.save
		end
	end
end
