class Licitacao::ItemDoAditivo < ApplicationRecord
	has_paper_trail

	attr_accessor :quantidade_saldo
	attr_accessor :valor_atualizado
	attr_accessor :quantidade_solicitada

	attr_accessor :tipo_de_itens_do_aditivo

	belongs_to :item_do_lote, class_name: 'Licitacao::ItemDoLote', required: true
	belongs_to :aditivo, class_name: 'Licitacao::Aditivo', required: true

	delegate :contrato, to: :aditivo

	validates_presence_of :item_do_lote_id, :aditivo_id
	validates_presence_of :quantidade, if: Proc.new { aditivo.qualitativo? }

	validates_numericality_of :quantidade, greater_than_or_equal_to: 0, allow_nil: true
	validates_numericality_of :valor_adicionado, greater_than_or_equal_to: 0, allow_nil: true, if: Proc.new { aditivo && (aditivo.reajuste_de_valor_acrescimo? || aditivo.reajuste_de_valor_decrescimo?)}

	validate :valida_quantidade_dos_itens_no_aditivo_de_reducao, if: Proc.new { aditivo && aditivo.reducao? }
	validate :valida_quantidade_dos_itens_nos_aditivos_de_reajuste, if: Proc.new { aditivo && (aditivo.reajuste_de_valor_acrescimo? || aditivo.reajuste_de_valor_decrescimo?) }
	validate :valida_valor_do_reajuste_de_decrescimo, if: Proc.new { aditivo && aditivo.reajuste_de_valor_decrescimo? }

	after_save :apaga_a_si_mesmo_se_quantidade_for_zero_ou_nula, unless: Proc.new { aditivo.qualitativo? }
	after_save :apaga_a_si_mesmo_se_valor_adicionado_for_zero_ou_nulo, if: Proc.new { aditivo && (aditivo.reajuste_de_valor_acrescimo? || aditivo.reajuste_de_valor_decrescimo?)}

	before_save :define_diferenca_da_quantidade
	before_save :calcular_quantidade_total_prazo_e_acrescimo, if: Proc.new { aditivo.prazo_e_acrescimo? }
	before_save :calcular_quantidade_total_prazo_e_reducao, if: Proc.new { aditivo.prazo_e_reducao? }
	before_save :set_valor_total_prazo_reducao_e_acrescimo, if: Proc.new { aditivo.prazo_e_reducao? || aditivo.prazo_e_acrescimo? }
	before_save :set_valor_total_prazo_e_reajuste, if: Proc.new { aditivo.prazo_e_reajuste_acrescimo? || aditivo.prazo_e_reajuste_decrescimo? }
	

	scope :acrescimo, -> { joins(:aditivo).where(licitacao_aditivos: { modalidade: Licitacao::Aditivo.modalidades["acrescimo"] }) }
	scope :reducao, -> { joins(:aditivo).where(licitacao_aditivos: { modalidade: Licitacao::Aditivo.modalidades["reducao"] }) }
	scope :por_prazo, -> { joins(:aditivo).where(licitacao_aditivos: { modalidade: Licitacao::Aditivo.modalidades.values_at("por_prazo", "prazo_e_acrescimo", "prazo_e_reducao", "prazo_e_reajuste_acrescimo", "prazo_e_reajuste_decrescimo", "renovacao") }) }
	scope :por_prazo_e_acrescimo, -> { joins(:aditivo).where(licitacao_aditivos: { modalidade: Licitacao::Aditivo.modalidades["prazo_e_acrescimo"] }) }
	scope :por_prazo_e_reducao, -> { joins(:aditivo).where(licitacao_aditivos: { modalidade: Licitacao::Aditivo.modalidades["prazo_e_reducao"] }) }
	scope :por_id_dos_itens_do_lote, -> { joins(:item_do_lote).includes(item_do_lote: { item_do_pedido: :item }).order(:id) }
	scope :por_ordem_dos_itens_do_lote, -> {
		joins(:item_do_lote).includes(item_do_lote: { item_do_pedido: :item }).order(:ordem)
	}

	# BOOLEANS
	def lote_de_produto?
		item_do_lote.lote.present? ? item_do_lote.lote.produto? : false
	end

	def lote_de_servico?
		item_do_lote.lote.present? ? item_do_lote.lote.servico? : false
	end

	def possui_aditivo_de_reajuste?
		contrato.itens_do_aditivo.merge(Licitacao::Aditivo.de_reajuste_de_valor).where("licitacao_aditivos.id < ?", self.aditivo_id).any?
	end

	def possui_aditivo_de_reajuste_na_ata?
		contrato.ata_de_registro_de_precos.present? && contrato.ata_de_registro_de_precos.aditivos_da_ata.confirmados.de_reajuste_de_valor.any?
	end

	# AÇÕES
	def apaga_a_si_mesmo_se_quantidade_for_zero_ou_nula
		self.delete if self.quantidade == 0 || self.quantidade.nil?
	end

	def apaga_a_si_mesmo_se_valor_adicionado_for_zero_ou_nulo
		self.delete if self.valor_adicionado == 0 || self.valor_adicionado.nil?
	end

	# VALIDAÇÕES
	def valida_quantidade_dos_itens_no_aditivo_de_reducao
		if self.quantidade && (self.quantidade.to_f.round(2) > (quantidade_permitida_para_reducao.to_f).abs)
			errors.add(:quantidade, "não pode ser maior que o saldo de itens no contrato")
		end
	end

	def valida_quantidade_dos_itens_nos_aditivos_de_reajuste
		unless item_do_lote.lote.servico?
			if self.quantidade && (self.quantidade.to_f.round(2) > quantidade_permitida_para_reajuste.to_f.round(2))
				errors.add(:quantidade, "não pode ser maior que o limite disponível")
			end
		end
	end

	def valida_valor_do_reajuste_de_decrescimo
		# Valor não pode ser maior que o valor unitário do item senão fica negativo
		if self.valor_adicionado && (self.valor_adicionado > valor_do_item)
			errors.add(:valor_adicionado, "não pode ser maior que o valor unitário do item")
		end
	end

	# QUANTIDADES
	def quantidade_do_item_do_contrato_por_item_do_lote
		contrato.itens_do_contrato.find_by_item_do_lote_id(item_do_lote).quantidade
	end

	def quantidade_total_por_item
		contrato.quantidade_total_por_item(item_do_lote.item)
	end

	def quantidade_aditivada_por_item
		quantidade_total_por_item - quantidade_do_item_do_contrato_por_item_do_lote
	end

	def quantidade_aditivada_anteriormente_por_item
		qtd_acrescida = contrato.itens_do_aditivo.acrescimo.where("licitacao_aditivos.id < ?", aditivo.id).where(item_do_lote: item_do_lote).sum(:quantidade).to_f
		qtd_reduzida = contrato.itens_do_aditivo.reducao.where("licitacao_aditivos.id < ?", aditivo.id).where(item_do_lote: item_do_lote).sum(:quantidade).to_f
		qtd_acrescida - qtd_reduzida
	end

	def quantidade_por_prazo_do_item
		contrato.quantidade_dos_aditivos_de_prazo_por_item(item_do_lote.item)
	end

	def quantidade_liquidada_por_item
		contrato.quantidade_liquidada_por_item(item_do_lote.item)
	end

	def saldo
		contrato.itens_do_contrato.find_by_item_do_lote_id(item_do_lote).present? ? contrato.itens_do_contrato.find_by_item_do_lote_id(item_do_lote).saldo : 0
	end

	def calcular_quantidade_total_prazo_e_acrescimo
    self.quantidade = quantidade_prorrogada.to_f + quantidade_acrescida.to_f
  end

	def calcular_quantidade_total_prazo_e_reducao
		self.quantidade = quantidade_prorrogada.to_f - quantidade_reduzida.to_f
  end

	def valor_atualizado_prazo_reajuste_acrescimo_ou_decrescimo
		
		if aditivo.prazo_e_reajuste_acrescimo?
			valor_do_item + self.valor_adicionado
		else
			valor_do_item - self.valor_adicionado
		end
	end
	

	def set_valor_total_prazo_reducao_e_acrescimo
		if (aditivo.prazo_e_acrescimo? || aditivo.prazo_e_reducao?)
			total = self.quantidade * valor_do_item
		end
		self.total = total
	end	

	def set_valor_total_prazo_e_reajuste
		if (aditivo.prazo_e_reajuste_acrescimo? || aditivo.prazo_e_reajuste_decrescimo?)
			total = (self.quantidade.to_d * valor_atualizado_prazo_reajuste_acrescimo_ou_decrescimo.to_d).round(2)	
		end	
		self.total = total
	end

	def quantidade_permitida_para_reducao
		# Segundo a lei deveria ser os mesmos 25%/50% mas foi pedido pra ser até o saldo do item
		saldo.to_f
	end

	def quantidade_permitida_para_reajuste
		# Reajuste => Obra, serviço de eng. e serviço puxa o total do contrato e aquisição puxa o total - liquidado
		if aditivo.contrato.obra_ou_servico? || (aditivo.contrato.outros_contratos? && lote_de_servico?)
			quantidade_total_por_item.to_f
		elsif lote_de_produto?
			saldo.to_f
		else
			saldo.to_f
		end
	end

	# Não limita para acréscimo e nem para prazo
	def quantidade_permitida
		if aditivo.reducao?
			quantidade_permitida_para_reducao
		elsif aditivo.reajuste_de_valor_acrescimo? || aditivo.reajuste_de_valor_decrescimo?
			quantidade_permitida_para_reajuste
		end
	end

	# VALORES
	def valor_dos_reajustes_do_item
		acrescimo = contrato.itens_do_aditivo.merge(Licitacao::Aditivo.reajuste_de_valor_acrescimo).where("licitacao_aditivos.id < ?", self.aditivo_id).where(item_do_lote: item_do_lote).sum(:valor_adicionado)
		decrescimo = contrato.itens_do_aditivo.merge(Licitacao::Aditivo.reajuste_de_valor_decrescimo).where("licitacao_aditivos.id < ?", self.aditivo_id).where(item_do_lote: item_do_lote).sum(:valor_adicionado)
		acrescimo_apostilamento = item_do_contrato.valor_acrescido_por_apostilamento
		decrescimo_apostilamento = item_do_contrato.valor_reduzido_por_apostilamento
		acrescimo_apostilamento + acrescimo - decrescimo - decrescimo_apostilamento
	end

	def valor_do_item
		valor_do_item = contrato.discriminacao_obrigatoria_de_itens? ? item_do_lote.preco_unitario : item_do_contrato.valor_unitario
		if !possui_aditivo_de_reajuste_na_ata? && possui_aditivo_de_reajuste?
			(valor_do_item + valor_dos_reajustes_do_item).to_f
		elsif possui_aditivo_de_reajuste_na_ata?
			contrato.itens_do_contrato.find_by(item_do_lote_id: item_do_lote.id).valor_unitario.to_f
		elsif item_do_lote.lote.lote_por_desconto?
			item_do_lote.preco_unitario_por_unidade_orcamentaria(contrato.unidade_orcamentaria.id).to_f
		else
			valor_do_item.to_f
		end
	end

	def valor_total
		if aditivo.present? && aditivo.reajuste_de_valor_acrescimo?
			(self.quantidade.to_f * self.valor_adicionado.to_f).round(2)
		elsif aditivo.present? && aditivo.reajuste_de_valor_decrescimo?
			(self.quantidade.to_f * - self.valor_adicionado.to_f).round(2)
		elsif aditivo.present? && (aditivo.acrescimo? || aditivo.por_prazo? || aditivo.qualitativo?)
			(self.quantidade.to_f * valor_do_item.to_f).round(2)
		elsif aditivo.present? && aditivo.reducao?
			(self.quantidade.to_f * - valor_do_item.to_f).round(2)
		elsif aditivo.present? && aditivo.renovacao?
			total.to_f
		elsif aditivo.present? && (aditivo.prazo_e_reajuste_acrescimo?)
			(self.quantidade.to_f * (valor_do_item.to_f + self.valor_adicionado.to_f)).round(2)
		elsif aditivo.present? && (aditivo.prazo_e_reajuste_decrescimo?)	
			(self.quantidade.to_f * (valor_do_item.to_f - self.valor_adicionado.to_f)).round(2)
		end
	end

	def valor_final_item_do_aditivo_de_reequilibrio
		#Foi preciso criar outro método, pois o método valor_do_item, não puxa o valor atualizado no presente aditivo, isso porque é o mesmo método utilizado para a grid de itens do aditivo
		acrescimo = contrato.itens_do_aditivo.merge(Licitacao::Aditivo.reajuste_de_valor_acrescimo).where("licitacao_aditivos.id <= ?", self.aditivo_id).where(item_do_lote: item_do_lote).sum(:valor_adicionado)
		decrescimo = contrato.itens_do_aditivo.merge(Licitacao::Aditivo.reajuste_de_valor_decrescimo).where("licitacao_aditivos.id <= ?", self.aditivo_id).where(item_do_lote: item_do_lote).sum(:valor_adicionado)
		valor_reajustado = acrescimo - decrescimo
		return item_do_lote.preco_unitario.to_f + valor_reajustado.to_f
	end

	def porcentagem_quantidade
		porcentagem = 100 * self.quantidade.to_f / self.quantidade_do_item_do_contrato_por_item_do_lote.to_f
	end

	def define_diferenca_da_quantidade
		self.diferenca_da_quantidade = quantidade.to_d - contrato.saldo_a_empenhar_do_item(item_do_lote).to_d
	end

	def item_do_contrato
		@item_do_contrato ||= contrato.itens_do_contrato.find_by(item_do_lote_id: item_do_lote_id)
	end
end
