include DiaryHelper
class Plan < ApplicationRecord
	before_save :set_recorders
	after_create :create_diet
	after_create :create_routine
	#relations
	[:meals, :routines].each do |_attr|
		has_many _attr, dependent: :destroy
		accepts_nested_attributes_for _attr, :allow_destroy => true
	end
	has_many :portions, through: :meals
	belongs_to :trainer, class_name: "User"
	belongs_to :subscription, optional: true
	belongs_to :user
	has_one :program

	[:front, :side, :back].each { |_attr| mount_uploader _attr, ImageUploader }
	# [:front, :side, :back].each { |_attr| mount_base64_uploader _attr, ImageUploader }

	def expires_ago
		today = Time.zone.now.to_date
		# return "Expirado" if today > (finish.to_date + 1.week)
		days = (today - finish.to_date).to_i
		weeks = ~~(days/7)
		months = ~~(days/30)
		years = ~~(months/12)
		if days < 0
			return "En #{days.abs} día#{'s' if days.abs > 1}"
		elsif days == 0 
			return "Hoy"
		elsif days < 7 
			return "Hace #{days} día#{'s' if days > 1}. En cortesía."
		elsif days == 7 
			return "El tiempo de cortesía termina hoy"
		elsif months > 1
			return "Hace #{months} mes#{'es' if months > 1 }"
		elsif years >= 1
			return "Hace #{years} año#{'s' if years > 1 }"
		else
			return "Hace #{weeks} semana#{'s' if weeks > 1 }"
		end
	end

	def pdf_name
		user_name = self.user.short_name.downcase.gsub(/[^0-9A-Za-z]/, '_')
		user_name = ActiveSupport::Inflector.transliterate(user_name)
		"NTS-PlanIntegral_#{number}-#{user_name}"
	end

	def cardio_schedule_description
		["el horario de tu preferencia", "ayunas", "antes de entrenar", "después de entrenar"][cardio_schedule]
	end

	def pasos
		values = ["conteo de", "de 6,000 a 8,000", "de 8,000 a 10,000", "de 10,000 a 12,000", "de 12,000 a 14,000"]
		"Realiza #{values[steps]} pasos diarios"
	end

	def heart_rate
		total = (220 - user.years.to_i)
		min = (total * 0.6).to_i
		max = (total * 0.7).to_i
		return "#{min} y #{max}"
	end

	def date
		return "#{self.init.strftime("%b")}-#{self.finish.strftime("%b %y")}"
	end

	def programa
		# Relación virtual para obtener el macho ligado al plan
		if self.programa_id.to_s != "0" && !self.programa_id.nil?
			# {programa_id} guarda el id del macho (programa) que se seleccionó para crear el plan
			# NO CONFUNDIR CON LA RELACIÓN has_one :program
			# @see program.rb
			_program = Program.where(id: self.programa_id).first
			return _program if _program
		end
		return nil
	end

	def height
		user.height
	end

	def total_meals
		return meals.count * total_days
	end
	
	def meals_today
		return meals.count * current_day
	end

	def registered_meals 
		count = 0
		registro_diario(self).each_with_index do |day, idx|
			day.each { |register| count += 1 if register.to_i != 0 }
		end
		return count
	end

	def ccd
		_tmb = get_tmb.to_f
		case factor_activity.to_i
		when 0
			# 0 Sedentario CCD = TMB x 1.2 (trabajo de escritorio sin ejercicio)
			return (_tmb * 1.2).to_i
		when 1
			# 1 Actividad ligera CCD = TMB x 1.375 (ejercicio de 1 a 3 días x semana)
			return (_tmb * 1.375).to_i
		when 2
			# 2 Actividad moderada CCD = TMB x 1.55 (ejercicio de 3-5 días x semana)
			return (_tmb * 1.55).to_i
		when 3
			# 3 Actividad intensa CCD = TMB x 1.725 (ejercicio de 6-7 días x semana)
			return (_tmb * 1.725).to_i
		when 4
			# 4 Actividad muy intensa CCD = TMB x 1.9 (ejercicio 2 veces al día, ejercicios de mucha fuerza y agotamiento, deportistas profesionales)
			return (_tmb * 1.9).to_i
		end
	end

	def total_days
		if self.init && self.finish
			return (self.finish - self.init).to_i + 1
		else
			return 0
		end
	end

	def need_adjust
		if is_active?
			current_plan = false
			m = Message.where("created_at >= ? AND created_at <= ? AND user_id = ?", self.init.beginning_of_day, self.finish.end_of_day, self.user.id)
			if self.user
				current_plan = self.user.plans.where("finish >= ?", Date.today).count > 1
			end
			return week >= 3 && m.count == 0 && !current_plan
		else
			return false
		end
	end

	def week
		return (current_day / 7).floor + 1
	end

	# cálculos basados en macros
	def proteins
		get_fact(macros_protein)
	end

	def carbs
		get_fact(macros_carbs)
	end
	
	def fats
		get_fact(macros_fats)
	end

	def get_fact(macro)
		if macro.to_f == 0.0
			return 0
		else 
			return (macro.to_f * kg.to_f).to_i
		end
	end

	def cals_per_kg
		if kg.to_f == 0.0 || total_calories.to_f == 0.0
			return '-'
		else
			return (total_calories.to_f / kg.to_f).round(1)
		end
	end

	# totales
	def recommended_calories
		return ((proteins * 4) + (fats * 9) + (carbs * 4)).round(1)
	end

	def total_carbs
		total = 0
		self.meals.each do |m|
			m.meal_portions.each { |mp| total += mp.carbs }
		end
		return total.round(1)
	end

	def total_proteins
		total = 0
		self.meals.each do |m|
			m.meal_portions.each { |mp| total += mp.proteins }
		end
		return total.round(1)
	end

	def total_fats
		total = 0
		self.meals.each do |m|
			m.meal_portions.each { |mp| total += mp.fats }
		end
		return total.round(1)
	end

	def progreso
		txt = "Plan #{number} | Semana #{((progress-1) * 4) + week}°"
		# txt += " - Día #{current_day} de #{total_days} " if is_active?
		txt += " | #{I18n.localize(init, format: '%d %b').titleize} - #{I18n.localize(finish, format: '%d %b %y').titleize}"
	end

	def total_calories
		total = 0
		self.meals.each { |m| m.meal_portions.each { |mp| total += mp.calories } }
		return total.round(1)
	end

	def period
		"#{self.init.strftime('%m/%d/%y')} - #{self.finish.strftime('%m/%d/%y')}"
	end

	def current_day
		return self.index_day + 1
	end

	def index_day
		return [(Time.zone.now.to_date - self.init).to_i, (self.finish - self.init).to_i].min
	end

	def is_active?
		return (self.finish + 1.week) >= Time.zone.now.to_date
	end

	def state
		return is_active? ? "active" : "inactive"
	end

	def get_tmb
		if tmb.blank? || tmb.to_i.to_s == "0"
			if self.user.sex == "male"
				(66.4730 + (13.7516 * (self.kg || 0).to_f) + (5.0033 * (self.user.height || 0).to_f - (6.7550 * (self.user.years || 0).to_f))).to_i
			else
				(655.0955 + (9.5634 * (self.kg || 0).to_f) + (1.8449 * (self.user.height || 0).to_f - (4.6756 * (self.user.years || 0).to_f))).to_i
			end
		else
			tmb
		end
	end

	def user_plans
		user.plans.order(created_at: :asc)
	end
	def number
		idx = user_plans.index(self) || -1
		return idx + 1
	end
	def previous_plan
		user_plans[number - 2]
	end
	
	def create_diet
		_plan = current_diet == "clone" ? previous_plan : Plan.find(current_diet)
		return false if !_plan
		self.update(supplements: _plan.supplements, ped: _plan.ped, medicine: _plan.medicine)
		meals.each { |m| m.meal_portions.delete_all }
    	meals.delete_all
		#
		_plan.meals.each do |m|
			meal = m.dup
			meal.update(plan_id: self.id)
			m.meal_portions.each do |mp|
				meal_portion = mp.dup
				meal_portion.update(meal_id: meal.id)
				mp.substitutes.each do |sbt|
					substitute = sbt.dup 
					substitute.update(equalable_id: meal_portion.id)
				end
			end
		end
	end

	def create_routine
		_plan = current_routine == "clone" ? previous_plan : Plan.find(current_routine)
		return false if !_plan
		_title = current_routine == "clone" ? "Plan Anterior" : (_plan.programa ? _plan.programa.title : _plan.title)
		self.update(title: _title, groups: _plan.groups, medicine: _plan.medicine, programa_id: _plan.id, cardio: _plan.cardio)
		#
		routines.each { |r| r.routine_workouts.delete_all }
		routines.delete_all
		_plan.routines.order(number: :asc).each_with_index do |r, idx|
			routine = r.dup
			routine.update(plan_id: self.id, number: idx, safe_url: SecureRandom.urlsafe_base64(12, false), history: "")
			r.routine_workouts.each do |rw|
				routine_workout = rw.dup
				routine_workout.update(routine_id: routine.id, history: "", charge: (rw.history.to_s.split("|").last || rw.charge)) # history: charge, 
			end
		end
	end

	private

	def set_recorders
		# Utilizando el total de días y el número de comidas por día
		# Se genera una matrix para el registro de comidas
		# 0 para comidas no registradas, se actualizará a 1 cada comida realizada en un registro dentro del arreglo
		# La matriz se genera a partir de un string, un split en | generará los espacios por días
		self.sessions_notes = "|" * self.total_days if self.sessions_notes.blank?
		self.cardio_record = "|" * self.total_days if self.cardio_record.blank?
		self.meals_record = ("0" * self.meals.count + "|") * self.total_days if self.meals_record.blank?
		self.comments = "|" * self.total_days if self.comments.blank?
	end

end