class Obra::OrdemDeServico < ApplicationRecord
	has_paper_trail
	attr_accessor :cadastro_direto_na_obra

	belongs_to :obra, class_name: 'Contabilidade::Obra'
	belongs_to :contrato, class_name: 'Licitacao::Contrato'
	belongs_to :empenho, class_name: 'Contabilidade::Empenho'

	has_many :ordens_de_servico, through: :obra

	validates :codigo, :data_de_inicio, :obra_id, :contrato_id, :data_da_ordem, presence: true
	validates :data_prevista_de_termino, presence: true, if: Proc.new { self.prazo_de_execucao.nil? }
	validates :prazo_de_execucao, presence: true, if: Proc.new { self.data_prevista_de_termino.nil? }
	validates :data_prevista_de_termino, :prazo_de_execucao, presence: true, if: Proc.new { self.data_prevista_de_termino.nil? && self.prazo_de_execucao.nil? }
	validates_presence_of :historico, if: Proc.new {self.obra.present? && self.obra.servico?}

	validates :codigo, length: { maximum: 12 }, numericality: { greater_than: 0 }
	validates :prazo_de_execucao, numericality: { greater_than: 0 }, allow_nil: true

	validate :data_prevista_de_termino_nao_pode_ser_anterior_a_data_de_inicio
	validate :data_de_inicio_nao_pode_ser_antes_ou_depois_da_obra
	validate :data_prevista_de_termino_nao_pode_ser_maior_que_previsao_de_termino_da_obra
	validate :prazo_de_execucao_nao_pode_ser_maior_que_previsao_de_termino_da_obra
	validate :data_de_inicio_nao_pode_ser_antes_ou_no_periodo_da_ultima_ordem, if: Proc.new { ultima_ordem_de_servico_da_obra.present? && !ultima_ordem_de_servico_da_obra.eql?(self)}
	validate :data_da_ordem_nao_pode_ser_antes_ou_depois_da_data_de_inicio, if: Proc.new { primeira_ordem_de_servico_da_obra.present? && !primeira_ordem_de_servico_da_obra.eql?(self)}
	validate :na_primeira_ordem_data_da_ordem_nao_pode_ser_antes_do_inicio_da_vigencia_do_contrato, if: Proc.new { primeira_ordem_de_servico_da_obra.blank? || (primeira_ordem_de_servico_da_obra.present? && primeira_ordem_de_servico_da_obra.eql?(self))}
	validate :data_da_ordem_nao_pode_ser_depois_da_previsao_de_termino, if: Proc.new { data_prevista_de_termino.present? && data_de_inicio.present?}
	validate :obra_precisa_ter_engenheiro_responsavel

	after_create :altera_status_da_obra

	def data_prevista_de_termino_nao_pode_ser_anterior_a_data_de_inicio
		unless data_de_inicio.nil? || data_prevista_de_termino.nil?
			errors.add(:data_prevista_de_termino, "deve ser maior que a da de início da obra") if data_prevista_de_termino < data_de_inicio
		end
	end

	def data_de_inicio_nao_pode_ser_antes_ou_depois_da_obra
		unless data_de_inicio.nil? || obra.nil?
			errors.add(:data_de_inicio, "deve ser maior ou igual a data de início da obra: #{obra.data_de_inicio}") if data_de_inicio < obra.data_de_inicio
			errors.add(:data_de_inicio, "deve ser menor ou igual a data de previsão de término da obra: #{obra.data_prevista_de_termino}") if data_de_inicio > obra.data_prevista_de_termino
		end
	end

	def data_prevista_de_termino_nao_pode_ser_maior_que_previsao_de_termino_da_obra
		unless data_prevista_de_termino.nil? || obra.nil?
			errors.add(:data_prevista_de_termino, "deve ser menor ou igual a data de previsão de término da obra: #{obra.data_prevista_de_termino}") if data_prevista_de_termino > obra.data_prevista_de_termino
		end
	end

	def prazo_de_execucao_nao_pode_ser_maior_que_previsao_de_termino_da_obra
		unless prazo_de_execucao.nil? || obra.nil?
			errors.add(:prazo_de_execucao, "prazo de execução não pode ultrapassar #{retorna_quantidade_de_dias_prazo_de_execucao} dia(s)") if self.data_prevista_de_termino > obra.data_prevista_de_termino
		end
	end

	def data_de_inicio_nao_pode_ser_antes_ou_no_periodo_da_ultima_ordem
		unless data_de_inicio.nil? || obra.nil?
			if ultima_ordem_de_servico_da_obra.data_prevista_de_termino.blank?
				errors.add(:data_de_inicio, "não pode ser menor ou dentro do período da última OS: #{ultima_ordem_de_servico_da_obra.data_de_inicio} - #{ultima_ordem_de_servico_da_obra.retorna_previsao_de_termino}") if data_de_inicio < ultima_ordem_de_servico_da_obra.data_de_inicio || data_de_inicio.between?(ultima_ordem_de_servico_da_obra.data_de_inicio, ultima_ordem_de_servico_da_obra.retorna_previsao_de_termino)
			else
				errors.add(:data_de_inicio, "não pode ser menor ou dentro do período da última OS: #{ultima_ordem_de_servico_da_obra.data_de_inicio} - #{ultima_ordem_de_servico_da_obra.data_prevista_de_termino}") if data_de_inicio < ultima_ordem_de_servico_da_obra.data_de_inicio || data_de_inicio.between?(ultima_ordem_de_servico_da_obra.data_de_inicio, ultima_ordem_de_servico_da_obra.data_prevista_de_termino)
			end
		end
	end

	def data_da_ordem_nao_pode_ser_antes_ou_depois_da_data_de_inicio
		unless data_da_ordem.nil? || obra.nil?
			errors.add(:data_da_ordem, "não pode ser antes da data de início #{self.data_de_inicio}") if self.data_da_ordem < self.data_de_inicio
			errors.add(:data_da_ordem, "não pode ser depois da data de início #{self.data_de_inicio}") if self.data_da_ordem > self.data_de_inicio
		end
	end

	def data_da_ordem_nao_pode_ser_depois_da_previsao_de_termino
		unless data_da_ordem.nil? || obra.nil?
			errors.add(:data_da_ordem, "não pode ser após a previsão de término #{self.data_prevista_de_termino}") if self.data_prevista_de_termino.present? && self.data_da_ordem > self.data_prevista_de_termino
			errors.add(:data_da_ordem, "não pode ser após a previsão de término #{retorna_previsao_de_termino}") if self.data_prevista_de_termino.blank? && self.data_da_ordem > retorna_previsao_de_termino
		end
	end

	def na_primeira_ordem_data_da_ordem_nao_pode_ser_antes_do_inicio_da_vigencia_do_contrato
		unless data_da_ordem.nil? || obra.nil?
			errors.add(:data_da_ordem, "não pode ser antes da data de início da vigência do contrato #{self.obra.contrato.inicio_da_vigencia}") if (self.data_da_ordem < self.obra.contrato.inicio_da_vigencia)
		end
	end

	def obra_precisa_ter_engenheiro_responsavel
		errors.add(:obra_id, "obra precisa ter engenheiro responsável cadastrado") if self.obra && !self.obra.engenheiros_da_obra.any?
	end

	def ultima_ordem_de_servico_da_obra
		ordens_de_servico.order(data_de_inicio: :desc).first
	end

	def primeira_ordem_de_servico_da_obra
		ordens_de_servico.order(data_de_inicio: :asc).first
	end

	def retorna_previsao_de_termino
		unless prazo_de_execucao.nil?
			(self.data_de_inicio + self.prazo_de_execucao)
		end
	end

	def retorna_prazo_de_execucao
		(self.data_prevista_de_termino - self.data_de_inicio).to_i
	end

	def retorna_quantidade_de_dias_prazo_de_execucao
		(self.obra.data_prevista_de_termino - self.data_de_inicio).to_i
	end

	private

	def altera_status_da_obra
		tipo_de_status = Contabilidade::SituacaoDaObra.tipos_de_status_da_obra[:em_andamento] #status: em andamento
		obra.situacoes_da_obra.create(data_da_situacao: self.data_de_inicio, tipo_de_status_da_obra: tipo_de_status)
	end

end
