class Admin::Legacy::Discipline::DetentionsController < Admin::Legacy::Discipline::Controller
  def index
    data = detentions
      .by_student_ids(params[:student_ids])
      .by_classroom(params[:classroom_ids])
      .decorate
    render_success :ok, json: data.map { |d| detention_props(d) }
  end

  def batch_create
    if students.empty?
      return render_error :unprocessable_entity,
        errors: { students: 'Must select at least one student' }
    end

    batch = students.map do |student|
      detention = student.discipline_detentions.build(detention_params)
      detention.author = current_user
      detention
    end

    if transactional_save(batch)
      render_success :ok, message: "#{batch.count} detentions created.",
        json: batch.map { |d| detention_props(d.decorate) }
    else
      render_error :unprocessable_entity, errors: multi_errors(batch)
    end
  end

  def pending
    pending_or_waived = []
    # Loop thru discipline_student_logs and find students with enough points to trigger a detention
    students_with_pending_detentions.each do |student_id, total_points|
      student = students_by_id[student_id]
      subtotal_points = 0
      remaining_points = total_points

      # Loop thru student logs and add up points to create pending detentions
      logs_by_student[student_id].each do |log|
        subtotal_points += log.points
        log_datetime = log.datetime.to_date
        detentions = detentions_by_student[student_id] || []

        # Loop thru as many times point to trigger is reached in subtotal & add pending detentions
        (subtotal_points / config.points_to_trigger).floor.times do
          # Pop off the first detention from the array if any exist
          detention = detentions.shift
          status = detention&.waived ? :waived : :pending
          detention_id = detention&.id
          log_datetime = detention&.posted_on || log_datetime
          remaining_points -= config.points_to_trigger

          # Only add detention if it's waived or pending
          if detention.nil? || detention.waived
            pending_or_waived << {
              detention_id: detention_id,
              student_id: student_id,
              full_name: student.full_name(:reverse),
              subtotal_points: subtotal_points,
              remaining_points: remaining_points,
              datetime: log_datetime,
              status: status
            }
          end

          # Subtract points_to_trigger from subtotal_points
          subtotal_points -= config.points_to_trigger
        end
      end
    end

    render_success :ok, json: pending_or_waived
  end

  private
    def detentions
      current_school.discipline_student_detentions.includes(:student, :author, :monitor)
    end

    def config
      @config ||= current_school.find_or_build_discipline_config
    end

    def students
      current_school.students.where(id: params[:student_ids])
    end

    def detention_params
      params.permit(:posted_on, :served_on, :length, :comments, :monitor_id, :waived)
    end

    def students_with_pending_detentions
      @students_with_pending_detentions ||= current_school.discipline_student_logs
        .sums_by_student_with_pending_detentions(config)
    end

    def students_by_id
      @students_by_id ||= current_school.students
        .where(id: students_with_pending_detentions.keys)
        .index_by(&:id)
    end

    def logs_by_student
      @logs_by_student ||= current_school.discipline_student_logs
        .where(student_id: students_by_id.keys)
        .group_by(&:student_id)
    end

    def detentions_by_student
      @detentions_by_student ||= current_school.discipline_student_detentions
        .where(student_id: students_by_id.keys)
        .group_by(&:student_id)
    end

    def detention_props(detention)
      {
        id: detention.id,
        student_id: detention.student_id,
        name: detention.student_full_name(:reverse),
        grade: detention.student_grade,
        grade_label: grade_levels[detention.student_grade],
        posted_on: detention.posted_on,
        served_on: detention.served_on,
        length: detention.length,
        monitor_name: detention.monitor_full_name(:reverse),
        author_name: detention.author_full_name(:reverse),
        waived: detention.waived
      }
    end
end
