class CanvasSync::JobBatches::ChainBuilder

def insert(new_jobs, *args, **kwargs, &blk)

def insert(new_jobs, *args, **kwargs, &blk)
  if new_jobs.is_a?(Class) || new_jobs.is_a?(String)
    job_kwargs = kwargs.except(*VALID_PLACEMENT_PARAMETERS)
    args << job_kwargs if job_kwargs.present?
    new_jobs = build_job_hash(new_jobs, *args, &blk)
    kwargs = kwargs.slice(*VALID_PLACEMENT_PARAMETERS)
  else
    invalid_params = kwargs.keys - VALID_PLACEMENT_PARAMETERS
    raise "Invalid placement parameters: #{invalid_params.map(&:to_s).join(', ')}" if invalid_params.present?
    raise "At most one placement parameter may be provided" if kwargs.values.compact.length > 1
    raise "Unexpected number of arguments" if args.length > 0
  end
  new_jobs = [new_jobs] unless new_jobs.is_a?(Array)
  if !kwargs.present?
    insert_at(-1, new_jobs)
  else
    placement = kwargs.keys[0]
    relative_to = kwargs.values[0]
    matching_jobs = find_matching_jobs(relative_to).to_a
    raise "Could not find a \"#{relative_to}\" job in the chain" if matching_jobs.count == 0
    raise "Found multiple \"#{relative_to}\" jobs in the chain" if matching_jobs.count > 1
    relative_job, parent_job, sub_index = matching_jobs[0]
    needed_parent_type = placement == :with ? ConcurrentBatchJob : SerialBatchJob
    chain = self.class.get_chain_parameter(parent_job)
    if parent_job[:job] != needed_parent_type
      old_job = chain[sub_index]
      parent_job = chain[sub_index] = {
        job: needed_parent_type,
        parameters: [],
      }
      sub_index = 0
      chain = self.class.get_chain_parameter(parent_job)
      chain << old_job
    end
    if placement == :with
      chain.insert(-1, *new_jobs)
    else
      sub_index += 1 if placement == :after
      chain.insert(sub_index, *new_jobs)
    end
  end
end