class Competitions::SaveTeamService < ApplicationService
  attr_reader :competition, :team, :creator, :params

  TEAM_MEMBER_ATTRIBUTES = %i[competition_id competition_team_id user_id role is_teacher created_at updated_at]

  def initialize(team, params)
    @team        = team
    @competition = team.competition
    @creator     = team.user
    @params      = params
  end

  def call
    Competitions::SaveTeamForm.new(form_params).validate!

    new_record = team.new_record?
    is_teacher = team.user.is_teacher?
    ActiveRecord::Base.transaction do
      team.generate_invite_code if new_record
      team.team_type = 1 # 组队竞赛
      team.name = params[:name].to_s.strip
      team.save!

      # 创建者
      team.team_members.create!(user_id: creator.id, competition_id: competition.id, role: 1, is_teacher: is_teacher) if new_record

      update_teacher_team_members!
      update_member_team_members!
    end
  end

  private

  def update_teacher_team_members!
    teacher_ids = Array.wrap(params[:teacher_ids]).map(:to_i)
    old_teacher_ids = team.team_members.where(role: 3).pluck(:user_id)

    destroy_teacher_ids = old_teacher_ids - teacher_ids
    team.team_members.where(role: 3).where(user_id: destroy_teacher_ids).delete_all

    new_teacher_ids = teacher_ids - old_teacher_ids
    TeamMember.bulk_insert(*TEAM_MEMBER_ATTRIBUTES) do |worker|
      base_attr = { competition_id: competition.id, competition_team_id: team.id, role: 3, is_teacher: true }
      new_teacher_ids.each do |teacher_id|
        next if teacher_id == creator.id
        worker.add(base_attr.merge(user_id: teacher_id))
      end
    end
  end

  def update_member_team_members!
    member_ids = Array.wrap(params[:member_ids]).map(:to_i)
    old_member_ids = team.team_members.where(role: 2).pluck(:user_id)

    destroy_member_ids = old_member_ids - member_ids
    team.team_members.where(role: 2).where(user_id: destroy_member_ids).delete_all

    new_member_ids = member_ids - old_member_ids
    TeamMember.bulk_insert(*TEAM_MEMBER_ATTRIBUTES) do |worker|
      base_attr = { competition_id: competition.id, competition_team_id: team.id, role: 2, is_teacher: false }
      new_member_ids.each do |member_id|
        next if member_id == creator.id
        worker.add(base_attr.merge(user_id: member_id))
      end
    end
  end

  def form_params
    params.merge(competition: competition, team: team, creator: creator)
  end
end