class Licitacao::Lote < ApplicationRecord
	has_paper_trail
	include AASM
	include IncrementadorDeCodigoConcern
	include TradutorConcern

	attr_default :lances_abertos, false
	attr_default :status, 'ativo'

	validates_presence_of :criterio_de_julgamento, on: :update
	validates_presence_of :justificativa, on: :update, if: Proc.new { self.tecnica_e_preco? && self.criterio_de_julgamento_was.eql?("tecnica_e_preco") && self.projeto.em_sessao?}
	validates_presence_of :ganhador_id, on: :update, if: Proc.new { self.tecnica_e_preco? && self.criterio_de_julgamento_was.eql?("tecnica_e_preco") && self.projeto.em_sessao?}

	belongs_to :processo, foreign_key: :projeto_id
	belongs_to :ganhador, class_name: 'Licitacao::PessoaDoProjeto', foreign_key: :ganhador_id, inverse_of: :lotes_ganhos

	has_many :rodadas, dependent: :destroy
	has_many :lances, through: :rodadas
	has_many :itens_do_lote, class_name: 'Licitacao::ItemDoLote', dependent: :destroy
	has_many :itens_do_projeto_por_pessoa, through: :itens_do_lote, class_name: 'Licitacao::ItemDoProjetoPorPessoa'
	has_many :pessoas_do_projeto_do_lote, class_name: 'Licitacao::PessoaDoProjetoDoLote', dependent: :destroy
	has_many :pessoas_do_projeto, through: :pessoas_do_projeto_do_lote
	has_many :lotes_do_contrato, class_name: 'Licitacao::LoteDoContrato'
	has_many :contratos, through: :lotes_do_contrato, class_name: 'Licitacao::Contrato'

	accepts_nested_attributes_for :rodadas
	accepts_nested_attributes_for :pessoas_do_projeto_do_lote, reject_if: :all_blank, allow_destroy: true
	accepts_nested_attributes_for :itens_do_lote

	alias_method :projeto, :processo

	scope :anulados, -> { where('anulado = ? OR status <> ?', true, Licitacao::Lote.status[:ativo]) }
	scope :ativos, -> { where(status: Licitacao::Lote.status[:ativo], anulado: false) }
	scope :nao_nulos, -> { where(anulado: false) }
	scope :homologados, -> { where('anulado = ? AND status in (?)', false, [Licitacao::Lote.status[:ativo], Licitacao::Lote.status[:homologado]]) }

	before_validation :atribui_numero, if: Proc.new { |lote| self.new_record? || itens_do_lote.ativos.any? }
	before_validation :atribui_ganhador, if: :melhor_tecnica?

	before_update do
		primeiro_colocado unless rodadas.empty? || lances_abertos
	end

	validate :projeto_nao_deve_ter_mais_de_um_lote, if: Proc.new { |lote| projeto.try(:global?) }
	validate :modalidade_de_licitacao_deve_ser_pregao, if: :lances_abertos
	validate :licitacao_deve_estar_em_processo, if: :lances_abertos

	validates_associated :pessoas_do_projeto_do_lote
	validates_associated :itens_do_lote


	enum criterio_de_julgamento: {
		menor_preco: 1,
		melhor_tecnica: 2,
		tecnica_e_preco: 4,
		maior_desconto: 5,
		melhor_tecnica_ou_conteudo_artistico: 6,
		nao_se_aplica: 7,
		maior_retorno_economico: 8,
		conteudo_artistico: 9
	}

	enum tipo: {
		produto: 0,
		servico: 1
	}

	enum status: {
		ativo: 0,
		fracassado: 1,
		cancelado: 2,
		deserto: 3,
		homologado: 4
	}

	enum tipo_de_agrupamento: {
		por_preco_e_quantidade: 1,
		por_preco_e_valor_previsto: 2,
		por_desconto_e_valor_previsto: 3
	}

	# BOOLEANS
	def lances_fechados?
		!lances_abertos
	end

	def lote_por_preco?
		itens_do_lote.joins(:item_do_pedido).where(licitacao_itens_do_pedido: {tipo: Licitacao::ItemDoPedido.tipos["por_preco"]}).size > 0
	end

	def lote_por_desconto?
		itens_do_lote.joins(:item_do_pedido).where(licitacao_itens_do_pedido: {tipo: Licitacao::ItemDoPedido.tipos["por_desconto"]} ).size > 0
	end

	def lote_por_valor_previsto?
		itens_do_lote.joins(item_do_pedido: :itens_do_pedido_por_unidade_orcamentaria).where('licitacao_itens_do_pedido_por_unidade_orcamentaria.valor_previsto_desconto > 0').distinct.size > 0
	end

	def pode_ser_fracassado?
		(!processo.homologado? || processo.homologado_parcialmente?) && !processo.adjudicado? && !fracassado? && ((tem_proposta_inicial? && !tem_proposta_final? && !processo.tomada_de_precos?) || (processo.tomada_de_precos? && pessoas_do_projeto.any? && !pessoas_do_projeto.credenciados.any?))
	end

	def pode_ser_desertado?
		processo.sessao_iniciada? && !processo.cancelado? && (!processo.homologado? || processo.homologado_parcialmente?) && !deserto? && ((!tem_licitante_com_cotacoes? && !processo.tomada_de_precos?) || (processo.tomada_de_precos? && !pessoas_do_projeto.any?))
	end

	def pode_ter_lances?
		if processo.lei_8666_93?
			processo.pregao? && ( processo.em_sessao? || ( processo.homologado? && processo.homologado_parcialmente? && self.ganhador_id.nil? ) ) && !eh_dispensa_ou_carona_antiga_licitacao? && !processo.outro? && !processo.por_item? && (!melhor_tecnica? && !melhor_tecnica_ou_conteudo_artistico? && !tecnica_e_preco?) && !fracassado? && !deserto? && (processo.pedido.projeto_simplificado == false)
		elsif processo.lei_14133_21?
			((!eh_inexigibilidade_ou_carona? && processo.em_sessao?) || (processo.dispensa_de_licitacao? && processo.enviado_para_comissao?))  && (!melhor_tecnica? && !melhor_tecnica_ou_conteudo_artistico? && !tecnica_e_preco?) && !fracassado? && !deserto? 
		end
	end

	def eh_dispensa_ou_carona_nova_licitacao?
		((processo.dispensa_de_licitacao? || processo.dispensa_de_chamamento?) || processo.carona?) && processo.lei_14133_21?
	end

	def eh_inexigibilidade_ou_carona?
		(processo.inexigibilidade_de_licitacao? || processo.carona?) && processo.lei_14133_21?
	end

	def eh_dispensa_ou_carona_antiga_licitacao?
		(processo.eh_dispensa_ou_inexigibilidade? || processo.carona?) && processo.lei_8666_93?
	end

	def pode_ter_historico_de_lances?
		processo.pregao? && processo.em_sessao? && !processo.eh_dispensa_ou_inexigibilidade? && !processo.carona? && !processo.outro? && fracassado? && (!melhor_tecnica? && !melhor_tecnica_ou_conteudo_artistico?)
	end

	def pode_receber_nota?
		!processo.eh_dispensa_ou_inexigibilidade? && !processo.carona? && !ganhador.present? && !processo.outro? && (melhor_tecnica? || melhor_tecnica_ou_conteudo_artistico?) && tem_licitante_com_cotacoes? && !fracassado? &&
			!deserto? && ((processo.pedido.projeto_simplificado? && processo.homologado?) || processo.em_sessao?)
	end

	def nao_eh_dispensa_nem_carona?
		!processo.eh_dispensa_ou_inexigibilidade? && !processo.carona? && !processo.outro?
	end

	def eh_simplificado?
		processo.pedido.projeto_simplificado? && processo.homologado?
	end

	def lote_pode_definir_ou_salvar_ganhador?
		((!processo.pregao? || eh_simplificado?) && !ganhador.present? &&  tem_licitante_com_cotacoes? && !fracassado? && !deserto?) || ((processo.eh_dispensa_ou_inexigibilidade? && processo.lei_8666_93? || processo.eh_dispensa_ou_inexigibilidade? && processo.lei_14133_21?) && !ganhador.present?  &&  tem_licitante_com_cotacoes?) 
	end

	def pode_definir_ganhador?
		(tecnica_e_preco? || maior_desconto?) && lote_pode_definir_ou_salvar_ganhador?
	end

	def pode_salvar_ganhador?
		menor_preco? && lote_pode_definir_ou_salvar_ganhador?
	end

	def tem_proposta_inicial?
		itens_do_projeto_por_pessoa.iniciais.validos.any?
	end

	def tem_proposta_final?
		itens_do_projeto_por_pessoa.finais.validos.any?
	end

	def todos_os_itens_do_lote_tem_cotacoes?
		self.pessoas_do_projeto_com_cotacao.each do |pessoa_do_projeto|
			existe_cotacao_para_todos_os_itens_do_lote = tem_cotacao_para_todos_os_itens_do_lote? (pessoa_do_projeto)
			return existe_cotacao_para_todos_os_itens_do_lote
		end
	end

	def tem_cotacao_para_todos_os_itens_do_lote? (pessoa_do_projeto)
		existe_cotacao_para_todos_os_itens_do_lote = self.itens_do_lote.ativos.all? do |item_do_lote|
			pessoa_do_projeto.itens_do_projeto_por_pessoa.where(item_do_lote_id: item_do_lote.id).size > 0
		end
		return existe_cotacao_para_todos_os_itens_do_lote == true
	end

	def tem_licitante_com_cotacoes?
		return false unless self.pessoas_do_projeto_com_cotacao.any?
		todos_os_itens_do_lote_tem_cotacoes?
	end

	def tabela_de_itens_com_opcoes?
		self.itens_do_lote.any? do |item_do_lote|
			item_do_lote.pode_ser_anulado? || item_do_lote.pode_ter_lances?
		end
	end

	def itens_com_saldo?
		total_saldo = self.itens_do_lote.map{|item_do_contrato| item_do_contrato.saldo}.sum(&:to_d)
		
		return true if total_saldo > 0
	end

	# VALORES
	def menor_cotacao_dos_itens
		itens_do_lote.validos.inject(0) { |total, item_do_lote|
			total + item_do_lote.item_do_pedido.menor_preco
		}
	end

	def valor_total_da_menor_cotacao_dos_itens
		itens_do_lote.validos.inject(0) { |total, item_do_lote|
			total + (item_do_lote.item_do_pedido.menor_preco * item_do_lote.item_do_pedido.quantidade_total_requisitada)
		}
	end

	def maior_cotacao_dos_itens
		itens_do_lote.validos.inject(0) { |total, item_do_lote|
			total + item_do_lote.item_do_pedido.maior_preco
		}
	end

	def media_dos_valores
		itens_do_lote.validos.inject(0) { |total, item_do_lote|
			total + item_do_lote.item_do_pedido.preco_medio
		}
	end

	def total
		if itens_do_lote.present?
			if processo.pedido.projeto_simplificado.blank?
				itens_do_lote.ativos.to_a.sum(&:valor_total)
			else
				itens_do_lote.ativos.inject(0) { |total, item_do_lote|
					total + item_do_lote.item_do_pedido.valor_total_projeto_simplificado
				}
			end
		end
	end

	def total_por_unidade(unidade_orcamentaria_id)
		total = 0
		if !unidade_orcamentaria_id.blank? && itens_do_lote.present?
			if processo.pedido.projeto_simplificado.blank?
				itens_do_lote.ativos.each do |item|
					total += item.valor_total_por_unidade(unidade_orcamentaria_id).to_f
				end
			else
				itens_do_lote.ativos.each do |item|
					total += item.item_do_pedido.valor_total_projeto_simplificado_por_unidade(unidade_orcamentaria_id).to_f
				end
			end
		end
		return total
	end

	# AÇÕES
	def atribui_numero
		gerar_sugestao_codigo(:numero, 4, {projeto_id: projeto.id}).to_i if projeto.present? && numero.nil?
	end

	def abrir_lances
		if lances_abertos
			raise "Lances já estão abertos" and return
		else
			ActiveRecord::Base.transaction do
				begin
					self.update!(lances_abertos: true)
					if rodadas.empty?
						cria_rodada_inicial
						cria_ocorrencia_lances
					end
				rescue => e
					raise
					raise ActiveRecord::Rollback, e.message
				end
			end
		end
	end

	def fechar_lances
		if lances_abertos
			ActiveRecord::Base.transaction do
				begin
					if rodadas.last.try(:concluida?)
						ganhador = primeiro_colocado[:pessoa_do_projeto]
						pessoas_do_projeto_do_lote.find_by(pessoa_do_projeto_id: ganhador.id).update!(habilitado: true)
						self.update!(lances_abertos: false, ganhador_id: ganhador.id)
						self.cria_proposta_final_quando_processo_por_item_ou_lote_por_desconto
						processo.ocorrencias.create(data_da_ocorrencia: Date.today, horario_da_ocorrencia: Time.now.strftime("%H:%M"), tipo: "habilitacao", motivo: "Ganhador do lote Nº" + "#{self.numero.to_s}: #{ganhador.empresa_nome}"  )
					else
						raise "Só é possível encerrar quando houver um vencedor."
					end
				rescue => e
					raise
					raise ActiveRecord::Rollback, e.message
				end
			end
		else
			raise "Lances já estão fechados"
		end
	end

	def cria_proposta_final_quando_processo_por_item_ou_lote_por_desconto
		if (self.processo.por_item? || self.lote_por_desconto?) && self.itens_do_projeto_por_pessoa.finais.count == 0
			self.itens_do_projeto_por_pessoa.each {|item_do_projeto_por_pessoa|
				pessoa_do_projeto_do_lote = pessoas_do_projeto_do_lote.find_by(pessoa_do_projeto_id: item_do_projeto_por_pessoa.pessoa_do_projeto_id)
				if pessoa_do_projeto_do_lote.pessoa_do_projeto.eql?(self.ganhador)
					item_do_projeto_por_pessoa_final = item_do_projeto_por_pessoa.dup
					item_do_projeto_por_pessoa_final.final = true
					item_do_projeto_por_pessoa_final.preco = pessoa_do_projeto_do_lote.lance_final
					item_do_projeto_por_pessoa_final.save
				end
			}
		end
	end

	def cria_proposta_final
		if (self.processo.outro? || self.processo.dispensa_de_licitacao? || self.processo.inexigibilidade_de_licitacao? || self.processo.tomada_de_precos? || self.processo.concorrencia_publica? || self.processo.carona? || self.processo.concurso? || self.processo.convite? || self.processo.contratacao_consultoria_individual? || self.processo.parceria_osc? || self.processo.pedido.projeto_simplificado?) && self.itens_do_projeto_por_pessoa.finais.count == 0
			self.itens_do_projeto_por_pessoa.each {|item_do_projeto_por_pessoa|
				pessoa_do_projeto_do_lote = pessoas_do_projeto_do_lote.find_by(pessoa_do_projeto_id: item_do_projeto_por_pessoa.pessoa_do_projeto_id)
				if !pessoa_do_projeto_do_lote.nil? && pessoa_do_projeto_do_lote.pessoa_do_projeto.classificado? && pessoa_do_projeto_do_lote.pessoa_do_projeto.eql?(self.ganhador)
					item_do_projeto_por_pessoa_final = item_do_projeto_por_pessoa.dup
					item_do_projeto_por_pessoa_final.final = true
					item_do_projeto_por_pessoa_final.save
				end
			}
		end
	end

	def cria_proposta_final_para_ganhador
		pessoa_do_projeto_do_lote = pessoas_do_projeto_do_lote.find_by(pessoa_do_projeto_id: self.ganhador.id)
		item_do_projeto_por_pessoa_final = self.itens_do_projeto_por_pessoa.where(pessoa_do_projeto_id: self.ganhador.id).last.dup
		item_do_projeto_por_pessoa_final.final = true
		item_do_projeto_por_pessoa_final.preco = pessoa_do_projeto_do_lote.lance_final
		item_do_projeto_por_pessoa_final.save
	end

	def pessoas_do_projeto_elegiveis_para_lances_verbais
		if itens_do_projeto_por_pessoa.any?
			empresas_elegiveis_por_porcentagem = elegiveis_por_porcentagem(ranking_de_propostas)
			if empresas_elegiveis_por_porcentagem.size >= 3 || lote_por_desconto?
				empresas_elegiveis_por_porcentagem
			else
				elegiveis_por_preco(ranking_de_propostas)
			end
		else
			[]
		end
	end

	def primeiro_colocado
		if processo.eh_dispensa_ou_inexigibilidade? || processo.convite? || processo.contratacao_consultoria_individual? || processo.carona? || processo.outro?
			if ranking_de_propostas.blank?
				raise "não existem propostas cadastradas."
			else
				if processo.eh_dispensa_ou_inexigibilidade? && ranking_de_propostas.size > 1
					primeiro_do_ranking = ranking_de_propostas.keys.first
					valor_do_primeiro = primeiro_do_ranking.valor_total_do_lote(self).to_f
					segundo_do_ranking = ranking_de_propostas.keys.second
					valor_do_segundo = segundo_do_ranking.valor_total_do_lote(self).to_f

					if valor_do_primeiro.to_f.round(2) == valor_do_segundo.to_f.round(2)
						return nil
					else
						{ pessoa_do_projeto: ranking_de_propostas.keys.first, valor: ranking_de_propostas.values.first }
					end
				else
					{ pessoa_do_projeto: ranking_de_propostas.keys.first, valor: ranking_de_propostas.values.first }
				end
			end
		else
			raise "não há rodadas." unless rodadas.first.concluida?
			raise "Empate ficto detectado." if empate_ficto?
			if rodadas.last.desempate?
				ranking_de_lances.first
			elsif rodadas.last.lances.count > 1
				raise "Só é possível encerrar quando houver um vencedor."
			else
				raise "ocorreu um erro. Não existem lances computados."
			end
		end
	end

	def empresas_empatadas
		primeiro_lugar = ranking_de_lances.first
		ranking_de_lances.select {|candidato| candidato[:pessoa_do_projeto].pessoa.me_ou_epp_ou_mei? && candidato[:valor] <= primeiro_lugar[:valor] + (primeiro_lugar[:valor] * 0.05) }
	end

	def todos_os_itens_do_lote_devem_ter_cotacoes
		existe_cotacao_para_todos_os_itens_do_lote = false
		self.processo.pessoas_do_projeto.classificados.each do |pessoa_do_projeto|
			existe_cotacao_para_todos_os_itens_do_lote = tem_cotacao_para_todos_os_itens_do_lote? (pessoa_do_projeto)
			break if existe_cotacao_para_todos_os_itens_do_lote == true
		end
		if self.processo.global?
			raise "Todos os itens devem ter propostas preenchidas" unless existe_cotacao_para_todos_os_itens_do_lote
		elsif self.processo.por_item?
			raise "Nenhuma empresa preencheu proposta para este item" unless existe_cotacao_para_todos_os_itens_do_lote
		elsif self.processo.por_lote?
			raise "Nem todos os itens do lote tem proposta preenchida" unless existe_cotacao_para_todos_os_itens_do_lote
		end
	end

	def pessoas_do_projeto_com_cotacao
		self.processo.pessoas_do_projeto.classificados.select {|pessoa_do_projeto|
			tem_cotacao_para_todos_os_itens_do_lote? pessoa_do_projeto
		}
	end

	def pessoas_do_projeto_com_cotacao_e_lotes_validos
		self.processo.pessoas_do_projeto.classificados.select {|pessoa_do_projeto|
			tem_cotacao_para_todos_os_itens_do_lote?(pessoa_do_projeto) && pessoa_do_projeto.itens_do_projeto_por_pessoa_validos?(self.id)
		}
	end

	def pessoas_do_projeto_do_lote_com_cotacao
		self.pessoas_do_projeto_do_lote.classificados.select {|pessoa_do_projeto_do_lote|
			tem_cotacao_para_todos_os_itens_do_lote? pessoa_do_projeto_do_lote.pessoa_do_projeto
		}
	end

	def salva_ganhador(params)
		ActiveRecord::Base.transaction do
			begin
				if params[:ganhador_id].present?
					if self.update(params)
						pessoas_do_projeto_do_lote.where.not(pessoa_do_projeto_id: params[:ganhador_id]).update_all(habilitado: false)
						pessoas_do_projeto_do_lote.find_by(pessoa_do_projeto_id: params[:ganhador_id]).update!(habilitado: true)
						cria_proposta_final
						return true
					end
				end
				return false
			rescue => e
				raise
				raise ActiveRecord::Rollback, e.message
			end
		end
	end

	def atualiza_novo_ganhador
		if processo.pregao_presencial? || processo.pregao_eletronico?
			atualiza_novo_ganhador_por_lance
		else
			atualiza_novo_ganhador_por_proposta
		end
	end

	def atualiza_novo_ganhador_por_lance
		ranking_de_lances.each do |ranking_do_lance|
			pessoa_do_projeto_do_lote = pessoas_do_projeto_do_lote.find_by(pessoa_do_projeto_id: ranking_do_lance[:pessoa_do_projeto].id)
			if !pessoa_do_projeto_do_lote.habilitado && pessoa_do_projeto_do_lote.justificativa.nil?
				self.update!(ganhador: pessoa_do_projeto_do_lote.pessoa_do_projeto)
				pessoa_do_projeto_do_lote.update!(habilitado: true)
				break
			end
		end
	end

	def atualiza_novo_ganhador_por_proposta
		ranking_de_propostas.each do |pessoa_do_projeto, valor|
			pessoa_do_projeto_do_lote = pessoas_do_projeto_do_lote.find_by(pessoa_do_projeto_id: pessoa_do_projeto.id)
			if !pessoa_do_projeto_do_lote.habilitado && pessoa_do_projeto_do_lote.justificativa.nil?
				self.update!(ganhador: pessoa_do_projeto_do_lote.pessoa_do_projeto)
				pessoa_do_projeto_do_lote.update!(habilitado: true)
				break
			end
		end
	end

	def define_ganhador_menor_preco

			if tem_proposta_inicial? == false && tem_proposta_final? == false
				return false
			else 
				primeiro_colocado = self.send(:ranking_de_propostas).keys.first
				self.update(ganhador_id: primeiro_colocado.id)
				cria_proposta_final
				if ganhador.present?
					return true
				end
			end	
	end

	def pessoa_do_projeto_do_lote_ganhadora
		pessoas_do_projeto_do_lote.find_by(pessoa_do_projeto_id: self.ganhador_id)
	end

	def exclui_rodada_de_lances
		ActiveRecord::Base.transaction do
			begin
				deleta_ultima_rodada
				return true
			rescue => e
				raise
				raise ActiveRecord::Rollback, e.message
			end
		end
	end

	def fracassar
		self.update(status: 'fracassado') if pessoas_do_projeto_do_lote.all? {|ppl| ppl.justificativa.present? }
	end

	def cria_sequencia_dos_itens_do_lote
		ordem = 0
		self.itens_do_lote.each do |item|
			ordem += 1
			item.update(sequencia: ordem)
		end
	end

	private
	def deleta_ultima_rodada
		self.rodadas.last.destroy
		self.rodadas.last.lances.update_all(valor: nil, desistir: false)
		if self.rodadas.last.numero.zero?
			self.rodadas.last.destroy
			self.update(lances_abertos: false)
		end
	end

	def ranking_de_propostas
		if processo.por_lote? || processo.global?
			ranking = itens_do_projeto_por_pessoa.iniciais.validos.joins(item_do_lote: [item_do_pedido: :itens_do_pedido_por_unidade_orcamentaria]).group(:pessoa_do_projeto).order('sum_preco_all_quantidade_all_periodicidade', Arel.sql('random()')).sum("preco * quantidade * periodicidade")
		else
			ranking = itens_do_projeto_por_pessoa.iniciais.validos.group(:pessoa_do_projeto).order(Arel.sql('sum_preco, random()')).sum(:preco)
		end
		ranking = (lote_por_desconto?) ? ranking.reverse_each.to_h : ranking
	end

	def ranking_de_lances
		if lote_por_preco?
			lances.group(:pessoa_do_projeto).minimum(:valor).map { |pp, valor| { pessoa_do_projeto: pp, valor: valor.to_f } }.sort_by { |pp, valor| pp[:valor] }
		elsif lote_por_desconto?
			lances.group(:pessoa_do_projeto).maximum(:valor).map { |pp, valor| { pessoa_do_projeto: pp, valor: valor.to_f } }.sort_by { |pp, valor| pp[:valor] }.reverse
		end
	end

	def projeto_nao_deve_ter_mais_de_um_lote
		errors.add(:projeto_id, "Projeto global não pode ter mais de um lote") if projeto.lotes.where.not(id: self.id).count >= 1
	end

	def modalidade_de_licitacao_deve_ser_pregao
		if processo.lei_8666_93? && (!projeto.pregao_presencial? && !projeto.pregao_eletronico?)
			errors.add(:lances_abertos, "não pode ser verdadeiro caso modalidade de licitação seja #{projeto.modalidade_de_licitacao}")
		end
	end

	def licitacao_deve_estar_em_processo
			errors.add(:lances_abertos, "não pode ser verdadeiro caso a fase do processo seja #{projeto.status}") if processo.em_sessao? == false && processo.homologado? && processo.homologado_parcialmente? == false 
	end

=begin
	Para haver empate:
	- Ganhador não é microempresa, pequeno porte ou microempresa;
	- Há pelo menos uma empresa de pequeno porte cujo ultimo lance registrado passa menos de 5% do valor do ganhador;
=end
	def empate_ficto?
		ganhador = ranking_de_lances.first
		!ganhador[:pessoa_do_projeto].pessoa.me_ou_epp_ou_mei? && empresas_empatadas.count > 0 && !rodadas.last.desempate?
	end

	def cria_rodada_inicial
		#Cria rodada de propostas
		unless pessoas_do_projeto_com_cotacao_e_lotes_validos.any?
			raise "Não existem propostas para esse item/lote ou foram anuladas."
		end
		lances_attributes =
			pessoas_do_projeto_com_cotacao_e_lotes_validos.each_with_index.inject({}) { |hash, (pessoa_do_projeto, index)|
				if self.processo.por_item?
					valor = pessoa_do_projeto.itens_do_projeto_por_pessoa.find_by(item_do_lote_id: self.itens_do_lote.first.id).preco
				elsif self.lote_por_desconto?
					valor = pessoa_do_projeto.desconto_total_do_lote(self)
				else
					valor = pessoa_do_projeto.valor_total_do_lote(self)
				end
				hash.merge({ index.to_s => {
						pessoa_do_projeto_id: pessoa_do_projeto.id,
						valor: valor
					}})
			}
		rodada = rodadas.build(numero: 0, lances_attributes: lances_attributes)
		rodada.save(validate: false)
		# Cria rodada 1
		rodada = self.rodadas.build
		rodada.save
		raise "Não é possível criar rodada inicial: #{rodada.errors.messages[:base].join}" unless rodada.persisted?
	end

	def cria_ocorrencia_lances
		processo.ocorrencias.create(data_da_ocorrencia: Date.today, horario_da_ocorrencia: Time.now.strftime("%H:%M"), tipo: "lances",
			motivo: "Abertura de Lances para o lote Nº" + self.numero.to_s)
	end

	# Métodos para descobrir as pessoas do projeto elegíveis para lances verbais

	# 10% do menor valor
	def elegiveis_por_porcentagem lista_empresas
		if lote_por_desconto?
			maior_desconto = lista_empresas.values.first
			limite = maior_desconto - (maior_desconto * 0.1) # Limite é o menor valor - 10%
		else
			menor_valor = lista_empresas.values.first
			limite = menor_valor + (menor_valor * 0.1) # Limite é o menor valor + 10%
		end
		elegiveis(lista_empresas, limite)
	end

	# 3 menores preços
	def elegiveis_por_preco lista_empresas
		if lista_empresas.values.uniq.count > 2
			limite = lista_empresas.values.uniq[2]
			elegiveis(lista_empresas, limite)
		else
			elegiveis(lista_empresas, lista_empresas.values.last)
		end
	end

	def elegiveis lista_empresas, limite
		if lote_por_desconto?
			lista_empresas.map {|pessoa_do_projeto, valor|
				pessoa_do_projeto if valor >= limite
			}.compact
		else
			lista_empresas.map {|pessoa_do_projeto, valor|
				pessoa_do_projeto if valor <= limite
			}.compact
		end
	end

	def atribui_ganhador
		pessoa_do_lote_ganhadora = pessoas_do_projeto_do_lote.sort_by {|ppl| ppl.nota_tecnica.to_f }.last
		if pessoa_do_lote_ganhadora.try(:nota_tecnica).to_f > 0
			self.ganhador_id = pessoa_do_lote_ganhadora.pessoa_do_projeto.id
			self.update_column(:ganhador_id, self.ganhador_id)
			cria_proposta_final
		else
			self.ganhador_id = nil
		end
	end
end
