class Contabilidade::ContaPorEventoContabil < ApplicationRecord
	has_paper_trail
	attr_accessor :utilizando_form

	attr_accessor :gerar_conta_par

	attr_default :conta_principal, true
	attr_default :gerar_conta_par, true

	belongs_to :conta_par, class_name: 'Contabilidade::Conta'
	belongs_to :evento_contabil, required: true
	belongs_to :conta, required: true

	has_many :movimentacoes_do_plano_de_contas, dependent: :restrict_with_exception

	before_validation :incrementa_ordem_de_lancamento, if: Proc.new{evento_contabil_id.present?}

	delegate :codigo_formatado_e_nome, to: :conta, allow_nil: true

	validates_uniqueness_of :ordem_de_lancamento, scope: :evento_contabil_id

	validates_presence_of :evento_contabil_id, :conta_id, :tipo_de_lancamento, :ordem_de_lancamento
	validates :conta_par_id, presence: true, if: proc { utilizando_form.present? }

	validate :uniqueness_of_par_de_contas, if: Proc.new{ evento_contabil_id.present? && conta_par_id.present? && conta_principal? }
	validate :conta_deve_ser_analitica

	before_validation :atribui_tipo_de_lancamento, if: proc { tipo_de_lancamento.nil? }

	before_save :atualiza_conta_por_evento_contabil_par, if: proc { debito? && conta_por_evento_contabil_par.present? && gerar_conta_par == true }
	after_save :cria_conta_por_evento_contabil_par, if: proc { debito? && conta_por_evento_contabil_par.nil? && gerar_conta_par == true }

	after_destroy :deleta_conta_por_evento_contabil_par, if: proc { debito? && conta_por_evento_contabil_par.present? }

	enum tipo_de_lancamento: {
		debito: 0,
		credito: 1
	}

	def pertence_ao_mesmo_grupo_de_conta? conta_par
		unless self.conta.grupo_de_conta_id.eql?(conta_par.conta.grupo_de_conta_id)
			errors.add(:base, 'As contas selecionadas não pertencem ao mesmo grupo de contas.')
			return false
		else
			return true
		end
	end

	def conta_deve_ser_analitica
		unless self.conta.present? && self.conta.analitica?
			#errors.add(:conta_id, 'deve ser analítica')
		end
	end

	def conta_por_evento_contabil_par
		evento_contabil.contas_por_eventos_contabeis.find_by(conta_id: conta_par_id_was, conta_par_id: conta_id_was)
	end

	private
	def cria_conta_por_evento_contabil_par
		Contabilidade::ContaPorEventoContabil.create(
			conta_id: conta_par_id,
			evento_contabil_id: evento_contabil_id,
			tipo_de_lancamento: "credito",
			conta_par_id: conta_id,
			conta_principal: true,
		)
	end

	def atualiza_conta_por_evento_contabil_par
		conta_por_evento_contabil_par.update_attributes(conta_id: conta_par_id, conta_par_id: conta_id)
	end

	def deleta_conta_por_evento_contabil_par
		conta_por_evento_contabil_par.destroy
	end

	def incrementa_ordem_de_lancamento
		ordens_utilizadas = Contabilidade::ContaPorEventoContabil.where(evento_contabil_id: self.evento_contabil_id).order(:ordem_de_lancamento).pluck(:ordem_de_lancamento)
		self.ordem_de_lancamento = ordens_utilizadas.empty? ? 1 : ordens_utilizadas.last + 1
	end

	def uniqueness_of_par_de_contas
		par,impar = nil
		if self.ordem_de_lancamento % 2 == 0
			[2,4,6].each do |par|
				par = Contabilidade::ContaPorEventoContabil.find_by(evento_contabil_id: self.evento_contabil_id, conta_id: self.conta_id, conta_par_id: self.conta_par_id, ordem_de_lancamento: self.ordem_de_lancamento)
				break if par.present?
			end
		else
			[1,3,5].each do |impar|
				impar = Contabilidade::ContaPorEventoContabil.find_by(evento_contabil_id: self.evento_contabil_id, conta_id: self.conta_id, conta_par_id: self.conta_par_id, ordem_de_lancamento: self.ordem_de_lancamento)
				break if impar.present?
			end
		end

		errors.add(:base, 'O par de contas selecionado já existe no evento contábil.') if par.present? || impar.present?
	end

	def atribui_tipo_de_lancamento
		self.tipo_de_lancamento = "debito"
	end
end
