class HomeworkCommon < ApplicationRecord
  # homework_type 1：普通作业  2：编程作业（弃用） 3：分组作业  4：实训作业
  enum homework_type: { normal: 1, program: 2, group: 3, practice: 4 }, _suffix: true
  has_many :homework_group_settings, dependent: :destroy
  has_many :published_settings, -> { group_published }, class_name: "HomeworkGroupSetting"
  has_many :student_works, -> { where("is_delete = 0") }
  has_many :score_student_works, -> { where("is_delete = 0 and work_status != 0").order("work_score desc") }, class_name: "StudentWork"
  has_one :homework_detail_manual, dependent: :destroy

  # 分组作业的设置
  has_one :homework_detail_group, dependent: :destroy

  belongs_to :course, counter_cache: true
  belongs_to :homework_bank, optional: true
  belongs_to :user
  has_many :homework_challenge_settings, dependent: :destroy

  has_one :homework_commons_shixun, dependent: :destroy
  has_and_belongs_to_many :shixuns, through: :homework_commons_shixun

  # attachtype: 1（描述的附件）， 2（参考答案的附件）
  has_many :attachments, as: :container, dependent: :destroy

  # 作业的评论
  has_many :journals_for_messages, as: :jour, dependent: :destroy

  # 二级目录
  belongs_to :course_second_category, optional: true

  # 课堂动态
  has_many :course_acts, class_name: 'CourseActivity', as: :course_act, dependent: :destroy
  has_many :tidings, as: :container, dependent: :destroy
  # 实训作业的分班查重记录
  has_many :homework_group_reviews, :dependent => :destroy
  # 学生的查重情况
  has_many :homework_review_results, :dependent => :destroy

  validates :name, length: { maximum: 60 }
  validates :description, length: { maximum: 15000 }
  validates :reference_answer, length: { maximum: 15000 }

  # after_update :update_activity
  before_destroy :update_homework_bank_quotes

  #1已发布的课堂作业
  scope :homework_published, -> {where("homework_commons.publish_time IS NOT NULL AND homework_commons.publish_time <= ? ",Time.now)}
  scope :published_no_end, -> {where("homework_commons.publish_time IS NOT NULL AND homework_commons.publish_time < ?
                                      and homework_commons.end_time > ?", Time.now, Time.now)}
  scope :search_homework_type, lambda {|num| where(homework_type:num)}
  scope :unified_setting, -> {where("unified_setting = ? ", 1)}

  scope :normals,  -> {where(homework_type: %i[normal]).order("position desc")}
  scope :groups,  -> {where(homework_type: %i[group]).order("position desc")}
  scope :practices,  -> {where(homework_type: %i[practice]).order("position desc")}

  # 是否显示参考答案
  def view_answer identity, user_id
    identity < Course::STUDENT || (identity == Course::STUDENT && answer_public &&
        self.end_or_late && self.user_work(user_id).try(:work_status).to_i > 0)
  end

  # 申诉阶段
  def appeal_duration
    self.anonymous_appeal && [3, 4].include?(homework_detail_manual.comment_status)
  end

  # 作业对应的子目录/父目录名称
  def category_info
    case self.homework_type
    when 'normal'
      {category_id: course.common_course_modules.first.try(:id), category_name: course.common_course_modules.first.try(:module_name), main: 1}
    when 'group'
      {category_id: course.group_course_modules.first.try(:id), category_name: course.group_course_modules.first.try(:module_name), main: 1}
    when 'practice'
      if self.course_second_category.present?
        {category_id: self.course_second_category.try(:id), category_name: self.course_second_category.try(:name), main: 0}
      else
        {category_id: course.shixun_course_modules.take.try(:id), category_name: course.shixun_course_modules.take.try(:module_name), main: 1}
      end
    end
  end

  # 根据是否统一发布获取作业的作品列表
  def all_works
    student_works = self.unified_setting ? self.student_works :
                        self.student_works.joins("join course_members on student_works.user_id=course_members.user_id").
                            where(course_members: {course_group_id: self.published_settings.pluck(:course_group_id)})
  end

  # 分班权限的老师可见的作品列表
  def teacher_works member
    # member = course.course_member(user_id)
    teacher_course_groups = member.try(:teacher_course_groups)
    all_student_works = self.all_works
    # 有分班权限的统计管理的分班且已发布的学生情况
    if member.present? && teacher_course_groups.exists?
      group_ids = teacher_course_groups.pluck(:course_group_id)
      all_student_works = all_student_works.joins("join course_members on student_works.user_id=course_members.user_id").
          where(course_members: {course_group_id: group_ids})
    end
    all_student_works
  end

  def user_work user_id
    work = self.student_works.find_by_user_id(user_id)
  end

  # 是否在补交阶段内
  def late_duration
    homework_setting = self.homework_group_setting(User.current.id)
    !course.is_end && self.publish_time && self.publish_time < Time.now && homework_setting.end_time &&
        homework_setting.end_time < Time.now && self.allow_late && (self.late_time.nil? || self.late_time > Time.now)
  end

  # 作业是否补交截止或者不允许补交且提交截止
  def end_or_late
    status = false
    if self.course.is_end || (self.allow_late && self.late_time && self.late_time < Time.now)
      status = true
    elsif !self.allow_late
      homework_setting = self.homework_group_setting(User.current.id)
      status = homework_setting.end_time && homework_setting.end_time < Time.now
    end
    status
  end

  # 作业是否补交截止或者不允许补交且提交截止(不考虑分班)
  def end_or_late_none_group
    course.is_end || (allow_late && late_time < Time.now) || (!allow_late && end_time < Time.now)
  end

  # 作业是否可以查重
  def code_review
    self.homework_type == 'practice' && self.publish_time.present? && self.publish_time < Time.now && self.homework_group_reviews.count == 0
  end

  # 作业能否立即发布
  def publish_immediately user
    homework_detail_manual.try(:comment_status) == 0 || homework_group_settings.where(course_group_id: course.charge_group_ids(user)).
        none_published.count > 0
  end

  # 作业能否立即截止
  def end_immediately user
    (unified_setting && homework_detail_manual.try(:comment_status) == 1 && end_time > Time.now) || homework_group_settings.
        where(course_group_id: course.charge_group_ids(user)).published_no_end.count > 0
  end

  # 学生是否提交了作品
  def user_has_commit_work user_id
    work = self.student_works.find_by_user_id(user_id)
    work.present? && work.work_status != 0
  end

  # 是否有学生提交过作品
  def has_commit_work
    student_works.has_committed.count > 0
  end

  # 是否有学生关联了项目
  def has_relate_project
    homework_type == "group" && student_works.where("project_id != 0").count > 0
  end

  # 作业描述的附件
  def des_attachments
    attachments.where(attachtype: 1)
  end

  # 参考答案的附件
  def ref_attachments
    attachments.where(attachtype: 2)
  end

  def update_activity
    course_activity = CourseActivity.find_by_course_act_type_and_course_act_id(self.class.to_s, self.id)

    course_activity.update_attributes(updated_at: Time.now) if course_activity
  end

  #删除时更新题库中的引用数
  def update_homework_bank_quotes
    old_bank = self.homework_bank
    old_bank.update_attributes(quotes: (old_bank.quotes - 1) > 0 ? (old_bank.quotes - 1) : 0, homework_common_id: nil) if old_bank.present?
  end

  # 查重是否有新结果
  def code_reviews_new_results?
    self.homework_group_reviews.where(status: 0).count > 0
  end

  # 任务已评数 user_id: 对应老师的id
  def comment_count(user_id)
    course = self.course
    # 如果有分班，则取此老师对应分班的已评数，没有分班，则取所有的
    course_group_ids = course.group_course_power(user_id)
    sql =
        if course_group_ids.count > 0
          %Q{
            SELECT count(distinct sw.id) cnt FROM student_works sw
              JOIN student_works_scores sws on sws.student_work_id = sw.id WHERE
              reviewer_role IN(1,2) AND sw.id IN (SELECT id FROM student_works WHERE homework_common_id = #{self.id}
              AND user_id IN (SELECT user_id FROM course_members WHERE role = 4 AND course_group_id
                    IN (#{course_group_ids.join(",")})
                   )
                )
          }
        else
          %Q{
            SELECT COUNT(distinct sw.id) cnt FROM student_works sw
              JOIN student_works_scores sws ON sw.id = sws.student_work_id
            WHERE reviewer_role IN(1,2) AND sw.homework_common_id = #{self.id}
          }
        end
    StudentWorksScore.find_by_sql(sql).first.try(:cnt).to_i
  end

  # 任务未评数
  def uncomment_count(user_id)
    user_ids = course.teacher_group_user_ids user_id
    self.student_works.where(user_id: user_ids).count - self.comment_count(user_id)
  end

  # 作品未提交数
  def unfinished_count member
    self.teacher_works(member).unfinished.count
  end

  # 任务按时提交数
  def finished_count member
    self.teacher_works(member).finished.count
  end

  def delay_finished_count member
    self.teacher_works(member).delay_finished.count
  end

  # 分组作业的最大分组id
  def max_group_id
    self.student_works.has_committed.maximum(:group_id).to_i + 1
  end

  # 作业的分班设置时间
  def homework_group_setting user_id
    if unified_setting
      homework_setting = self
    else
      member = course.course_member(user_id)
      group_setting = self.homework_group_settings.find_by_course_group_id(member.try(:course_group_id))
      homework_setting = group_setting.present? ? group_setting : self
    end
    homework_setting
  end

  def min_group_publish_time
    #HomeworkGroupSetting.where("homework_common_id = #{self.id} and publish_time is not null").pluck(:publish_time).min
    # 可以使用includes
    self.homework_group_settings.where("publish_time is not null").pluck(:publish_time).min
  end

  def max_group_end_time
    #HomeworkGroupSetting.where("homework_common_id = #{self.id} and end_time is not null").pluck(:end_time).max
    # 可以使用includes
    self.homework_group_settings.where("end_time is not null").pluck(:end_time).max

  end

  def challenge_score challenge_id
    homework_challenge_settings.find_by(challenge_id: challenge_id)&.score.to_f
  end

  def update_homework_work_score
    if unified_setting
      works = student_works
      user_ids = course.students.pluck(:user_id)
    else
      user_ids = course.students.where(course_group_id: published_settings.pluck(:course_group_id)).pluck(:user_id)
      works = student_works.where(user_id: user_ids)
    end

    works = works.includes(:challenge_work_scores)

    challenge_settings = homework_challenge_settings
    challenge_setting_ids = challenge_settings.pluck(:challenge_id)
    myshixuns = Myshixun.where(shixun_id: homework_commons_shixun&.shixun_id, user_id: user_ids).includes(:games)
    myshixuns.find_each(batch_size: 100) do |myshixun|
      work = works.select{|work| work.user_id == myshixun.user_id}.first
      if work && myshixun
        games = myshixun.games.select{|game| challenge_setting_ids.include?(game.challenge_id)}
        HomeworksService.new.update_myshixun_work_score work, myshixun, games, self, challenge_settings
      end
    end
    HomeworksService.new.update_student_eff_score(self) if (allow_late && late_time < Time.now) ||
      (!allow_late && end_time < Time.now)
    update_attribute('calculation_time', Time.now)
  end
end
