class Licitacao::ItemDoPedidoPorUnidadeOrcamentaria < ApplicationRecord
	has_paper_trail
	attr_default :quantidade, 0
	attr_default :valor_previsto_desconto, 0
	attr_default :periodicidade, 1

	belongs_to :item_do_pedido, inverse_of: :itens_do_pedido_por_unidade_orcamentaria
	belongs_to :unidade_orcamentaria_por_pedido
	belongs_to :unidade_de_medida

	validates_presence_of :item_do_pedido, :unidade_orcamentaria_por_pedido_id
	validates_uniqueness_of :unidade_orcamentaria_por_pedido_id, scope: :item_do_pedido_id
	validates_numericality_of :quantidade
	#validates_numericality_of :valor_previsto_desconto

	delegate :pedido, to: :item_do_pedido, allow_nil: true
	delegate :pessoas_do_pedido, to: :pedido, allow_nil: true

	validates :periodicidade, presence: true, if: Proc.new {self.unidade_de_medida.present?}
	validates :unidade_de_medida, presence: true, if: Proc.new {self.periodicidade && self.periodicidade > 1}
	validates_numericality_of :periodicidade, greater_than_or_equal_to: 1

	scope :por_valor_previsto, -> { joins(:item_do_pedido).where(licitacao_itens_do_pedido: {por_valor_previsto: true} ) }
	scope :por_valor_previsto_por_preco, -> { joins(:item_do_pedido).where(licitacao_itens_do_pedido: {por_valor_previsto: true, tipo: Licitacao::ItemDoPedido.tipos[:por_preco] } ) }
	scope :por_valor_previsto_por_desconto, -> { joins(:item_do_pedido).where(licitacao_itens_do_pedido: {por_valor_previsto: true, tipo: Licitacao::ItemDoPedido.tipos[:por_desconto] } ) }
	scope :por_quantidade,  -> { joins(:item_do_pedido).where(licitacao_itens_do_pedido: {por_valor_previsto: false} ) }
	#validate :valida_periodicidade, if: Proc.new {self.periodicidade && (unidade_orcamentaria_por_pedido.present? && self.item_do_pedido.pedido.unidade_orcamentaria != self.unidade_orcamentaria_por_pedido.unidade_orcamentaria)}

	def valida_periodicidade
		if self.periodicidade.to_f > self.item_do_pedido.periodicidade_principal.to_f
			errors.add(:periodicidade, "A periodicidade não pode ser maior do que a da unidade principal")
		end
	end

	def menor_valor_cotado(pessoa)
		item_por_pessoa = pessoa.itens_do_pedido_por_pessoa.find_by(item_do_pedido_id: item_do_pedido_id)

		quantidade * item_por_pessoa.try(:preco_de_cotacao).to_d * periodicidade.to_d
	end

	def itens_do_pedido_por_pessoa_valor_previsto(pessoas_do_pedido_ids)
		@itens_do_pedido_por_pessoa_valor_previsto ||= Licitacao::ItemDoPedidoPorPessoa.joins(:item_do_pedido).where(
			licitacao_itens_do_pedido_por_pessoa: {pessoa_do_pedido_id: pessoas_do_pedido_ids},
			licitacao_itens_do_pedido: { por_valor_previsto: true, id: item_do_pedido_id }
		)
	end

	def valor_previsto_preco_medio
		itens_do_pedido_por_pessoa = itens_do_pedido_por_pessoa_valor_previsto(pessoas_do_pedido.ids)
		itens_do_pedido_por_pessoa.sum(&:preco_de_cotacao) / itens_do_pedido_por_pessoa.size rescue 0 
	end

	def valor_previsto_mediana
		itens_do_pedido_por_pessoa = itens_do_pedido_por_pessoa_valor_previsto(pessoas_do_pedido.ids)
		
		itens_ordenados = itens_do_pedido_por_pessoa.sort
		size = itens_ordenados.size

		if size.even?
			return(itens_ordenados[size/2 - 1] + itens_ordenados[size/2]) / 2.0
		else
			return itens_ordenados[size/2]
		end
	end

	def menor_cotacao_por_valor_previsto_lote
		itens_do_pedido_por_pessoa_valor_previsto(pessoas_do_pedido.ids).minimum(:preco_de_cotacao)
	end

	def menor_cotacao_por_valor_previsto_global
		itens_do_pedido_por_pessoa_valor_previsto([pessoas_do_pedido.pessoas_que_cotaram_todos.min_by(&:total_da_cotacao)]).sum(:preco_de_cotacao) rescue 0
	end

	def valor_previsto_total_menor_preco(forma_de_agrupamento)
		return 0 if item_do_pedido.por_desconto?

		menor_valor_cotado = forma_de_agrupamento.eql?('global') ? menor_cotacao_por_valor_previsto_global : menor_cotacao_por_valor_previsto_lote
		valor_previsto_desconto + (menor_valor_cotado / item_do_pedido.unidades_que_cotaram_item.size)
	end

	def valor_previsto_total_preco_medio
		return 0 if item_do_pedido.por_desconto?
		valor_previsto_desconto + (valor_previsto_preco_medio / item_do_pedido.unidades_que_cotaram_item.size)
	end

	def valor_previsto_total_mediana
		return 0 if item_do_pedido.por_desconto?
		valor_previsto_desconto + (valor_previsto_mediana / item_do_pedido.unidades_que_cotaram_item.size)
	end
end
