class SchoolYearSession < Base::SchoolYearSession
  associations_for legacy: true do |a|
    a.belongs_to :school
    a.belongs_to :school_year
  end

  has_many :school_days, ->(record) { where(quarter: record.sequence) },
    foreign_key: :SchoolYearID, primary_key: :SchoolYearID
  has_many :additional_sessions, ->(record) { where.not(id: record.id) },
    class_name: '::SchoolYearSession', foreign_key: :SchoolYearID, primary_key: :SchoolYearID

  before_validation :set_school, unless: :school_id?

  before_create :create_school_days

  validates :name, :start, :end, presence: true
  validates :sequence, uniqueness: { scope: :school_year },
    numericality: { greater_than: 0,  message: 'must be a number and greater than 0' }

  validate :dates_within_academic_year, :end_after_start_date, :overlapping_records

  scope :ordered, -> { order(:sequence) }

  def current?
    Time.zone.today.between?(start, self.end)
  end

  private
    def set_school
      self.school_id = school_year.school_id
    end

    def create_school_days
      days_in_between = (self.end - start).to_i
      days_in_between.times do |index|
        day = start + index.days
        next if day.saturday? || day.sunday?

        school_days.build(
          date: day,
          quarter:
          sequence,
          hours: school.classroom_hours,
          half_day: false
        )
      end
    end

    def dates_within_academic_year
      valid_years = [school_year.academic_year, school_year.academic_year - 1]
      { start: start, end: self.end }.each do |prop, date|
        next if date.nil? || valid_years.include?(date.year)

        errors.add(prop, 'enter a date within the academic year')
      end
    end

    def end_after_start_date
      return if start.nil? || self.end.nil? || start < self.end

      errors.add(:end, 'cannot be before the begin date')
    end

    def overlapping_records
      return if start.nil? || self.end.nil? || start >= self.end

      additional_sessions.each do |session|
        if between_dates?(start, session)
          errors.add(:start, 'cannot overlap an existing session')
        end

        if between_dates?(self.end, session)
          errors.add(:end, 'cannot overlap an existing session')
        end

        if start < session.start && self.end > session.end
          errors.add(:start, 'cannot overlap an existing session')
          errors.add(:end, 'cannot overlap an existing session')
        end
      end
    end

    def between_dates?(date, sibling)
      date >= sibling.start && date < sibling.end
    end
end
