class Licitacao::ItemDoOrcamentoDaDespesaPorProjeto < ApplicationRecord
	has_paper_trail

	delegate :projeto, to: :orcamento_da_despesa_por_projeto
	delegate :unidade_orcamentaria, to: :orcamento_da_despesa_por_projeto

	belongs_to :orcamento_da_despesa_por_projeto, class_name: "Licitacao::OrcamentoDaDespesaPorProjeto"
	belongs_to :item_do_lote, class_name: 'Licitacao::ItemDoLote'

	validates_numericality_of :quantidade, greater_than: 0
	validates_numericality_of :total_por_item, greater_than: 0
	validates_presence_of :quantidade

	validate :valida_quantidade_de_itens, if: Proc.new {self.projeto.pedido.por_quantidade?}
	validate :valida_valor_destinado_de_itens, if: Proc.new {self.projeto.pedido.por_valor_previsto?}
	validate :valida_valor_total_do_item, if: Proc.new {self.projeto.pedido.por_quantidade?}

	def quantidade_vinculada_em_outras_dotacoes
		projeto.itens_dos_orcamentos_da_despesa_por_projeto.joins(orcamento_da_despesa_por_projeto: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]]]).where.not(id: self.id).where(item_do_lote: item_do_lote).where(loa_unidades_orcamentarias: {id: unidade_orcamentaria.id}).sum(:quantidade)
	end

	def quantidade_vinculada
		quantidade_vinculada_em_outras_dotacoes + self.quantidade
	end

	def valor_vinculada_em_outras_dotacoes
		projeto.itens_dos_orcamentos_da_despesa_por_projeto.joins(orcamento_da_despesa_por_projeto: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]]]).where.not(id: self.id).where(item_do_lote: item_do_lote).where(loa_unidades_orcamentarias: {id: unidade_orcamentaria.id}).sum(:total_por_item)
	end

	def valor_vinculado
		valor_vinculada_em_outras_dotacoes + self.total_por_item
	end

	def saldo_da_quantidade
		item_do_lote.itens_por_unidade(unidade_orcamentaria.id).to_d - quantidade_vinculada.to_d
	end

	def saldo_do_valor_previsto
		item_do_lote.itens_por_unidade_valor_previsto(unidade_orcamentaria.id).to_d - valor_vinculado.to_d
	end

	def saldo_de_quantidade_a_vincular
		item_do_lote.itens_por_unidade(unidade_orcamentaria.id).to_d - quantidade_vinculada_em_outras_dotacoes.to_d
	end

	def saldo_de_valor_previsto_a_vincular
		item_do_lote.itens_por_unidade_valor_previsto(unidade_orcamentaria.id).to_d - valor_vinculada_em_outras_dotacoes.to_d
	end

	def valor_pela_quantidade
		quantidade.to_f * item_do_lote.valor_unitario.to_f
	end

	def valor
		return total_por_item.to_f if total_por_item.present?
		valor_pela_quantidade
	end

	private

	def valida_quantidade_de_itens
		if item_do_lote.present? && quantidade.present? && saldo_da_quantidade.to_f < 0
			errors.add(:quantidade, "não pode ser maior que a quantidade de itens licitada pela unidade. Saldo para vincular: #{saldo_de_quantidade_a_vincular.to_f}")
		end
	end

	def valida_valor_destinado_de_itens
		if item_do_lote.present? && total_por_item.present? && saldo_do_valor_previsto.to_f < 0
			errors.add(:total_por_item, "não pode ser maior que a quantidade de itens licitada pela unidade. Saldo para vincular: #{saldo_de_valor_previsto_a_vincular.to_f}")
		end
	end

	def valida_valor_total_do_item
		return if quantidade.blank? || total_por_item.blank?

		if total_por_item.to_f < valor_pela_quantidade.to_f - 0.1 || total_por_item.to_f > valor_pela_quantidade.to_f + 0.1
			msg = 'deve ser igual a quantidade * valor unitário com uma margem de até 10 centavos'
			errors.add(:total_por_item, msg)
		end
	end
end
