class Admins::CompetitionStagesController < Admins::BaseController

  def create
    Admins::CompetitionStageCreateService.call(current_competition, update_form_params)
    render_ok
  end

  def update
    Admins::CompetitionStageUpdateService.call(current_competition, update_form_params, current_stage)
    render_ok
  end

  def destroy
    current_stage.destroy!
  end

  def calculate_stage_score
    if current_stage.max_end_time && current_stage.max_end_time < Time.now

      ActiveRecord::Base.transaction do
        begin

          current_stage.competition_scores.destroy_all

          if current_stage.competition_stage_sections.size > 0
            # 是否只有老师参赛
            only_teacher = current_competition.member_staff.blank?
            stage_sections = current_stage.competition_stage_sections.includes(:competition_entries)
            shixuns = Shixun.where(identifier: current_stage.competition_entries.pluck(:shixun_identifier).reject(&:blank?))
            challenges = Challenge.where(shixun_id: shixuns.pluck(:id))

            # 计算每个战队的成绩
            current_competition.competition_teams.each do |team|
              totoal_score = 0
              total_time = 0
              # 只有老师参赛则计算所有参赛队员的成绩，否则只计算学生的成绩
              user_ids = only_teacher ? team.team_members.pluck(:user_id) : team.team_members.where(is_teacher: 0).pluck(:user_id)

              stage_sections.each do |section|
                shixun_identifiers = section.competition_entries.pluck(:shixun_identifier).reject(&:blank?)
                shixun_ids = shixuns.select{ |shixun| shixun_identifiers.include?(shixun.identifier) }.map(&:id)
                section_challenges = challenges.select{ |challenge| shixun_ids.include?(challenge.shixun_id) }
                if section.score_source == 0
                  result1 = chart_stage_score user_ids, section.start_time, section.end_time, section_challenges, section_challenges.length/shixun_ids.length
                else
                  result1 = chart_stage_rate user_ids, section.start_time, section.end_time, section_challenges, section_challenges.length/shixun_ids.length
                end
                score = result1[0]
                time = result1[1]

                totoal_score += score
                total_time += time
              end

              # 比赛已截止且未有分数纪录 则创建
              unless team.competition_scores.exists?(competition_id: current_competition.id, competition_stage_id: current_stage.id)
                CompetitionScore.create!(user_id: team.user_id, competition_team_id: team.id, competition_id: current_competition.id,
                                         competition_stage_id: current_stage.id, score: totoal_score, cost_time: total_time)
              end
            end

            # 如果计算的是最后一个阶段，则同时计算总成绩（只有一个阶段则不需计算）
            if current_stage.max_end_time == current_competition.max_stage_end_time && current_competition.competition_stages.size > 1
              calculate_total_score current_competition
            end
          end

        rescue Exception => e
          uid_logger_error(e.message)
          @message = "#{e.message}"
        end
      end

      @message = "计算成功"
    else
      @message = "#{current_stage.name}还未结束"
    end
  end

  def send_message
    if current_stage.max_end_time && current_stage.max_end_time > Time.now
      User.where(id: TeamMember.where(competition_team_id: current_competition.competition_teams.pluck(:id)).pluck(:user_id).uniq).each do |user|
        name = current_competition.name + "#{current_competition.sub_title}（#{stage.name}）"
        begin
          if user.phone.present?
            Educoder::Sms.send(mobile: user.phone.to_s, code: '1', send_type:'competition_start', user_name:user.show_name,
                               name:name, result:section.start_time.strftime('%Y-%m-%d %H:%M:%S'))
          end
        rescue => e
          logger_error(e)
          render_error("发送验证码出错")
        end
      end
    else
      render_error("#{current_stage.name}已结束")
    end
  end

  private

  def current_competition
    @_current_competition ||= Competition.find(params[:competition_id])
  end

  def current_stage
    @_current_stage ||= CompetitionStage.find_by!(competition_id: params[:competition_id], id: params[:id])
  end

  def update_form_params
    params.permit(:stage_name, :score_rate, stage: [:start_time, :end_time, :entry, :score_source, identifiers: []])
  end


  # challenges 每阶段的所有关卡
  # s_time 阶段开始时间  e_time 阶段结束时间
  # rate 关卡经验值与分数的比值
  # challenge_count 每个实训的关卡数
  # 对三个实训的所有关卡循环： 找到在比赛时间内通关的最低耗时
  def chart_stage_score user_ids, s_time, e_time, challenges, challenge_count
    total_score = 0
    total_time = 0
    length = challenge_count   #每个实训的关卡数
    for i in 1..length
      score = 0
      time = 0
      challenges.select{|challenge| challenge.position == i}.each do |challenge|
        Game.where(:challenge_id => challenge.id, :user_id => user_ids, :status => 2).select{|game| game.open_time >= s_time && game.end_time <= e_time }.each do |game|
          game_score = challenge.score
          cost_time = (game.end_time.to_i - s_time.to_i) > 0 ? (game.end_time.to_i -  s_time.to_i) : 0
          if score < game_score
            score = game_score
            time = cost_time
          elsif score == game_score
            time = cost_time > time ? time : cost_time
          end
        end
      end
      total_score += score
      total_time += time
    end
    return [total_score, total_time]
  end

  def chart_stage_rate user_ids, s_time, e_time, challenges, challenge_count
    # 第三阶段的得分和耗时
    total_score = 0
    total_time = 0
    length = challenge_count   #每个实训的关卡数
    for i in 1..length
      score3 = 0
      time3 = 0

      challenges.select{|challenge| challenge.position == i}.each do |challenge|
        Game.where(:challenge_id => challenge.id, :user_id => user_ids, :status => 2).select{|game| game.open_time >= s_time && game.end_time <= e_time }.each do |game|
          outputs = game.outputs.select{|output| !output.text_scor.nil? && output.created_at <= e_time }
          if outputs.present?
            outputs = outputs.sort { |a, b| b[:text_scor].to_f <=> a[:text_scor].to_f }
            myshixun_score = outputs.first.text_scor.to_f
            myshixun_time = outputs.first.created_at.to_i - s_time.to_i
            if score3 < myshixun_score
              score3 = myshixun_score
              time3 = myshixun_time
            elsif score3 == myshixun_score
              time3 = myshixun_time > time3 ? time3 : myshixun_time
            end
          end
        end
      end

      total_score += score3
      total_time += time3
    end
    return [total_score, total_time]
  end

  def calculate_total_score competition
    competition.competition_scores.where(competition_stage_id: 0).destroy_all
    competition.competition_teams.each do |team|
      total_score = 0
      total_time = 0

      competition.competition_stages.where("score_rate > 0").each do |stage|
        stage_score = team.competition_scores.where(competition_stage_id: stage.id).take
        total_score += stage_score.try(:score).to_f * stage.score_rate
        total_time += stage_score.try(:cost_time).to_i
      end

      unless team.competition_scores.exists?(competition_id: competition.id, competition_stage_id: 0)
        CompetitionScore.create!(user_id: team.user_id, competition_team_id: team.id, competition_id: competition.id,
                                 competition_stage_id: 0, score: total_score, cost_time: total_time)
      end
    end
  end
end