class ExaminationBanksController < ApplicationController
  include PaginateHelper
  include CoursesHelper

  before_action :require_login
  before_action :certi_identity_auth, only: [:edit, :revoke_item]
  before_action :find_exam, except: [:index, :create, :create_random_exam, :cancel_items]
  before_action :edit_auth, only: [:update, :set_public, :destroy]
  before_action :identity_auth, only: [:index]
  before_action :check_account, only: [:index]
  before_action :check_contents_and_score_setting, only: [:create_random_exam, :update_random_exam]

  # 创建随机组卷
  def create_random_exam
    ActiveRecord::Base.transaction do
      examination_bank = current_user.examination_banks.build(
          random_exam_params.slice(:name, :difficulty, :time, :source, :sub_discipline_id).merge(is_random: true)
      )
      if examination_bank.save!
        # 1.保存随机规则设置
        #  "contents":  [
        #         {
        #             "question_type": "MULTIPLE",
        #             "difficulty": 1,
        #             "sub_discipline_id": 1,
        #             "sub_discipline_name": null,
        #             "size": 1
        #         },
        #         {
        #             "question_type": "SINGLE",
        #             "difficulty": 1,
        #             "sub_discipline_id": 81,
        #             "sub_discipline_name": null,
        #             "size": 1
        #         }
        # ]
        random_exam_params[:contents].each do |random_setting|
          examination_bank.examination_bank_random_settings.create!(
              item_type: random_setting[:item_type],
              sub_discipline_id: random_setting[:sub_discipline_id],
              difficulty: random_setting[:difficulty],
              quanlity: random_setting[:items_count]
          )
        end
        # 2.保存赋分设置
        # [
        #  {
        #   item_type: "SINGLE",
        #   score: 1
        #   }
        # ]
        random_exam_params[:score_settings].each do |score_setting|
          examination_bank.examination_bank_score_settings.create!(
              item_type: score_setting[:item_type], score: score_setting[:score]
          )
        end
      end
      render_ok({examination_bank_id: examination_bank.id})
    end
  rescue Exception => ex
    render_error(ex.message)
  end

  # 编辑随机组卷
  def edit_random_exam
    @examination_bank_score_settings = @exam.examination_bank_score_settings
    @examination_bank_random_settings = @exam.examination_bank_random_settings.includes(:sub_discipline=>[:discipline])
    # 按照题型-课程-难度进行分组
    # @contents = []
    # item_types = @examination_bank_random_settings.pluck(:item_type).uniq
    # item_types.each do |item_type|
    #   hash = {item_type: item_type, items_by_item_type: []}
    #   items_by_item_type = @examination_bank_random_settings.where(item_type: item_type)
    #   # 该题型下各个课程类的题目集合
    #   sub_disciplines = items_by_item_type.joins(:sub_discipline=>[:discipline]).pluck(:sub_discipline_id, "sub_disciplines.name name", :discipline_id, "disciplines.name discipline_name").uniq
    #   sub_disciplines.each_with_index do |sub_discipline, index|
    #     hash[:items_by_item_type] << {
    #         sub_discipline_id: sub_discipline[0], sub_discipline_name: sub_discipline[1], discipline_id: sub_discipline[2], discipline_name: sub_discipline[3],
    #         items_by_item_type_and_sub_discipline: []
    #     }
    #     items_by_item_type_and_sub_discipline = items_by_item_type.where(sub_discipline_id: sub_discipline[0])
    #     difficulties = items_by_item_type_and_sub_discipline.pluck(:difficulty).uniq
    #     difficulties.each do |difficulty|
    #       items_by_item_type_and_sub_discipline_and_difficulty = items_by_item_type_and_sub_discipline.where(difficulty: difficulty).select(:id)
    #       hash[:items_by_item_type][index][:items_by_item_type_and_sub_discipline] << {difficulty: difficulty, items_count: items_by_item_type_and_sub_discipline_and_difficulty.size}
    #     end
    #   end
    #   @contents << hash
    # end

    # 赋分设置
    @score_settings = []
    @examination_bank_score_settings.each do |examination_bank_score_setting|
      @score_settings << {
          item_type: examination_bank_score_setting.item_type,
          score: examination_bank_score_setting.score
      }
    end
  end

  # 更新随机组卷
  def update_random_exam
    ActiveRecord::Base.transaction do
      # 更新时直接删除原有配置重新建立
      @exam.examination_bank_score_settings.destroy_all
      @exam.examination_bank_random_settings.destroy_all
      @exam.update!(random_exam_params.slice(:name, :difficulty, :time, :source).merge(is_random: true))
      if @exam.save!
        # 1.保存随机规则设置
        #  "contents":  [
        #         {
        #             "question_type": "MULTIPLE",
        #             "difficulty": 1,
        #             "sub_discipline_id": 1,
        #             "sub_discipline_name": null,
        #             "size": 1
        #         },
        #         {
        #             "question_type": "SINGLE",
        #             "difficulty": 1,
        #             "sub_discipline_id": 81,
        #             "sub_discipline_name": null,
        #             "size": 1
        #         }
        # ]
        random_exam_params[:contents].each do |random_setting|
          @exam.examination_bank_random_settings.create!(
              item_type: random_setting[:item_type],
              sub_discipline_id: random_setting[:sub_discipline_id],
              difficulty: random_setting[:difficulty],
              quanlity: random_setting[:items_count]
          )
        end
        # 2.保存赋分设置
        # [
        #  {
        #   item_type: "SINGLE",
        #   score: 1
        #   }
        # ]
        random_exam_params[:score_settings].each do |score_setting|
          @exam.examination_bank_score_settings.create!(
              item_type: score_setting[:item_type], score: score_setting[:score]
          )
        end
      end
      render_ok
    end
  rescue Exception => ex
    render_error(ex.message)
  end

  def index
    exams = ExaminationBankQuery.call(params)
    @exams_count = exams.size
    @exams = paginate exams.includes(:user, :examination_items)
    @current_user = current_user
    @role = current_user.admin_or_business? || current_user.is_teacher? || current_user.is_shixun_marker?
  end

  def show
    @items = @exam.examination_items
    # TODO： 由于Jbuilder层公用了item_bank，里面有根据用户的权限判断，因此，这边需要加上一个user_id
    @single_questions = @items.where(item_type: "SINGLE")
                            .joins(:examination_bank).select("examination_items.*, examination_banks.user_id")
    @multiple_questions = @items.where(item_type: "MULTIPLE")
                              .joins(:examination_bank).select("examination_items.*, examination_banks.user_id")
    @judgement_questions = @items.where(item_type: "JUDGMENT")
                               .joins(:examination_bank).select("examination_items.*, examination_banks.user_id")
    @completion_questions = @items.where(item_type: "COMPLETION")
                                .joins(:examination_bank).select("examination_items.*, examination_banks.user_id")
    @subjective_questions = @items.where(item_type: "SUBJECTIVE")
                                .joins(:examination_bank).select("examination_items.*, examination_banks.user_id")
    @program_questions = @items.where(item_type: "PROGRAM")
                             .joins(:examination_bank).select("examination_items.*, examination_banks.user_id")
  end

  def create
    ActiveRecord::Base.transaction do
      exam = ExaminationBank.new(user: current_user)
      # 保存试卷基础信息
      exam = ExaminationBanks::SaveExaminationBankService.call(exam, form_params)

      # 将试题篮中的试题发送到试卷，试卷的题目与试题独立
      current_user.item_baskets.includes(:item_bank).each do |basket|
        item = basket.item_bank
        if item.present?
          new_item = ExaminationItem.new
          new_item.new_item(item, exam, basket.score, basket.position)
        end
      end

      current_user.item_baskets.destroy_all
      render_ok({exam_id: exam.id})
    end
  rescue ApplicationService::Error => ex
    render_error(ex.message)
  end

  def edit; end

  def update
    ExaminationBanks::SaveExaminationBankService.call(@exam, form_params)
    render_ok
  rescue ApplicationService::Error => ex
    render_error(ex.message)
  end

  def destroy
    tip_exception(403, "无权限") unless current_user.admin? || @exam.user == current_user
    ActiveRecord::Base.transaction do
      ApplyAction.where(container_type: "ExaminationBank", container_id: @exam.id).destroy_all
      @exam.destroy!
      render_ok
    end
  end

  def set_public
    tip_exception(-1, "该试卷已公开") if @exam.public?
    tip_exception(-1, "请勿重复提交申请") if ApplyAction.where(container_id: @exam.id, container_type: "ExaminationBank", status: 0).exists?
    ApplyAction.create!(container_id: @exam.id, container_type: "ExaminationBank", user_id: current_user.id)
    # @exam.update_attributes!(public: 1)
    render_ok
  end

  def set_private
    tip_exception(-1, "该试卷已私有") unless @exam.public?
    ActiveRecord::Base.transaction do
      @exam.update_attributes!(public: 0)
      ApplyAction.where(container_id: @exam.id, container_type: 'ExaminationBank', status: 0).update_all(status: 3)
    end
    render_ok
  end

  def revoke_item
    item = @exam.examination_items.find_by!(item_bank_id: params[:item_id])
    ActiveRecord::Base.transaction do
      @exam.examination_items.where(item_type: item.item_type).where("position > #{item.position}").update_all("position = position -1")
      item.destroy!
    end
    render_ok
  end

  def cancel_items
    tip_exception(403, "无权限") unless current_user.admin_or_business? || current_user.item_baskets.where(item_bank_id: params[:item_ids]).size == params[:item_ids].size
    current_user.item_baskets.where(item_bank_id: params[:item_ids]).destroy_all
    render_ok
  end

  def send_to_course
    tip_exception(403, "无权限") unless @exam.public || @exam.user == current_user
    course = Course.find params[:course_id]
    exercise = Exercise.new(user_id: current_user.id, course_id: course.id)
    exercise = ExaminationBanks::SendToCourseService.call(@exam, exercise)
    render_ok({exercise_id: exercise.id, first_category_url: module_url(course.exercise_course_modules.first, course)})
  end

  private

  def form_params
    params.permit(:discipline_id, :sub_discipline_id, :difficulty, :name, :duration, tag_discipline_id: [])
  end

  def find_exam
    @exam = ExaminationBank.find_by!(id: params[:id])
  end

  def edit_auth
    tip_exception(403, "无权限") unless current_user.admin_or_business? || @exam.user == current_user
  end

  def random_exam_params
    result = params.permit(
        :name, :difficulty, :source, :time, :sub_discipline_id,
        contents: [
            :item_type,
            :sub_discipline_id,
            :difficulty,
            :items_count
        ],
        score_settings: [
            :item_type, :score
        ]
    )
    result
  end

  def check_contents_and_score_setting
    raise Educoder::TipException.new("随机规则设置不得为空或者题目数量不能为0") if random_exam_params[:contents].blank? || random_exam_params[:contents].all?{|content| content[:items_count].to_i == 0}
    raise Educoder::TipException.new("内容设置和赋分设置的题型数量不一致") if random_exam_params[:contents].collect{|content| content[:item_type]}.uniq.size != random_exam_params[:score_settings].collect{|setting| setting[:item_type]}.uniq.size
  end

end