class Base::ReceitaStn < ApplicationRecord

	attr_accessor :receitas_filhas
	attr_accessor :gerar_filhas
	attr_accessor :busca_ou_gera_natureza

	belongs_to :orcamento
	has_many :niveis_opcionais_stn, dependent: :destroy
	has_many :naturezas_da_receita, class_name: "Base::NaturezaDaReceita", dependent: :restrict_with_exception

	validates_presence_of :codigo, :descricao
	validates_uniqueness_of :codigo, scope: :orcamento_id

	attr_default :pedir_cadastro_de_convenio, false
	attr_default :de_convenio, false

	before_create :popula_analitica
	after_create :cria_receitas_filhas, if: Proc.new { (self.codigo[-2] != '0' && self.codigo[-1] == '0') || (self.codigo[-4..-3] != 0 && self.codigo[-2] == '0' && self.codigo[-1] == '0') }
	after_create :buscar_ou_gerar_natureza_da_receita

	def codigo_formatado_e_descricao
		if codigo[0].eql?("9") && codigo.size > 8
			"#{codigo[0]}.#{codigo[1]}.#{codigo[2]}.#{codigo[3]}.#{codigo[4..5]}.#{codigo[6]}.#{codigo[7]}.#{codigo[8]}.#{codigo[9]} - #{descricao_e_sigla}"
		else
			"#{codigo[0]}.#{codigo[1]}.#{codigo[2]}.#{codigo[3]}.#{codigo[4..5]}.#{codigo[6]}.#{codigo[7]} - #{descricao_e_sigla}"
		end
	end

	def descricao_e_sigla
		self[:sigla] ? self[:descricao].to_s + ' (' + self[:sigla].to_s.upcase + ')' : self[:descricao]
	end

	def codigos_da_hierarquia
		[
			codigo[0].ljust(8, '0'),
			codigo[0..1].ljust(8, '0'),
			codigo[0..2].ljust(8, '0'),
			codigo[0..3].ljust(8, '0'),
			codigo[0..5].ljust(8, '0'),
			codigo[0..6].ljust(8, '0'),
			codigo
		]
	end

	def gerar_natureza_da_receita(configuracoes, gerar_receita_intra, *deducoes)
		# Gera natureza, inclusive as receitas superiores se necessário
		self.codigos_da_hierarquia.uniq.each do |codigo|
			receita_stn = orcamento.receitas_stn.find_by(codigo: codigo)
			if receita_stn
				atributos = receita_stn.attributes.slice("codigo", "descricao", "de_convenio")
				atributos["codigo"] = '00' + receita_stn.attributes["codigo"] + '000000'
				atributos.merge!(configuracoes)
				natureza = Base::NaturezaDaReceita.find_by(codigo: atributos["codigo"], modulo_id: atributos["modulo_id"], modulo_type: atributos["modulo_type"])
				if natureza.nil?
					natureza = Base::NaturezaDaReceita.new(atributos)
					natureza.receita_stn = orcamento.receitas_stn.find_by(codigo: receita_stn.attributes["codigo"])

					if natureza.save
						natureza.cria_receita_intra if gerar_receita_intra
						natureza.cria_deducoes_correspondentes(deducoes) if deducoes.compact.any?
					else
						raise ActiveRecord::Rollback, "Não foi possível criar a natureza da receita" unless natureza.persisted?
					end
				end
			end
		end
	end

	private
	def cria_receitas_filhas
		if gerar_filhas == true
			descricoes = ["Principal", "Multas e Juros de Mora",
				"Dívida Ativa", "Dívida Ativa - Multas e Juros de Mora da Dívida Ativa",
				"Multas", "Juros de Mora", "Dívida Ativa - Multas da Dívida Ativa",
				"Juros de Mora da Dívida Ativa"]

			detalhamentos = [1,2,3,4,5,6,7,8]
			detalhamentos.each {|detalhamento|
				begin
					orcamento.receitas_stn.create(codigo: self.codigo.gsub(/0$/, detalhamento.to_s), descricao: "#{self.descricao} - #{descricoes[detalhamento-1]}", de_convenio: self.de_convenio) if orcamento.present?
				rescue => exception
					p "Erro: #{exception.message}"
					raise ActiveRecord::Rollback
				end
			}

			self.update_attribute(de_convenio: false) if de_convenio
		end
	end

	def buscar_ou_gerar_natureza_da_receita
		if busca_ou_gera_natureza == true
			codigo_formatado = self.codigo.strip.size > 8 ? "#{self.codigo + '000000'}" :"#{'00' + self.codigo + '000000'}"
			natureza_da_receita = Base::NaturezaDaReceita.where(modulo_id: orcamento.id, codigo: codigo_formatado).first

			if !natureza_da_receita.present?
				tipo_de_orcamento = Base::TipoDeOrcamento.where(modulo_id: orcamento.id, codigo: "#{self.descricao.upcase.include?('SOCIAL') || self.descricao.upcase.include?('SAÚDE') ? 'S' : 'F'}").first
				tipo_de_deducao = Loa::TipoDeDeducao.where(orcamento_id: orcamento.id, codigo: codigo_formatado[0..1]).first

				natureza_da_receita = Base::NaturezaDaReceita.new(
					codigo: codigo_formatado,
					descricao: self.descricao[0..199],
					tipo_de_orcamento: tipo_de_orcamento,
					valor_previsto: 0.00,
					modulo_id: orcamento.id,
					modulo_type: 'Orcamento',
					de_convenio: self.de_convenio,
					padrao: true,
					novo_tipo: true,
					categoria_economica: codigo_formatado[0..2],
					origem: codigo_formatado[3],
					especie: codigo_formatado[4],
					rubrica: codigo_formatado[5],
					alinea: codigo_formatado[6..7],
					subalinea: codigo_formatado[8],
					detalhamento_optativo: codigo_formatado[9],
					nivel_opcional_1: codigo_formatado[10..11],
					nivel_opcional_2: codigo_formatado[12..13],
					nivel_opcional_3: codigo_formatado[14..15],
					tipo_de_deducao_id: tipo_de_deducao.id
				)			
			end
			
			natureza_da_receita.receita_stn_id = self.id
			natureza_da_receita.save(validate: false)
		end
	end

	def popula_analitica
		self.analitica = (self.codigo.to_s.last != '0')
		return true
	end

	def self.hash_com_codigos_antigos_e_novos
		ActiveSupport::JSON.decode(File.read("db/data_seeds/base/receitas_stn/correspondencia_receitas.json"))
	end

end
