class Ecs::ImportCourseStudentAchievementService < ApplicationService
  Error = Class.new(StandardError)

  attr_reader :ec_year, :course_evaluation, :attachment

  def initialize(course_evaluation, attachment_id)
    @course_evaluation = course_evaluation
    @ec_year = course_evaluation.ec_course.ec_year
    @attachment = Attachment.find_by(id: attachment_id)
  end

  def call
    raise Error, '文件不存在' if attachment.blank?
    raise Error, '请先导入学生数据' if ec_year.ec_year_students.count.zero?

    path = attachment.diskfile
    excel = Ecs::ImportAchievementExcel.new(path)

    ActiveRecord::Base.transaction do
      course_evaluation.ec_student_achievements.delete_all

      handler = excel.average_score_template? ? :average_score_handler : :detail_score_handler
      EcStudentAchievement.bulk_insert(*achievement_columns) do |worker|
        excel.read_each do |arr|
          send(handler, worker, arr)
        end
      end

      score_type = excel.average_score_template? ? :average : :detail
      current_course_evaluation.update!(import_status: true, score_type: score_type)
    end
  rescue BaseImportExcel::Error => ex
    raise Error, ex.message
  end

  private

  def achievement_columns
    %i[
      score student_name student_number position ec_year_student_id
      ec_course_evaluation_id ec_course_evaluation_subitem_id created_at updated_at
    ]
  end

  def average_score_handler(worker, arr)
    items_size = course_evaluation.ec_course_evaluation_subitems.size

    ec_year.ec_year_students.find_each do |student|
      course_evaluation.ec_course_evaluation_subitems.each_with_index do |evaluation_subitem, index|
        course_evaluation.evaluation_count.times do |times|
          score = arr[times * items_size + index].to_i  # 共4个分项:第一次考核的第三项下标为 0 * 4 + 2,即 2
          attrs = {
            score: score, student_name: student.name, student_number: student.student_id,
            position: times + 1, ec_year_student_id: student.id, ec_course_evaluation_id: course_evaluation.id,
            ec_course_evaluation_subitem_id: evaluation_subitem.id
          }
          worker.add(attrs)
        end
      end
    end
  end

  def detail_score_handler(worker, arr)
    student = ec_year_students.find_by(student_id: arr[0].is_a?(Float) ? arr[0].to_i : arr[0].to_s.strip)
    return if student.blank?

    items_size = course_evaluation.ec_course_evaluation_subitems.size
    course_evaluation.ec_course_evaluation_subitems.each_with_index do |evaluation_subitem, index|
      course_evaluation.evaluation_count.times do |times|
        # 因为0和1是学号和姓名,所以下标要 + 2
        score = arr[times * items_size + 2 + index].to_i  # 共4个分项:第一次考核的第三项下标为 0 * 4 + 2 + 2,即 arr[4]
        attrs = {
          score: score, student_name: student.name, student_number: student.student_id,
          position: times + 1, ec_year_student_id: student.id, ec_course_evaluation_id: course_evaluation.id,
          ec_course_evaluation_subitem_id: evaluation_subitem.id
        }
        worker.add(attrs)
      end
    end
  end
end