class Competitions::CompetitionTeamsController < Competitions::BaseController
  before_action :tech_mode, only: [:shixun_detail, :course_detail]

  def shixun_detail
    start_time = current_competition.competition_mode_setting&.start_time || current_competition.start_time
    end_time = current_competition.competition_mode_setting&.end_time || current_competition.end_time

    team_user_ids = @team.team_members.pluck(:user_id)
    shixuns = Shixun.where(user_id: team_user_ids, status: 2)
                .where('shixuns.created_at > ? && shixuns.created_at <= ?', start_time, end_time)
    shixuns = shixuns.joins('left join shixuns forked_shixuns on forked_shixuns.fork_from = shixuns.id and forked_shixuns.status = 2')
    shixuns = shixuns.select('shixuns.id, shixuns.identifier, shixuns.user_id, shixuns.myshixuns_count, shixuns.name, shixuns.fork_from, sum(forked_shixuns.myshixuns_count) forked_myshixun_count')
    @shixuns = shixuns.group('shixuns.id').order('shixuns.myshixuns_count desc').includes(:user)

    shixun_ids = @shixuns.map(&:id)
    @myshixun_count_map = get_valid_myshixun_count(shixun_ids)
    @original_myshixun_count_map = @myshixun_count_map.clone
    # forked shixun valid myshixun count
    forked_shixun_map = Shixun.where(status: 2, fork_from: shixun_ids).select('id, fork_from')
    forked_shixun_map = forked_shixun_map.each_with_object({}) { |sx, obj| obj[sx.id] = sx.fork_from }
    @forked_myshixun_count_map = get_valid_myshixun_count(forked_shixun_map.keys)
    @forked_myshixun_count_map.each { |k, v| @myshixun_count_map[forked_shixun_map[k]] += v }

    @course_count_map = get_valid_course_count(shixun_ids)
    @forked_map = get_valid_course_count(forked_shixun_map.keys)
    @forked_course_count_map = {}
    @forked_map.each do |forked_id, course_count|
      @forked_course_count_map[forked_shixun_map[forked_id]] ||= 0
      @forked_course_count_map[forked_shixun_map[forked_id]] += course_count
    end
    @forked_shixun_map = forked_shixun_map
  end

  def course_detail
    start_time = current_competition.competition_mode_setting&.start_time || current_competition.start_time
    end_time = current_competition.competition_mode_setting&.end_time || current_competition.end_time
    @team_user_ids = @team.team_members.pluck(:user_id)

    student_count_subquery = CourseMember.where('course_id = courses.id AND role = 4').select('count(*)').to_sql
    subquery = StudentWork.where('homework_common_id = hcs.id')
                 .select('sum(compelete_status >0 ) as finish, count(*) as total')
                 .having('total != 0 and finish >= (total / 2)').to_sql
    course_ids = Course.where('courses.created_at > ?', start_time)
                   .where('courses.created_at <= ?', end_time)
                   .where("(#{student_count_subquery}) >= 3")
                   .where("exists(select 1 from homework_commons hcs where hcs.course_id = courses.id and hcs.publish_time is not null and hcs.publish_time < NOW() and hcs.homework_type = 4 and exists(#{subquery}))")
                   .joins('join course_members on course_members.course_id = courses.id and course_members.role in (1,2,3)')
                   .where(course_members: { user_id: @team_user_ids }).pluck(:id)
    courses = Course.where(id: course_ids).joins(:practice_homeworks).where('homework_commons.publish_time < ?', end_time)
    @courses = courses.select('courses.id, courses.name, courses.members_count, count(*) shixun_homework_count')
                 .group('courses.id').order('shixun_homework_count desc').having('shixun_homework_count > 0')

    course_ids = @courses.map(&:id)
    @course_myshixun_map = Myshixun.joins(student_works: :homework_common)
                             .where(homework_commons: { course_id: course_ids })
                             .where('exists(select 1 from games where games.myshixun_id = myshixuns.id and games.status = 2)')
                             .group('homework_commons.course_id').count
    @course_shixun_count_map = get_valid_shixun_count(course_ids)
  end

  def index
    @competition = current_competition
    @personal = current_competition.personal?
    if admin_or_business?
      all_competition_teams
      user_competition_teams
    else
      user_competition_teams
    end
  end

  def create
    if current_competition.personal? # 个人赛报名
      Competitions::CreatePersonalTeamService.call(current_competition, current_user)
    else
      team = current_competition.competition_teams.new(user: current_user)
      Competitions::SaveTeamService.call(team, save_params)
    end
    render_ok

  rescue ApplicationService::Error => ex
    render_error(ex.message)
  end

  def update
    team = current_competition.competition_teams.where(user: current_user).find(params[:id])
    Competitions::SaveTeamService.call(team, save_params)
    render_ok
  end

  def join
    Competitions::JoinTeamService.call(current_competition, current_user, params)
    render_ok
  rescue Competitions::JoinTeamService::Error => ex
    render_error(ex.message)
  end

  def leave
    team = current_competition.competition_teams.find(params[:id])
    member = team.team_members.find_by(user_id: current_user.id)
    return render_error('您不是该战队的成员') if member.blank?

    if member.user_id == team.user_id
      team.destroy! # 队长退出，战队解散
    else
      member.destroy!
    end

    render_ok
  end

  private

  def all_competition_teams
    teams = current_competition.competition_teams

    keyword = params[:keyword].to_s.strip
    if keyword.present?
      teams = teams.joins(user: { user_extension: :school })
                .where('competition_teams.name LIKE :keyword OR schools.name LIKE :keyword', keyword: "%#{keyword}%")
    end

    @all_count = teams.count
    @all_teams = paginate(teams.includes(:user, users: { user_extension: :school }))
    @all_member_count = teams.joins(:team_members).count
  end

  def user_competition_teams
    teams  = current_competition.competition_teams
    teams  = teams.joins(:team_members).where(team_members: { user_id: current_user.id })
    @teams = teams.includes(:user, users: { user_extension: :school }).to_a
    @count = @teams.size
  end

  def save_params
    params.permit(:name, teacher_ids: [], member_ids: [])
  end

  def tech_mode
    # render_not_found if current_competition.mode != 3
    @team = current_competition.competition_teams.find_by!(id: params[:id])
  end

  def get_valid_myshixun_count(ids)
    Myshixun.where(shixun_id: ids)
      .where('exists(select 1 from games where games.myshixun_id = myshixuns.id and games.status = 2)')
      .group('shixun_id').count
  end

  def get_valid_course_count(ids)
    percentage_sql = StudentWork.where('homework_common_id = homework_commons.id and homework_commons.publish_time is not null and homework_commons.publish_time < NOW()')
                       .select('sum(compelete_status >0 ) as finish, count(*) as total')
                       .having('total != 0 and finish >= (total / 2)').to_sql

    Course.joins(practice_homeworks: :homework_commons_shixun)
      .where('shixun_id in (?)', ids)
      .where("exists (#{percentage_sql})")
      .group('shixun_id').count
  end

  def get_valid_shixun_count(ids)
    percentage_sql = StudentWork.where('homework_common_id = homework_commons.id and homework_commons.publish_time is not null and homework_commons.publish_time < NOW()')
                       .select('sum(compelete_status >0 ) as finish, count(*) as total')
                       .having('total != 0 and finish >= (total / 2)').to_sql
    Shixun.joins(homework_commons_shixuns: :homework_common)
      .where(homework_commons: { homework_type: 4 })
      .where('course_id in (?)', ids)
      .where("exists (#{percentage_sql})")
      .group('course_id').count
  end
end
