class Contabilidade::DotacaoDestino < ApplicationRecord
	has_paper_trail
	attr_accessor :subacao_id
	attr_accessor :elemento_de_despesa_id
	attr_accessor :fonte_de_recurso_id

	belongs_to :solicitacao_de_alteracao_orcamentaria, foreign_key: "solicitacao_de_alteracao_orcamentaria_id"
	belongs_to :orcamento_da_despesa, foreign_key: "dotacao_id", class_name: 'Loa::OrcamentoDaDespesa',required: true

	has_one :lancamento_do_orcamento_da_despesa, as: :modulo, class_name: 'Contabilidade::LancamentoDoOrcamentoDaDespesa'

	validate :verifica_valor_edicao, if: Proc.new { solicitacao_de_alteracao_orcamentaria.try(:confirmado?) & self.valor_changed? }

	#validates_presence_of :solicitacao_de_alteracao_orcamentaria_id, :dotacao_id -Foi retirado pois com essa validação não funciona solicitações de alteracoes orcamentarias criadas a partir de decretos
	validates_presence_of :valor, if: Proc.new { self.dotacao_id.present? }
	validates_presence_of :subacao_id, :elemento_de_despesa_id, :fonte_de_recurso_id, :valor, if: Proc.new { self.solicitacao_de_alteracao_orcamentaria_criada_no_administrativo? }
	
	# Lançamento do Orçamento da Despesa
	before_destroy :verifica_valor, if: Proc.new { solicitacao_de_alteracao_orcamentaria.try(:confirmado?)}
	after_destroy :apagar_movimento_orcamentario
	after_initialize :atribui_dotacao_baseado_na_fonte_e_elemento_de_despesa_por_subacao
	after_initialize :retorna_atributos_baseado_no_orcamento_da_despesa

	def nao_pode_ser_deletado?
		(orcamento_da_despesa.try(:saldo).to_f  - valor_was.to_f) < 0
	end

	def to_sim(data_referencia)
		begin
			exercicio_do_orcamento = solicitacao_de_alteracao_orcamentaria.orcamento.exercicio.to_s
			decreto = solicitacao_de_alteracao_orcamentaria.decreto
			unidade_orcamentaria = orcamento_da_despesa.unidade_orcamentaria

			texto = ""
			texto << "701".sim_preenche(3) + "," #01
			texto << Configuracao.first.codigo_do_municipio_no_tcm.sim_preenche(3) + "," #02
			texto << exercicio_do_orcamento.sim_limite_sem_aspas(6, "00") + "," #03
			texto << decreto.try(:data_da_legislacao).sim_data + "," #04
			texto << numero_da_alteracao_orcamentaria.to_s + "," #05
			texto << unidade_orcamentaria.orgao.codigo.sim_preenche(2) + "," #06
			texto << unidade_orcamentaria.codigo.to_s.codigo_uo_to_sim + "," #07
			texto << orcamento_da_despesa.subacao.funcao.codigo.sim_limite(2)  + "," #08
			texto << orcamento_da_despesa.subacao.subfuncao.codigo.sim_limite(3) + "," #09
			texto << orcamento_da_despesa.acao.programa_de_governo.codigo.sim_limite(4) + "," #10
			texto << orcamento_da_despesa.acao.natureza_da_acao.codigo.sim_limite(1) + "," #11
			texto << orcamento_da_despesa.acao.codigo.sim_limite(3) + "," #12
			texto << orcamento_da_despesa.subacao.codigo.to_s.sim_preenche(4) + "," #Número do Subprojeto ou Subatividade
			texto << orcamento_da_despesa.elemento_de_despesa.codigo.sim_preenche(8) + "," #14
			texto << orcamento_da_despesa.fonte_de_recursos.codigo_completo.first(1).sim_limite(1) + "," #15
			texto << orcamento_da_despesa.fonte_de_recursos.codigo_completo.last(9).sim_limite(9) + "," #16
			texto << data_referencia.to_s + "," #17
			texto << (decreto.credito_especial? ? decreto&.lei_autorizativa : decreto&.numero_da_lei_sim).to_s.sim_limite(10) + "," #18
			texto << solicitacao_de_alteracao_orcamentaria.decreto.numero.sim_limite(10) + "," #19
			texto << solicitacao_de_alteracao_orcamentaria.tipo_de_credito_to_sim.sim_limite(1) + "," #20
			texto << solicitacao_de_alteracao_orcamentaria.origem_do_recurso_to_sim.sim_limite(1) + "," #21
			if solicitacao_de_alteracao_orcamentaria.superavit_financeiro?
				texto << valor.round(2).to_d.to_s.sim_valor + "," #22
			else
				texto << "0.00,"#22
			end
			if solicitacao_de_alteracao_orcamentaria.execesso_de_arrecadacao?
				texto << valor.round(2).to_d.to_s.sim_valor + "," #23
			else
				texto << "0.00,"#23
			end
			if solicitacao_de_alteracao_orcamentaria.operacao_de_credito?
				texto << valor.round(2).to_d.to_s.sim_valor + "," #24
			else
				texto << "0.00,"#24
			end
			if solicitacao_de_alteracao_orcamentaria.anulacao_de_dotacao?
				texto << valor.round(2).to_d.to_s.sim_valor #25
			else
				texto << "0.00"#25
			end

			return texto
		rescue => e
			if e.class.to_s == "NoMethodError"
				atributo_falho = e.message.split(" ")[2]
				coluna = CSV.parse(texto, :headers => false).last.count
				raise e.mensagem_traduzida(self, "", atributo_falho, coluna)
			else
				raise e
			end
		end
	end

	def to_sim_elementos
		begin
			exercicio_do_orcamento = solicitacao_de_alteracao_orcamentaria.orcamento.exercicio.to_s
			
			texto = ""
			texto << "204".to_s.sim_preenche(3) + "," #1
			texto << Configuracao.first.codigo_do_municipio_no_tcm.to_s.sim_preenche(3) + "," #2
			texto << exercicio_do_orcamento + '00' + "," #3
			texto << orcamento_da_despesa.subacao.unidade_orcamentaria.orgao.codigo.to_s.sim_preenche(2) + "," #Código do Órgão
			texto << orcamento_da_despesa.subacao.unidade_orcamentaria.codigo.to_s.codigo_uo_to_sim + "," #Código da Unidade Orçamentária
			texto << orcamento_da_despesa.subacao.funcao.codigo.to_s.sim_preenche(2) + "," #Código da Função
			texto << orcamento_da_despesa.subacao.subfuncao.codigo.to_s.sim_preenche(3) + "," #Código da Subfunção
			texto << orcamento_da_despesa.subacao.acao.programa_de_governo.codigo.to_s.sim_preenche(4) + "," #Código do Programa
			texto << orcamento_da_despesa.subacao.acao.natureza_da_acao.codigo.to_s.sim_limite(1) + "," #Código de Projeto ou Atividade
			texto << orcamento_da_despesa.subacao.acao.codigo.to_s.sim_preenche(3) + "," #Número do Projeto ou Atividade
			texto << orcamento_da_despesa.subacao.codigo.to_s.sim_preenche(4) + "," #Número do Subprojeto ou Subatividade
			texto << orcamento_da_despesa.elemento_de_despesa.codigo.to_s.sim_limite(8) + "," #Código do Elemento de Despesa
			texto << orcamento_da_despesa.fonte_de_recursos.codigo_completo.to_s.sim_limite(1) + "," #Código do Grupo da Fonte
			texto << orcamento_da_despesa.fonte_de_recursos.codigo_sim + "," #Código da Especificação da Fonte
			texto << valor.to_s.sim_valor #Valor fixado
			return texto
		rescue => e
			if e.class.to_s == "NoMethodError"
				atributo_falho = e.message.split(" ")[2]
				coluna = CSV.parse(texto, :headers => false).last.count
				raise e.mensagem_traduzida(self, "", atributo_falho, coluna)
			else
				raise e
			end
		end
	end

	def dotacao_ja_utilizada_no_decreto?
		Contabilidade::DotacaoDestino.joins(:solicitacao_de_alteracao_orcamentaria).includes(:solicitacao_de_alteracao_orcamentaria).where(dotacao_id: self.dotacao_id).where("contabilidade_solicitacao_de_alteracao_orcamentarias.status = 4 and decreto_id = ? and contabilidade_dotacoes_destino.id <> ?", self.solicitacao_de_alteracao_orcamentaria.decreto_id , self.id).exists?
	end

	# def to_sim_fonte_anulacao(data_referencia)
	# 	begin
	# 		exercicio_do_orcamento = solicitacao_de_alteracao_orcamentaria.orcamento.exercicio.to_s
	# 		decreto = solicitacao_de_alteracao_orcamentaria.decreto
	# 		unidade_orcamentaria = orcamento_da_despesa.unidade_orcamentaria

	# 		texto = ""
	# 		texto << "702".sim_preenche(3) + "," #01
	# 		texto << Configuracao.first.codigo_do_municipio_no_tcm.sim_preenche(3) + "," #02
	# 		texto << exercicio_do_orcamento.sim_limite_sem_aspas(6, "00") + "," #03
	# 		texto << solicitacao_de_alteracao_orcamentaria.decreto.try(:data_da_legislacao).sim_data + "," #04
	# 		texto << self.id.to_s  + "," #05
	# 		texto << unidade_orcamentaria.orgao.codigo.sim_preenche(2) + "," #06
	# 		texto << unidade_orcamentaria.codigo.to_s.sim_preenche(2) + "," #07
	# 		texto << orcamento_da_despesa.subacao.funcao.codigo.sim_limite(2)  + "," #08
	# 		texto << orcamento_da_despesa.subacao.subfuncao.codigo.sim_limite(3) + "," #09
	# 		texto << orcamento_da_despesa.acao.programa_de_governo.codigo.sim_limite(4) + "," #10
	# 		texto << orcamento_da_despesa.acao.natureza_da_acao.codigo.sim_limite(1) + "," #11
	# 		texto << orcamento_da_despesa.acao.codigo.sim_limite(3) + "," #12
	# 		texto << (orcamento_da_despesa.subacao.codigo.present? ? orcamento_da_despesa.subacao.codigo.sim_preenche(4) : '"0000"') + "," #13
	# 		texto << orcamento_da_despesa.elemento_de_despesa.codigo.sim_preenche(8) + "," #14
	# 		texto << orcamento_da_despesa.fonte_de_recursos.codigo_completo.first(1).sim_limite(1) + "," #15
	# 		texto << orcamento_da_despesa.fonte_de_recursos.codigo_completo.last(9).sim_limite(9) + "," #16
	# 		texto << self.valor.round(2).to_f.to_s.sim_valor rescue "0.00" + "," #17
	# 		texto << data_referencia.to_s + "," #18

	# 		return texto
	# 	rescue => e
	# 		if e.class.to_s == "NoMethodError"
	# 			atributo_falho = e.message.split(" ")[2]
	# 			coluna = CSV.parse(texto, :headers => false).last.count
	# 			raise e.mensagem_traduzida(self, "", atributo_falho, coluna)
	# 		else
	# 			raise e
	# 		end
	# 	end
	# end

	def to_sim_remanejamentos_transposicoes_e_transferencias(data_referencia)
		begin
			exercicio_do_orcamento = solicitacao_de_alteracao_orcamentaria.orcamento.exercicio.to_s
			decreto = solicitacao_de_alteracao_orcamentaria.decreto
			unidade_orcamentaria = orcamento_da_despesa.unidade_orcamentaria

			texto = ""
			texto << "704".sim_preenche(3) + "," #01
			texto << Configuracao.first.codigo_do_municipio_no_tcm.sim_preenche(3) + "," #02
			texto << exercicio_do_orcamento.sim_limite_sem_aspas(6, "00") + "," #03
			texto << solicitacao_de_alteracao_orcamentaria.decreto.try(:data_da_legislacao).sim_data + "," #04
			texto << numero_da_alteracao_orcamentaria.to_s + "," #05
			texto << unidade_orcamentaria.orgao.codigo.sim_preenche(2) + "," #06
			texto << unidade_orcamentaria.codigo.to_s.codigo_uo_to_sim + "," #07
			texto << orcamento_da_despesa.subacao.funcao.codigo.sim_limite(2)  + "," #08
			texto << orcamento_da_despesa.subacao.subfuncao.codigo.sim_limite(3) + "," #09
			texto << orcamento_da_despesa.acao.programa_de_governo.codigo.sim_limite(4) + "," #10
			texto << orcamento_da_despesa.acao.natureza_da_acao.codigo.sim_limite(1) + "," #11
			texto << orcamento_da_despesa.acao.codigo.sim_limite(3) + "," #12
			texto << orcamento_da_despesa.subacao.codigo.to_s.sim_preenche(4) + "," #13
			texto << orcamento_da_despesa.elemento_de_despesa.codigo.sim_preenche(8) + "," #14
			texto << orcamento_da_despesa.fonte_de_recursos.codigo_completo.first(1).sim_limite(1) + "," #15
			texto << orcamento_da_despesa.fonte_de_recursos.codigo_completo.last(9).sim_limite(9) + "," #16
			texto << data_referencia.to_s + "," #17
			# campo 18 esta na fdunção gerar_destinacao_remanejamentos_transposicoes_e_transferencias do lote.rb

			return texto
		rescue => e
			if e.class.to_s == "NoMethodError"
				atributo_falho = e.message.split(" ")[2]
				coluna = CSV.parse(texto, :headers => false).last.count
				raise e.mensagem_traduzida(self, "", atributo_falho, coluna)
			else
				raise e
			end
		end
	end

	def atribui_dotacao_baseado_na_fonte_e_elemento_de_despesa_por_subacao
		if self.elemento_de_despesa_id.present? && self.fonte_de_recurso_id.present?
			elemento_de_despesa_por_subacao_id =  Loa::ElementoDeDespesaPorSubacao.find_by(subacao_id: self.subacao_id, elemento_de_despesa: self.elemento_de_despesa_id).try(:id)
			self.dotacao_id = Loa::OrcamentoDaDespesa.find_by(fonte_de_recursos_id: self.fonte_de_recurso_id, elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao_id).try(:id)
		end
	end

	def retorna_elementos_de_despesa
		Base::ElementoDeDespesa.ativos.joins(:elementos_de_despesa_por_subacao).where(
			loa_elementos_de_despesa_por_subacao: {
				subacao_id: self.subacao_id
			},
			base_elementos_de_despesa: {
				exibir_elemento_de_despesa: true
			}
		)
	end

	def retorna_fontes_de_recursos
		Base::FonteDeRecursos.joins(:subacoes).where(
			loa_subacoes:{
				id: self.subacao_id
			}
		).uniq
	end

	def retorna_atributos_baseado_no_orcamento_da_despesa
		if self.solicitacao_de_alteracao_orcamentaria.present? && self.orcamento_da_despesa.present? && self.solicitacao_de_alteracao_orcamentaria.avulso?
			self.subacao_id = self.orcamento_da_despesa.subacao.id
			self.elemento_de_despesa_id = self.orcamento_da_despesa.elemento_de_despesa.id
			self.fonte_de_recurso_id = self.orcamento_da_despesa.fonte_de_recursos_id
		end
	end

	def solicitacao_de_alteracao_orcamentaria_criada_no_administrativo?
		self.solicitacao_de_alteracao_orcamentaria.present? && self.solicitacao_de_alteracao_orcamentaria.avulso?
	end

	private
	def apagar_movimento_orcamentario
		lancamento_do_orcamento_da_despesa.try(:destroy)
	end

	def verifica_valor
		if (orcamento_da_despesa.saldo.to_f - valor.to_f) < 0
			raise Exception.new("Não pode ser excluída por que o saldo da dotação ficara negativo.")
		end
	end

	def verifica_valor_edicao
		if self.valor_was > self.valor
			valor_da_dotacao_alterado = (orcamento_da_despesa.saldo - self.valor_was + self.valor)
			if valor_da_dotacao_alterado < 0
				errors.add(:valor, "Não pode ser alterada para esse valor por que o saldo da dotação ficara negativo em #{valor_da_dotacao_alterado.to_f.round(2)}.")
			end
		end
	end

end
