class Licitacao::ItemDoContrato < ApplicationRecord
	has_paper_trail

	belongs_to :item_do_lote, class_name: 'Licitacao::ItemDoLote', required: true
	belongs_to :contrato, class_name: 'Licitacao::Contrato', required: true, inverse_of: :itens_do_contrato

	has_many :itens_do_empenho_retroativo_do_contrato, class_name: 'Licitacao::ItemDoEmpenhoRetroativoDoContrato'
	has_many :itens_do_apostilamento, class_name: 'Licitacao::ItemDoApostilamento'

	delegate :item, :item_do_pedido, :lote, to: :item_do_lote
	delegate :codigo_e_descricao_do_item, to: :item

	validates_uniqueness_of :item_do_lote_id, scope: :contrato_id, if: :persisted?
	validates_presence_of :item_do_lote_id
	# validates_numericality_of :quantidade, greater_than: 0, allow_nil: true

	# validate :limite_do_total_digitado_pelo_calculo, if: Proc.new{ !self.try(:quantidade).blank? && !self.try(:valor_unitario).blank? && !self.try(:total).blank?}

	validate :valida_quantidade_de_itens, unless: Proc.new{ self.item_do_lote.try(:item_do_pedido).try(:por_valor_previsto?) }

	after_save :apaga_a_si_mesmo_se_quantidade_igual_a_zero

	scope :por_ordem_dos_itens_do_lote, -> {
		joins(:item_do_lote).includes(item_do_lote: { item_do_pedido: :item }).order(:ordem)
	}

	scope :por_sequencia_dos_itens_do_lote, -> {
		joins(:item_do_lote).includes(item_do_lote: { item_do_pedido: :item }).order(:sequencia)
	}

	scope :por_unidade_do_pedido, -> (unidade_orcamentaria_id) {
		joins(contrato: :unidade_orcamentaria_por_pedido)
		.where(licitacao_unidades_orcamentarias_por_pedido: { unidade_orcamentaria_id: unidade_orcamentaria_id })
	}

	# RELAÇÕES
	def itens_dos_empenhos
		contrato.itens_dos_empenhos.validos_no_orcamento.where(item: try(:item)).includes(:empenho).where('contabilidade_empenhos.restos_a_pagar is false') rescue nil
	end

	def itens_dos_empenho_descriminados
		contrato.itens_dos_empenhos.validos_no_orcamento.where(item: try(:item)).includes(:empenho).where('contabilidade_empenhos.restos_a_pagar != true AND contabilidade_empenhos.descrimina_itens_processo_ou_contrato is true') rescue nil
	end

	def itens_dos_empenho_descriminados_sem_aditivo
		contrato.itens_dos_empenhos.validos_no_orcamento.where(item: try(:item)).includes(:empenho).where('contabilidade_empenhos.restos_a_pagar != true AND contabilidade_empenhos.descrimina_itens_processo_ou_contrato is true AND contabilidade_empenhos.aditivo_id is NULL') rescue 0
	end

	def itens_dos_empenhos_no_periodo(data_inicio, data_fim)
		contrato.empenhos.where("data_do_empenho >= ? AND data_do_empenho <= ?", data_inicio, data_fim).itens_dos_empenhos.where(item: item).includes(:empenho)
	end

	def aditivo_por_prazo_dentro_da_vigente_na_data(data_do_periodo)
		contrato.aditivos.confirmados.aditivos_de_prazo.where("? >= inicio_da_vigencia AND ? <= fim_da_vigencia", data_do_periodo, data_do_periodo).first
	end

	def contrato_ou_aditivo_vigente(data_solicitada)
		aditivo_por_prazo_dentro_da_vigente_na_data = aditivo_por_prazo_dentro_da_vigente_na_data(data_do_periodo)
		if periodo_dentro_da_vigencia_original_contrato(data_do_periodo) || (aditivo_por_prazo_dentro_da_vigente_na_data.present? && aditivo_por_prazo_dentro_da_vigente_na_data.itens_do_aditivo.size ==  0) || aditivo_por_prazo_dentro_da_vigente_na_data.blank? || aditivo_por_prazo_dentro_da_vigente_na_data.nil?
			data_inicio = contrato.inicio_da_vigencia.to_date
			data_fim = aditivo_por_prazo_dentro_da_vigente_na_data.present? ? aditivo_por_prazo_dentro_da_vigente_na_data.fim_da_vigencia.to_date : contrato.fim_da_vigencia.to_date
		else
			data_inicio = aditivo_por_prazo_dentro_da_vigente_na_data.inicio_da_vigencia.to_date
			data_fim = aditivo_por_prazo_dentro_da_vigente_na_data.fim_da_vigencia.to_date
		end
	end

	def aditivos_de_acrescimo_ou_decrescimo_no_preiodo_vigente(data_inicio, data_fim)
		contrato.aditivos.confirmados.de_acrescimo_ou_reducao.where("licitacao_aditivos.data_do_aditivo >= ? AND licitacao_aditivos.data_do_aditivo <= ?", data_inicio, data_fim)
	end

	def marca_do_item item_id
		@fornecedor = contrato.contratado.pessoa_do_projeto
		@itens_do_projeto_por_pessoa = @fornecedor.itens_do_projeto_por_pessoa.joins(item_do_lote: {item_do_pedido: :item}).where(base_itens: {id: item_id})
		return @itens_do_projeto_por_pessoa.first.marca if @itens_do_projeto_por_pessoa.any?
		nil
	end

	def marca_oficial_do_item
		item_id = self.item_do_lote.item.id
		if contrato.aditivos.confirmados.where(altera_marca: true).any? && item_possui_aditivo_de_alteracao_de_marca(item_id)
			aditivo = aditivo_de_alteracao_de_marca_do_item(item_id)
			#item_do_contrato = self.joins(item_do_lote: {item_do_pedido: :item}).find_by(base_itens: {id: item_id})
			@item_do_aditivo_de_alteracao_de_marca = aditivo.itens_do_aditivo_de_alteracao_de_marca.where(item_do_lote_id: self.item_do_lote_id)
			marca = @item_do_aditivo_de_alteracao_de_marca.first.marca_atualizada if @item_do_aditivo_de_alteracao_de_marca.any?
		else
			@ganhador = contrato.pessoa_do_projeto
			@itens_do_projeto_por_pessoa = @ganhador.itens_do_projeto_por_pessoa.joins(item_do_lote: {item_do_pedido: :item}).where(base_itens: {id: item_id})
			marca = @itens_do_projeto_por_pessoa.first.marca if @itens_do_projeto_por_pessoa.any?

			if marca.blank? && contrato.projeto.pedido.projeto_simplificado?
				marca = self.item_do_lote.item_do_pedido.marca
			end
		end
		return marca
		nil
	end

	def item_possui_aditivo_de_alteracao_de_marca item_id
		if aditivo_de_alteracao_de_marca_do_item(item_id).nil?
			return false
		else
			return true
		end
	end

	def aditivo_de_alteracao_de_marca_do_item item_id
		#item_do_contrato = self.joins(item_do_lote: {item_do_pedido: :item}).find_by(base_itens: {id: item_id})
		contrato.aditivos.confirmados.where(altera_marca: true).order(id: :desc).each do |aditivo|
			@item_do_aditivo_de_alteracao_de_marca = aditivo.itens_do_aditivo_de_alteracao_de_marca.where(item_do_lote_id: self.item_do_lote_id)
			if @item_do_aditivo_de_alteracao_de_marca.any?
				return aditivo
			end
		end
		return nil
	end

	#BOOLEANS
	def periodo_dentro_da_vigencia_original_contrato(data_do_periodo)
		if contrato.inicio_da_vigencia.present? && contrato.fim_da_vigencia.present?
			contrato.inicio_da_vigencia <= data_do_periodo && contrato.fim_da_vigencia >= data_do_periodo
		else
			return false
		end
	end

	# QUANTIDADES
	def quantidade_aditivada
		acrescimo = contrato.aditivos.confirmados.each.map { |aditivo| aditivo.itens_do_aditivo.acrescimo.where(item_do_lote: item_do_lote).sum(:quantidade).to_d }.sum
		reducao = contrato.aditivos.confirmados.each.map { |aditivo| aditivo.itens_do_aditivo.reducao.where(item_do_lote: item_do_lote).sum(:quantidade).to_d }.sum
		
		prazo = 0
		# No caso de aditivo de prazo com controle de itens, atualizar a quantidade a empenhar do contrato
		contrato.aditivos.confirmados.aditivos_de_prazo.each do |aditivo|
			if aditivo.prazo_com_controle_de_itens? && aditivo.itens_do_aditivo.size > 0
				prazo += aditivo.itens_do_aditivo.por_prazo.where(item_do_lote: item_do_lote).sum(:quantidade).to_d
			end
		end
		
		if itens_do_aditivo_qualitativo.any?
			return quantidade + itens_do_aditivo_qualitativo.last.diferenca_da_quantidade.to_d + ( acrescimo - reducao + prazo )
		else
			return acrescimo - reducao + prazo
		end
	end

	def quantidade_atual
		itens_do_aditivo_qualitativo.any? ? quantidade_qualitativa : quantidade
	end

	def quantidade_qualitativa
		diferenca_da_quantidade = itens_do_aditivo_qualitativo.last.try(:quantidade).to_d
	end

	def itens_do_aditivo_qualitativo
		@itens_do_aditivo_qualitativo ||= contrato.itens_do_aditivo.joins(:aditivo).where(
			licitacao_aditivos: { modalidade: Licitacao::Aditivo.modalidades[:qualitativo], status: Licitacao::Aditivo.status[:confirmado] },
			licitacao_itens_do_aditivo: { item_do_lote_id: item_do_lote_id } 
		).where('licitacao_aditivos.data_do_aditivo <= ?', Date.today)
	end

	def quantidade_total
		if itens_do_aditivo_qualitativo.any?
			quantidade_aditivada.to_d.round(2)
		else
			( quantidade.to_d + quantidade_aditivada ).round(2)
		end
	end

	def quantidade_total_do_periodo(contrato_periodo, data_empenho, data_inicio, data_fim)
		total_itens_do_aditivo = 0
		aditivos_de_acrescimo_ou_decrescimo_no_preiodo_vigente(data_inicio, data_fim).each do |aditivo|
			if aditivo.modalidade == "acrescimo"
				total_itens_do_aditivo += aditivo.itens_do_aditivo.find_by(item_do_lote_id: self.item_do_lote_id).try(:quantidade).to_f
			else
				total_itens_do_aditivo -= aditivo.itens_do_aditivo.find_by(item_do_lote_id: self.item_do_lote_id).try(:quantidade).to_f
			end
		end

		if contrato_periodo == true
			quantidade = quantidade_atual
		else
			quantidade = aditivo_por_prazo_dentro_da_vigente_na_data(data_empenho).itens_do_aditivo.find_by(item_do_lote_id: self.item_do_lote_id).try(:quantidade).to_f
		end
		quantidade + total_itens_do_aditivo
	end

	def quantidade_total_do_periodo_sem_aditivo(data_inicio, data_fim)
		total_itens_do_aditivo = 0
		aditivos_de_acrescimo_ou_decrescimo_no_preiodo_vigente(data_inicio, data_fim).each do |aditivo|
			if aditivo.modalidade == "acrescimo"
				total_itens_do_aditivo += aditivo.itens_do_aditivo.find_by(item_do_lote_id: self.item_do_lote_id).try(:quantidade).to_f
			else
				total_itens_do_aditivo -= aditivo.itens_do_aditivo.find_by(item_do_lote_id: self.item_do_lote_id).try(:quantidade).to_f
			end
		end 

		if itens_do_aditivo_qualitativo.any?
			if quantidade_qualitativa > 0
				quantidade_qualitativa_vigente.to_f + total_itens_do_aditivo
			else 
				itens_do_aditivo_qualitativo.last.try(:diferenca_da_quantidade).to_d.abs
			end
		else
			quantidade.to_f + total_itens_do_aditivo
		end
	end
	
	def quantidade_qualitativa_vigente
		quantidade_total + quantidade_do_item_em_rp_cancelado_nao_processado
	end

	def quantidade_empenhada
		itens_dos_empenho_descriminados.to_a.sum(&:quantidade_disponivel).to_d.round(2) + itens_do_empenho_retroativo_do_contrato.to_a.sum(&:quantidade_disponivel).to_d.round(2)
	end

	def quantidade_empenhada_na_dotacao(dotacao)
		itens_dos_empenho_descriminados.joins(:empenho).where("contabilidade_empenhos.orcamento_da_despesa_id = ?", dotacao).to_a.sum(&:quantidade_disponivel).to_d.round(2) + itens_do_empenho_retroativo_do_contrato.to_a.sum(&:quantidade_disponivel).to_d.round(2)
	end

	def quantidade_empenhada_no_periodo(data_inicio, data_fim)
		quantidade = 0
		quantidade_empenhada = contrato.itens_dos_empenhos.validos_no_orcamento.joins(:empenho).where("contabilidade_empenhos.restos_a_pagar != true AND contabilidade_empenhos.descrimina_itens_processo_ou_contrato is true AND contabilidade_itens_do_empenho.item_id = ? AND contabilidade_empenhos.reconhecimento_de_divida IS NULL AND ((contabilidade_empenhos.data_do_empenho BETWEEN ? AND ?) OR (contabilidade_empenhos.data_do_empenho IS NULL AND contabilidade_empenhos.data_de_solicitacao BETWEEN ? AND ? ))",item.id, data_inicio, data_fim, data_inicio, data_fim).sum(:quantidade)
		quantidade_empenhada_retroativa = contrato.itens_do_empenho_retroativo_do_contrato.joins(:item_do_contrato).where("licitacao_itens_do_contrato.id = ? AND licitacao_empenhos_retroativos_do_contrato.data_do_empenho BETWEEN ? AND ?", item.id, data_inicio, data_fim).sum(:quantidade)

		quantidade = quantidade_empenhada.to_d - quantidade_anulada_no_periodo(data_inicio, data_fim).to_d + quantidade_empenhada_retroativa.to_d
	end

	def quantidade_anulada
		if itens_do_aditivo_qualitativo.any? && quantidade_atual == 0
			return 0
		else
			qtd_anulacoes = itens_dos_empenho_descriminados.to_a.sum(&:quantidade_anulada).to_f.round(2)
			qtd_empenhos = itens_dos_empenho_descriminados.to_a.sum(&:quantidade_disponivel).to_f.round(6)
			qtd_anulacoes = ((qtd_anulacoes + qtd_empenhos) > quantidade_total) && qtd_empenhos.to_f > quantidade_total.to_f  ? (quantidade_total - qtd_empenhos).to_f.round(2) : qtd_anulacoes
		end
	end

	def quantidade_anulada_no_periodo(datainicio, datafim)
		qtd_anulacoes = itens_dos_empenho_descriminados.joins(:empenho).where('contabilidade_empenhos.restos_a_pagar != true AND contabilidade_empenhos.data_do_empenho >= ? AND contabilidade_empenhos.data_do_empenho <= ?', datainicio, datafim).to_a.sum(&:quantidade_anulada).to_d.round(6)
		qtd_empenhos = itens_dos_empenho_descriminados.joins(:empenho).where('contabilidade_empenhos.restos_a_pagar != true AND contabilidade_empenhos.data_do_empenho >= ? AND contabilidade_empenhos.data_do_empenho <= ?', datainicio, datafim).to_a.sum(&:quantidade_disponivel).to_d.round(6)
		qtd_anulacoes = ((qtd_anulacoes + qtd_empenhos) > quantidade_total) && qtd_empenhos.to_f > quantidade_total.to_f  ? (quantidade_total - qtd_empenhos).to_d.round(2) : qtd_anulacoes
	end

	def quantidade_a_empenhar_no_periodo_sem_aditivo(datainicio, datafim)
		itens_dos_empenho_descriminados_sem_aditivo.joins(:empenho).where('contabilidade_empenhos.data_do_empenho >= ? AND contabilidade_empenhos.data_do_empenho <= ? and contabilidade_empenhos.data_do_empenho is not null OR (contabilidade_empenhos.data_de_solicitacao >= ? and contabilidade_empenhos.data_de_solicitacao <= ? and contabilidade_empenhos.data_do_empenho is null)', datainicio, datafim, datainicio, datafim).to_a.sum(&:quantidade_disponivel).to_d
	end

	def saldo
		if itens_do_aditivo_qualitativo.any?
			if quantidade_atual == 0
				return 0
			else
				quantidade_total - quantidade_empenhada + quantidade_do_item_em_rp_cancelado_nao_processado
			end
		else
			quantidade_total - quantidade_empenhada + quantidade_do_item_em_rp_cancelado_nao_processado
		end
	end

	def saldo_para_empenho_atual(data_empenho)
		data_empenho = data_empenho.to_date
		aditivo_por_prazo_dentro_da_vigente_na_data = aditivo_por_prazo_dentro_da_vigente_na_data(data_empenho)
		if periodo_dentro_da_vigencia_original_contrato(data_empenho) || (aditivo_por_prazo_dentro_da_vigente_na_data.present? && aditivo_por_prazo_dentro_da_vigente_na_data.itens_do_aditivo.size ==  0) || aditivo_por_prazo_dentro_da_vigente_na_data.blank? || aditivo_por_prazo_dentro_da_vigente_na_data.nil?
			data_inicio = contrato.inicio_da_vigencia.to_date
			data_fim = aditivo_por_prazo_dentro_da_vigente_na_data.present? ? aditivo_por_prazo_dentro_da_vigente_na_data.fim_da_vigencia.to_date : contrato.fim_da_vigencia.to_date
			contrato_periodo = true
		else
			data_inicio = aditivo_por_prazo_dentro_da_vigente_na_data.inicio_da_vigencia.to_date
			data_fim = aditivo_por_prazo_dentro_da_vigente_na_data.fim_da_vigencia.to_date
			contrato_periodo = false
		end
		
		(quantidade_total_do_periodo(contrato_periodo, data_empenho, data_inicio, data_fim).to_d - quantidade_empenhada_no_periodo(data_inicio, data_fim).to_d).to_f.round(6)
	end

	def saldo_para_empenho_atual_sem_aditivo(data_empenho)
		data_empenho = data_empenho.to_date
		aditivo_por_prazo_dentro_da_vigente_na_data = aditivo_por_prazo_dentro_da_vigente_na_data(data_empenho)
		data_inicio = contrato.inicio_da_vigencia.to_date
		data_fim = aditivo_por_prazo_dentro_da_vigente_na_data.present? ? aditivo_por_prazo_dentro_da_vigente_na_data.fim_da_vigencia.to_date : contrato.fim_da_vigencia.to_date

		(quantidade_total_do_periodo_sem_aditivo(data_inicio, data_fim).to_d - quantidade_a_empenhar_no_periodo_sem_aditivo(data_inicio, data_fim).to_d + quantidade_do_item_em_rp_cancelado_nao_processado(data_inicio, data_fim).to_d).to_f.round(6)
	end

	def saldo_para_empenho_no_contrato_sem_aditivo
		data_empenho = contrato.inicio_da_vigencia.to_date
		aditivo_por_prazo_dentro_da_vigente_na_data = aditivo_por_prazo_dentro_da_vigente_na_data(data_empenho)
		data_inicio = contrato.inicio_da_vigencia.to_date
		data_fim = aditivo_por_prazo_dentro_da_vigente_na_data.present? ? aditivo_por_prazo_dentro_da_vigente_na_data.fim_da_vigencia.to_date : contrato.data_final_da_vigencia_atual(data_empenho)

		(quantidade_total_do_periodo_sem_aditivo(data_inicio, data_fim).to_d - quantidade_a_empenhar_no_periodo_sem_aditivo(data_inicio, data_fim).to_d + quantidade_do_item_em_rp_cancelado_nao_processado(data_inicio, data_fim).to_d).to_f.round(6)
	end

	def saldo_a_liquidar
		return quantidade_empenhada - itens_dos_empenhos.to_a.sum(&:quantidade_liquidada).to_f.round(2)
	end

	def saldo_atual(data_aditivo)
		data_do_aditivo = data_aditivo.to_date
		data_inicio = contrato.inicio_da_vigencia.to_date
		data_fim = contrato.fim_da_vigencia.to_date
		if (data_do_aditivo >= data_inicio && data_do_aditivo <= data_fim) && data_do_aditivo > Date.today
			saldo
		else
			self.quantidade.to_f - quantidade_empenhada
		end
	end

	def porcentagem_do_saldo
		return (quantidade_total > 0 ? ((saldo * 100) / quantidade_total) : 0)
	end

	# VALORES
	def preco_unitario
		if self.contrato.present? && self.contrato.de_ata?
			ata_de_registro_de_precos = contrato.ata_de_registro_de_precos
			reajustes_acrescimo_da_ata = 0
			reajustes_decrescimo_da_ata = 0

			reajustes_acrescimo_da_ata = ata_de_registro_de_precos.itens_do_aditivo_da_ata.joins(:aditivo_da_ata).where(item_do_lote: item_do_lote).where(licitacao_aditivos_da_ata: { status: Licitacao::AditivoDaAta.status["confirmado"], modalidade: Licitacao::AditivoDaAta.modalidades["reajuste_de_valor_acrescimo"]}).where('(licitacao_aditivos_da_ata.data_do_aditivo < ?) OR (licitacao_aditivos_da_ata.data_do_aditivo = ?)', contrato.data_da_solicitacao, contrato.data_da_solicitacao).sum(:valor_adicionado)
			reajustes_decrescimo_da_ata = ata_de_registro_de_precos.itens_do_aditivo_da_ata.joins(:aditivo_da_ata).where(item_do_lote: item_do_lote).where(licitacao_aditivos_da_ata: {status: Licitacao::AditivoDaAta.status["confirmado"],  modalidade: Licitacao::AditivoDaAta.modalidades["reajuste_de_valor_decrescimo"]}).where('(licitacao_aditivos_da_ata.data_do_aditivo < ?) OR (licitacao_aditivos_da_ata.data_do_aditivo = ?)', contrato.data_da_solicitacao, contrato.data_da_solicitacao).sum(:valor_adicionado)

			if item_do_pedido.por_valor_previsto?
				(item_do_pedido.valor_previsto_por_unidade_orcamentaria(contrato.unidade_orcamentaria.id).to_d + reajustes_acrescimo_da_ata.to_d - reajustes_decrescimo_da_ata.to_d).to_d
			else
				(item_do_lote.preco_unitario.to_d  + reajustes_acrescimo_da_ata.to_d - reajustes_decrescimo_da_ata.to_d).to_d
			end

		elsif self.item_do_pedido.por_valor_previsto?
			item_do_pedido.valor_previsto_por_unidade_orcamentaria(contrato.unidade_orcamentaria.id)
		else
			item_do_lote.preco_unitario
		end
	end

	def valor_unitario_para_o_empenho(data_do_empenho)
		reajustes_acrescimo = contrato.itens_do_aditivo.joins(:aditivo).where(item_do_lote: item_do_lote).where('licitacao_aditivos.inicio_da_vigencia <= ?', data_do_empenho.to_date).where(licitacao_aditivos: { modalidade: [ Licitacao::Aditivo.modalidades["reajuste_de_valor_acrescimo"], Licitacao::Aditivo.modalidades["prazo_e_reajuste_acrescimo"] ] })
		reajustes_decrescimo = contrato.itens_do_aditivo.joins(:aditivo).where(item_do_lote: item_do_lote).where('licitacao_aditivos.inicio_da_vigencia <= ?', data_do_empenho.to_date).where(licitacao_aditivos: { modalidade: [ Licitacao::Aditivo.modalidades["reajuste_de_valor_decrescimo"] , Licitacao::Aditivo.modalidades["prazo_e_reajuste_decrescimo"]] })
		apostilamentos_acrescimo = self.itens_do_apostilamento.joins(:apostilamento).where("licitacao_apostilamentos.data_apostilamento <= ? AND licitacao_apostilamentos.modalidade = ?", data_do_empenho, Licitacao::Apostilamento.modalidades[:acrescimo]).sum(&:preco_unitario).to_d
		apostilamentos_reducao = self.itens_do_apostilamento.joins(:apostilamento).where("licitacao_apostilamentos.data_apostilamento <= ? AND licitacao_apostilamentos.modalidade = ?", data_do_empenho, Licitacao::Apostilamento.modalidades[:reducao]).sum(&:preco_unitario).to_d

		if reajustes_acrescimo.any? || reajustes_decrescimo.any? ||apostilamentos_acrescimo > 0 || apostilamentos_reducao > 0
			(preco_unitario + reajustes_acrescimo.sum(:valor_adicionado) - reajustes_decrescimo.sum(:valor_adicionado) + apostilamentos_acrescimo - apostilamentos_reducao ).to_f
		elsif contrato.projeto.pedido.projeto_simplificado? && !contrato.projeto.bid_obra_ou_servico? && !contrato.de_ata?
			item_do_lote.valor_estimativo.to_f
		elsif valor.present?
			valor.to_f
		else
			preco_unitario.to_f
		end
	end

	def valor_unitario
		if item_do_lote.present?
			reajustes_acrescimo = contrato.itens_do_aditivo.joins(:aditivo).where(item_do_lote: item_do_lote).where(licitacao_aditivos: { modalidade: [Licitacao::Aditivo.modalidades["reajuste_de_valor_acrescimo"], Licitacao::Aditivo.modalidades["prazo_e_reajuste_acrescimo"]], status: 1 })
			reajustes_decrescimo = contrato.itens_do_aditivo.joins(:aditivo).where(item_do_lote: item_do_lote).where(licitacao_aditivos: { modalidade: [Licitacao::Aditivo.modalidades["reajuste_de_valor_decrescimo"], Licitacao::Aditivo.modalidades["reajuste_de_valor_decrescimo"]], status: 1 })
			if reajustes_acrescimo.any? || reajustes_decrescimo.any? || valor_acrescido_por_apostilamento > 0 || valor_reduzido_por_apostilamento > 0
				(preco_unitario + reajustes_acrescimo.sum(:valor_adicionado) - reajustes_decrescimo.sum(:valor_adicionado) + valor_acrescido_por_apostilamento - valor_reduzido_por_apostilamento).round(2).to_f
			elsif contrato.projeto.pedido.projeto_simplificado? && !contrato.projeto.bid_obra_ou_servico? && !contrato.de_ata?
				item_do_lote.valor_estimativo.to_f
			elsif valor.present?
				valor.to_f
			else
				preco_unitario.to_f
			end
		else
			return 0
		end
	end

	def valor_total
		if valor.present?
			(valor * quantidade_atual).round(2)
		elsif contrato.de_ata?
			(preco_unitario * quantidade_atual).round(2)
		elsif !valor.present? && contrato.projeto.pedido.projeto_simplificado? && !contrato.projeto.bid_obra_ou_servico?
			(quantidade_atual * item_do_lote.valor_estimativo.to_f).round(2)
		else
			(quantidade_atual * preco_unitario).round(2)
		end
	end

	def valor_original
		if valor.present?
			(valor * quantidade).round(2)
		elsif contrato.de_ata?
			(preco_unitario * quantidade).round(2)
		elsif !valor.present? && contrato.projeto.pedido.projeto_simplificado? && !contrato.projeto.bid_obra_ou_servico?
			(quantidade * item_do_lote.valor_estimativo.to_f).round(2)
		else
			(quantidade * preco_unitario).round(2)
		end
	end

	def valor_aditivado
		acrescimo_e_reducao = contrato.itens_do_aditivo.joins(:aditivo).where(item_do_lote: item_do_lote).where(licitacao_aditivos: { status: 1 }).merge(Licitacao::Aditivo.de_acrescimo_ou_reducao).to_a.sum(&:valor_total).to_f
		prazo = (contrato.aditivos.confirmados.aditivos_de_prazo.all? { |aditivo| aditivo.prazo_com_controle_de_itens? }) ? contrato.itens_do_aditivo.por_prazo.where(item_do_lote: item_do_lote).to_a.sum(&:valor_total).to_f : 0
		acrescimo_e_reducao + prazo
	end

	def valor_reajustado
		contrato.itens_do_aditivo.includes(:aditivo).where(licitacao_aditivos: { status: 1 }).where(item_do_lote: item_do_lote).merge(Licitacao::Aditivo.de_reajuste_de_valor).sum(:total).to_f
	end

	def valor_empenhado
		itens_dos_empenhos.to_a.sum(&:total_disponivel).to_f  + itens_do_empenho_retroativo_do_contrato.to_a.sum(&:total_disponivel).to_f
	end

	def valor_empenhado_total
		itens_dos_empenhos.to_a.sum(&:total).to_d  + itens_do_empenho_retroativo_do_contrato.to_a.sum(&:total).to_d
	end

	def valor_anulado
		total_anulado = 0
		total_anulado = itens_dos_empenhos.map {|f| f.anulacoes.map(&:total) }.flatten.sum(&:to_d)
		return total_anulado
	end

	def valor_acrescido_por_apostilamento
		self.itens_do_apostilamento.joins(:apostilamento)
			.where(licitacao_apostilamentos: {modalidade: Licitacao::Apostilamento.modalidades[:acrescimo] } ).sum(&:preco_unitario)
	end

	def valor_reduzido_por_apostilamento
		self.itens_do_apostilamento.joins(:apostilamento)
		.where(licitacao_apostilamentos: {modalidade: Licitacao::Apostilamento.modalidades[:reducao] } ).sum(&:preco_unitario)
	end

	def valor_a_empenhar
		if itens_do_aditivo_qualitativo.any? && quantidade_atual == 0
			0
		else
			valor = valor_aditivado + valor_reajustado - valor_empenhado_total + valor_do_item_em_rp_cancelado_nao_processado + valor_apostilado + valor_anulado

			if itens_do_aditivo_qualitativo.any?
				return ( ( quantidade_total + quantidade_do_item_em_rp_cancelado_nao_processado ) * valor_unitario ) + valor
			else
				return valor_total + valor
			end
		end
	end

	def valor_apostilado
		return self.saldo_acresido_apostilamento - self.saldo_reduzido_apostilamento
	end

	def saldo_acresido_apostilamento
		self.itens_do_apostilamento.joins(:apostilamento)
		.where(licitacao_apostilamentos: {modalidade: Licitacao::Apostilamento.modalidades[:acrescimo] } ).sum(&:saldo_para_calculos)
	end

	def saldo_reduzido_apostilamento
		self.itens_do_apostilamento.joins(:apostilamento)
		.where(licitacao_apostilamentos: {modalidade: Licitacao::Apostilamento.modalidades[:reducao] } ).sum(&:saldo_para_calculos)
	end

	def valor_a_empenhar_atual
		if contrato.inicio_da_vigencia.present? && contrato.fim_da_vigencia.present?
			quantidade_disponivel = saldo_para_empenho_atual(Date.today)
			if valor.present?
				(valor * quantidade_disponivel).round(2)
			elsif contrato.de_ata?
				(preco_unitario * quantidade_disponivel).round(2)
			elsif !valor.present? && contrato.projeto.pedido.projeto_simplificado? && !contrato.projeto.bid_obra_ou_servico?
				(quantidade_disponivel * item_do_lote.valor_estimativo.to_f).round(2)
			else
				(quantidade_disponivel * preco_unitario).round(2)
			end
		else
			if valor.present?
				(valor * self.quantidade).round(2)
			elsif contrato.de_ata?
				(preco_unitario * self.quantidade).round(2)
			elsif !valor.present? && contrato.projeto.pedido.projeto_simplificado? && !contrato.projeto.bid_obra_ou_servico?
				(self.quantidade * item_do_lote.valor_estimativo.to_f).round(2)
			else
				(self.quantidade * preco_unitario).round(2)
			end
		end
	end

	def valor_do_item_em_rp_cancelado_nao_processado
		quantidade_do_item_em_rp_cancelado_nao_processado * self.valor_unitario
	end

	def quantidade_do_item_em_rp_cancelado_nao_processado(datainicio=nil, datafim=nil)
		item_id = self.item_do_lote.item_do_pedido.item.id
		
		if datainicio==nil && datafim==nil
			empenhos_do_contrato = contrato.empenhos
		else
			empenhos_do_contrato = contrato.empenhos.where('contabilidade_empenhos.data_do_empenho >= ? AND contabilidade_empenhos.data_do_empenho <= ? and contabilidade_empenhos.data_do_empenho is not null OR (contabilidade_empenhos.data_de_solicitacao >= ? and contabilidade_empenhos.data_de_solicitacao <= ? and contabilidade_empenhos.data_do_empenho is null)', datainicio, datafim, datainicio, datafim)
		end

		total = 0
		empenhos_do_contrato.joins(:restos_a_pagar_cancelados).each do |empenho_cancelado|
			empenho_cancelado.restos_a_pagar_cancelados.joins(:cancelamento_de_resto_a_pagar).where('contabilidade_cancelamentos_de_restos_a_pagar.status = 1').each do |rp_cancelada|
				total = total + rp_cancelada.itens_dos_rps_cancelados.where('contabilidade_itens_dos_rps_cancelados.item_id = ?', item_id).sum(:quantidade_cancelada)
			end
		end

		return total
	end

	def quantidade_do_item_do_aditivo(empenho_id)
		aditivo = self.contrato.empenhos.find_by(id: empenho_id).aditivo
		aditivo_de_quantidade = self.contrato.aditivos.where('licitacao_aditivos.modalidade = 0').select { |aditivo| aditivo.itens_do_aditivo.where(item_do_lote_id: self.item_do_lote_id).present? }.map { |aditivo| aditivo.itens_do_aditivo.where(item_do_lote_id: self.item_do_lote_id).sum(&:quantidade)}.sum

		if aditivo.present?
			quantidade_do_aditivo = aditivo.itens_do_aditivo.find_by(item_do_lote_id: self.item_do_lote_id).quantidade rescue 0
			quantidades_empenhadas = aditivo.empenhos.where(restos_a_pagar: false).map { |empenho| empenho.itens_do_empenho.find_by(item_id: self.item_do_lote.item_do_pedido.item_id).quantidade rescue 0  }.sum
			quantidades_anuladas = aditivo.empenhos.where(restos_a_pagar: false).map { |empenho| empenho.itens_do_empenho.find_by(item_id: self.item_do_lote.item_do_pedido.item_id).quantidade_anulada rescue 0  }.sum
			quantidade_do_aditivo - quantidades_empenhadas + quantidades_anuladas + aditivo_de_quantidade
		else
			return 0
		end
	end

	def retorna_numero_lote
		self.lote.numero
	end

	def nome_do_item
		return self.item.try(:codigo_e_descricao)
	end

	def saldo_dos_itens_apostilados_vigente_na_data(data)
		apostilamentos_vigentes = self.contrato.apostilamentos.where("licitacao_apostilamentos.modalidade in (?) AND data_apostilamento >= ?", [Licitacao::Apostilamento.modalidades[:acrescimo], Licitacao::Apostilamento.modalidades[:reducao]] , data)

		apostilamentos_redutivos = apostilamentos_vigentes.reducao.inject(0){ |total, apostilamento| total + apostilamento.itens_do_apostilamento.sum(&:saldo_para_calculos) } rescue 0
		apostilamentos_acrescidos = apostilamentos_vigentes.acrescimo.inject(0){ |total, apostilamento| total + apostilamento.itens_do_apostilamento.sum(&:saldo_para_calculos) } rescue 0

		return apostilamentos_acrescidos - apostilamentos_redutivos
	end

	def saldo_dos_itens_no_periodo(data)
		if self.itens_do_apostilamento.any?
			apostilamentos_acrescimo = self.itens_do_apostilamento.joins(:apostilamento).where("licitacao_apostilamentos.data_apostilamento <= ? AND licitacao_apostilamentos.modalidade = ?", data, Licitacao::Apostilamento.modalidades[:acrescimo]).sum(&:saldo_para_calculos).to_d
			apostilamentos_reducao = self.itens_do_apostilamento.joins(:apostilamento).where("licitacao_apostilamentos.data_apostilamento <= ? AND licitacao_apostilamentos.modalidade = ?", data, Licitacao::Apostilamento.modalidades[:reducao]).sum(&:saldo_para_calculos).to_d

			return  apostilamentos_acrescimo - apostilamentos_reducao + ( self.preco_unitario * self.saldo )
		else
			return self.saldo * self.valor_unitario
		end
	end

	private
	# def limite_do_total_digitado_pelo_calculo
	# 	total_calculado = (self.quantidade.to_f * self.valor_unitario).round(2)
	# 	errors.add(:total, "não pode ser mais que 10 centavos do valor calculado da quantidade x preço unitário") if self.total.to_f > (total_calculado + 0.1)
	# 	errors.add(:total, "não pode ser menos que 10 centavos do valor calculado da quantidade x preço unitário") if self.total.to_f < (total_calculado - 0.1)
	# end

	def apaga_a_si_mesmo_se_quantidade_igual_a_zero
		self.delete unless self.quantidade.to_f > 0
	end

	#foi pedido a retirada da validação abaixo
	def verifica_existencia_de_contrato_vigente_com_mesmo_item
		if self.contrato.projeto.contratos_vigentes.where.not(id: self.contrato.id).joins(
				itens_do_contrato: :item_do_lote).where(licitacao_itens_do_lote: {id: self.item_do_lote}).joins(
					:unidade_orcamentaria_por_pedido).where(licitacao_unidades_orcamentarias_por_pedido: {id: self.contrato.unidade_orcamentaria_por_pedido.id}).any?
			errors.add(:quantidade, "Item já usado em outro contrato vigente")
		end
	end

	def valida_quantidade_de_itens
		if contrato.present? && contrato.discriminacao_obrigatoria_de_itens? && item_do_lote.present? && quantidade.present? && quantidade > (item_do_lote.saldo_por_unidade(contrato.unidade_orcamentaria.id) + quantidade_was.to_f)
			errors.add(:quantidade, "não pode ser maior que a quantidade de itens do pedido")
		end
	end
end
