class Contabilidade::LancamentoDoOrcamentoDaDespesa < ApplicationRecord
	has_paper_trail

	belongs_to :orcamento_da_despesa, class_name: 'Loa::OrcamentoDaDespesa', required: true
	belongs_to :modulo, polymorphic: true, required: true

	validates_presence_of :orcamento_da_despesa_id, :data_do_lancamento, :valor, :modulo_id, :modulo_type
	validates_numericality_of :valor

	validates_uniqueness_of :modulo_id, if: :lancamento_de_dotacao_origem?, scope: :modulo_type, message: 'Só é possivel fazer um lançamento por dotação origem'
	validates_uniqueness_of :modulo_id, if:	:lancamento_de_dotacao_destino?, scope: :modulo_type, message: 'Só é possivel fazer um lançamento por dotação destino'

	after_create :atualiza_sequencia

	validates :modulo_id, immutable: true
	validates :modulo_type, immutable: true

	validates :data_do_lancamento, date: true

	def atualiza_valor_empenhado?
		self.modulo_type == "Contabilidade::Empenho" || self.modulo_type == "Contabilidade::AnulacaoDoEmpenho"
	end

	def lancamento_de_dotacao_origem?
		self.modulo_type == 'Contabilidade::DotacaoOrigem'
	end

	def lancamento_de_dotacao_destino?
		self.modulo_type == 'Contabilidade::DotacaoDestino'
	end

	def saldo_ate_o_lancamento
		(orcamento_da_despesa.valor_fixado.to_f.abs - total_empenhado_ate_o_lancamento.to_f.abs - valor_bloqueado_ate_o_lancamento.to_f.abs - valor_reduzido_na_alteracao_ate_o_lancamento.to_f.abs + valor_anulado_ate_o_lancamento.to_f.abs + (valor_desbloqueio_de_dotacao_ate_o_lancamento.to_f.abs) + valor_acrescentado_na_alteracao_ate_o_lancamento.to_f.abs) rescue 0
	end

	def saldo_antes_do_lancamento
		(orcamento_da_despesa.valor_fixado.to_f.abs - total_empenhado_antes_do_lancamento.to_f.abs - valor_bloqueado_ate_o_lancamento.to_f.abs - valor_reduzido_na_alteracao_antes_do_lancamento.to_f.abs + valor_anulado_antes_do_lancamento.to_f.abs + (valor_desbloqueio_de_dotacao_antes_do_lancamento.to_f.abs)  + valor_acrescentado_na_alteracao_antes_do_lancamento.to_f.abs) rescue 0
	end

	def valor_desbloqueio_de_dotacao_ate_o_lancamento
		orcamento_da_despesa.lancamentos_do_orcamento_da_despesa.where(modulo_type: "Contabilidade::BloqueioDeDotacao").where("contabilidade_lancamentos_do_orcamento_da_despesa.valor < ?", 0).where("contabilidade_lancamentos_do_orcamento_da_despesa.data_do_lancamento <= ?", self.data_do_lancamento).sum(:valor)
	end

	def valor_desbloqueio_de_dotacao_antes_do_lancamento
		orcamento_da_despesa.lancamentos_do_orcamento_da_despesa.where(modulo_type: "Contabilidade::BloqueioDeDotacao").where("contabilidade_lancamentos_do_orcamento_da_despesa.valor < ?", 0).where("contabilidade_lancamentos_do_orcamento_da_despesa.data_do_lancamento < ?", self.data_do_lancamento).sum(:valor)
	end

	def valor_reduzido_na_alteracao_ate_o_lancamento
		orcamento_da_despesa.lancamentos_do_orcamento_da_despesa.where(modulo_type: "Contabilidade::DotacaoOrigem").where("contabilidade_lancamentos_do_orcamento_da_despesa.data_do_lancamento <= ?", self.data_do_lancamento).sum(:valor)
	end

	def valor_reduzido_na_alteracao_antes_do_lancamento
		orcamento_da_despesa.lancamentos_do_orcamento_da_despesa.where(modulo_type: "Contabilidade::DotacaoOrigem").where("contabilidade_lancamentos_do_orcamento_da_despesa.data_do_lancamento < ?", self.data_do_lancamento).sum(:valor)
	end

	def valor_acrescentado_na_alteracao_ate_o_lancamento
		orcamento_da_despesa.lancamentos_do_orcamento_da_despesa.where(modulo_type: "Contabilidade::DotacaoDestino").where("contabilidade_lancamentos_do_orcamento_da_despesa.data_do_lancamento <= ?", self.data_do_lancamento).sum(:valor)
	end

	def valor_acrescentado_na_alteracao_antes_do_lancamento
		orcamento_da_despesa.lancamentos_do_orcamento_da_despesa.where(modulo_type: "Contabilidade::DotacaoDestino").where("contabilidade_lancamentos_do_orcamento_da_despesa.data_do_lancamento < ?", self.data_do_lancamento).sum(:valor)
	end

	def total_empenhado_ate_o_lancamento
		total_empenhado_nos_dias_anteriores = orcamento_da_despesa.lancamentos_do_orcamento_da_despesa.where(modulo_type: "Contabilidade::Empenho").where("contabilidade_lancamentos_do_orcamento_da_despesa.data_do_lancamento < ?", self.data_do_lancamento).sum(:valor).to_d
		total_empenhado_no_mesmo_dia = orcamento_da_despesa.lancamentos_do_orcamento_da_despesa.where(modulo_type: "Contabilidade::Empenho").where("contabilidade_lancamentos_do_orcamento_da_despesa.data_do_lancamento = ? AND contabilidade_lancamentos_do_orcamento_da_despesa.sequencia <= ?", self.data_do_lancamento, self.sequencia).sum(:valor).to_d

		total = (total_empenhado_nos_dias_anteriores + total_empenhado_no_mesmo_dia).to_f
	end

	def total_empenhado_antes_do_lancamento
		total_empenhado_nos_dias_anteriores = orcamento_da_despesa.lancamentos_do_orcamento_da_despesa.where(modulo_type: "Contabilidade::Empenho").where("contabilidade_lancamentos_do_orcamento_da_despesa.data_do_lancamento < ?", self.data_do_lancamento).sum(:valor).to_d
		total_empenhado_no_mesmo_dia = orcamento_da_despesa.lancamentos_do_orcamento_da_despesa.where(modulo_type: "Contabilidade::Empenho").where("contabilidade_lancamentos_do_orcamento_da_despesa.data_do_lancamento = ? AND contabilidade_lancamentos_do_orcamento_da_despesa.sequencia < ?", self.data_do_lancamento, self.sequencia).sum(:valor).to_d

		total = (total_empenhado_nos_dias_anteriores + total_empenhado_no_mesmo_dia).to_f
	end

	def valor_bloqueado_ate_o_lancamento
		orcamento_da_despesa.bloqueio_de_dotacoes.sum(:valor).to_f
	end

	def valor_anulado_ate_o_lancamento
		orcamento_da_despesa.anulacoes_do_empenho.confirmados.where("contabilidade_anulacoes_do_empenho.data_da_anulacao <= ?", self.data_do_lancamento).sum(:valor).to_f
	end

	def valor_anulado_antes_do_lancamento
		orcamento_da_despesa.anulacoes_do_empenho.confirmados.where("contabilidade_anulacoes_do_empenho.data_da_anulacao < ?", self.data_do_lancamento).sum(:valor).to_f
	end

	def atualiza_sequencia
		novo_numero_de_sequencia = 0
		ultimo_lancamento_do_dia = orcamento_da_despesa.lancamentos_do_orcamento_da_despesa.where("contabilidade_lancamentos_do_orcamento_da_despesa.data_do_lancamento = ?", self.data_do_lancamento).order(:sequencia).last
		novo_numero_de_sequencia = ultimo_lancamento_do_dia.sequencia.to_i + 1

		self.update_column(:sequencia, novo_numero_de_sequencia)
	end

	def referente_a
		case self.modulo_type
		when "Contabilidade::Empenho"
			"Lançamento do Empenho \##{self.modulo.try(:numero_do_empenho)}"
		when "Contabilidade::AnulacaoDoEmpenho"
			"Anulação #{self.modulo.try(:tipo_de_anulacao).try(:humanize)} do Empenho \##{self.modulo.try(:empenho).try(:numero_do_empenho)}"
		when "Contabilidade::DotacaoDestino"
			"Alteração Orçamentária - Acréscimo \##{self.modulo.try(:solicitacao_de_alteracao_orcamentaria).try(:id).to_s}"
		when "Contabilidade::DotacaoOrigem"
			"Alteração Orçamentária - Redução \##{self.modulo.try(:solicitacao_de_alteracao_orcamentaria).try(:id).to_s}"
		when "Contabilidade::BloqueioDeDotacao"
			if self.valor >= 0
				"Bloqueio de Dotação - \##{self.modulo.try(:id).to_s}"
			else
				"Desbloqueio de Dotação - \##{self.modulo.try(:id).to_s}"
			end
		when "Loa::OrcamentoDaDespesa"
			"Despesa Fixada"
		else
			""
		end
	end
end
