class Users::ShixunService
  attr_reader :user, :params, :laboratory

  def initialize(user, params, laboratory)
    @user   = user
    @params = params
    @laboratory = laboratory
  end

  def call

    shixuns = category_scope_shixuns

    shixuns = user_policy_filter(shixuns)

    custom_order(shixuns, params[:sort_by], params[:sort_direction])
  end

  private

  def category_scope_shixuns
    case params[:category]
    when 'study' then
      user.study_shixuns.where(shixuns: {id: laboratory.shixuns})
    when 'manage' then
      laboratory.shixuns.where(id: user.shixuns)
    when 'collect' then
      laboratory.shixuns.where(id: user.shixun_collections.pluck(:container_id))
    else
      ids = user.study_shixuns.pluck(:id) + user.shixuns.pluck(:id) + user.shixun_collections.pluck(:container_id)
      laboratory.shixuns.where(id: ids)
    end
  end

  def status_filter(relations)
    case params[:category]
    when 'study' then
      study_shixun_status_filter(relations)
    when 'collect' then
      collect_shixun_status_filter(relations)
    when 'manage' then
      manage_shixun_status_filter(relations)
    else
      relations
    end
  end

  def user_policy_filter(relations)
    # 只有自己或者管理员才有过滤筛选及查看全部状态下实训功能
    if self_or_admin?
      relations = relations.where.not(status: -1).where(hidden: false)
      status_filter(relations)
    else
      relations.where(status: [2, 3], hidden: false)
    end
  end

  def self_or_admin?
    User.current.id == user.id || User.current.admin?
  end

  def study_shixun_status_filter(relations)
    status = case params[:status]
             when 'passed'     then 1
             when 'processing' then 0
             end
    relations = relations.where(myshixuns: { status: status }) if status
    relations
  end

  def collect_shixun_status_filter relations
    passed_shixun_ids = user.myshixuns.where(shixun_id: relations, status: 1).pluck(:shixun_id)
    if params[:status] == 'passed'
      relations = relations.where(id: passed_shixun_ids)
    elsif params[:status] == 'processing'
      relations = relations.where.not(id: passed_shixun_ids)
    end
    relations
  end

  def manage_shixun_status_filter(relations)
    if params[:status] == "publiced"
      relations = relations.where(public: 2)
    elsif params[:status] == "applying"
      relations = relations.where(public: 1)
    else
      status = case params[:status]
               when 'editing'   then 0
               when 'published' then 2
               when 'closed'    then 3
               end
      relations = relations.where(status: status) if status
    end
    relations
  end

  def custom_order(relations, sort_by, sort_direction)
    sort_by        = sort_by&.downcase
    sort_direction = sort_direction&.downcase

    if sort_by.blank? || !%w(updated_at created_at).include?(sort_by)
      sort_by = 'updated_at'
    end

    if sort_direction.blank? || !%w(desc asc).include?(sort_direction)
      sort_direction = 'desc'
    end

    if sort_by == 'language'
      return relations.left_joins(:tag_repertoires).order("tag_repertoires.name #{sort_direction}")
    end

    case params[:category]
    when 'study' then
      relations.order("myshixuns.#{sort_by} #{sort_direction}")
    when 'manage', 'collect' then
      relations.order("shixuns.#{sort_by} #{sort_direction}")
    else
      relations.order("shixuns.#{sort_by} #{sort_direction}")
    end
  end
end
