class Contabilidade::DotacaoOrigem  < ApplicationRecord
	attr_accessor :subacao_id
	attr_accessor :elemento_de_despesa_id
	attr_accessor :fonte_de_recurso_id

	has_paper_trail
	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'

	validates_presence_of :solicitacao_de_alteracao_orcamentaria_id, :dotacao_id
	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
	after_destroy :apagar_movimento_orcamentario

	after_save :apaga_a_si_mesmo_se_valor_da_acao_igual_a_zero
	after_initialize :atribui_dotacao_baseado_na_fonte_e_elemento_de_despesa_por_subacao
	after_initialize :retorna_atributos_baseado_no_orcamento_da_despesa

	validate :verifica_saldo_para_permitir_reducao

	def apaga_a_si_mesmo_se_valor_da_acao_igual_a_zero
		if self.valor.to_f <= 0 || self.valor.nil?
			self.delete
		end
  end

	def numero_da_alteracao_anulacoes
		self.solicitacao_de_alteracao_orcamentaria.dotacoes_origem.order(:id).first.numero_da_alteracao_orcamentaria
	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 << "703".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) + "," #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
			texto << (decreto.credito_especial? ? decreto&.lei_autorizativa : decreto&.numero_da_lei_sim).to_s.sim_limite(10) + "," #18
			texto << solicitacao_de_alteracao_orcamentaria.tipo_alteracao_orcamentaria_to_sim.sim_limite(1) + "," #19
			# o campo 20 é preenchido na função gerar_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 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 << decreto.try(:data_da_legislacao).sim_data + "," #04
			texto << numero_da_alteracao_anulacoes.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 << (self.valor.present? ? self.valor.round(2).to_f.to_s.sim_valor : "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 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 dotacao_ja_utilizada_no_decreto?
		Contabilidade::DotacaoOrigem.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_origem.id <> ?", self.solicitacao_de_alteracao_orcamentaria.decreto_id , self.id).exists?
	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
	
	def verifica_saldo_para_permitir_reducao
		if self.solicitacao_de_alteracao_orcamentaria.origem_do_recurso == "anulacao_de_dotacao"
			if ((self.orcamento_da_despesa.saldo + self.valor_was.to_d - self.valor.to_d) < 0)
				errors.add(:valor, "O valor não pode ser alterado ou o saldo da dotação ficará em negativo")
			end
		end
	end
	private

	def apagar_movimento_orcamentario
		lancamento_do_orcamento_da_despesa.try(:destroy)
	end

end
