findNextLevelsBySession = (sessions, levels, levelStatusMap, classroom, courseId) => {
  if (!levelStatusMap) {
    levelStatusMap = getLevelStatusMap(sessions)
  }
  const nextLevelOriginals = new Set() // next level = started levels + incomplete unlocked levels + not-started first levels

  let levelDataMap = {}
  if (_.isArray(levels)) {
    levelDataMap = getLevelDataMap(levels)
  } else {
    levelDataMap = levels || {}
  }
  for (const [levelOriginal, level] of Object.entries(levelDataMap)) {
    if (classroom && classroom.isStudentOnSkippedLevel(me.get('_id'), courseId, levelOriginal)) {
      continue
    }

    const levelStatus = levelStatusMap[levelOriginal]
    const isLevelStarted = typeof levelStatus === 'string' && levelStatus === 'started'
    const isLevelCompleted = typeof levelStatus === 'string' && levelStatus === 'complete'
    const hasCompletedStages = typeof levelStatus === 'number' && levelStatus > 0

    if (isLevelStarted) {
      nextLevelOriginals.add(levelOriginal)
    } else if (isLevelCompleted || hasCompletedStages) {
      let unlockedLevel = {}
      if (level.isPlayedInStages) {
        const stageCompleted = levelStatusMap[levelOriginal]
        unlockedLevel = getNextLevelForLevel(level, stageCompleted) || {}
      } else {
        unlockedLevel = getNextLevelForLevel(level) || {}
      }

      if (unlockedLevel.original && classroom && classroom.isStudentOnSkippedLevel(me.get('_id'), courseId, unlockedLevel.original)) {
        unlockedLevel = {}
      }

      const unlockedLevelStatus = levelStatusMap[unlockedLevel.original]
      const unlockedLevelCompleted = (typeof unlockedLevelStatus === 'string' && unlockedLevelStatus === 'complete') ||
        (typeof unlockedLevelStatus === 'number' && unlockedLevelStatus >= unlockedLevel.nextLevelStage)
      if (!unlockedLevelCompleted && unlockedLevel.original) { // add incomplete unlocks
        nextLevelOriginals.add(unlockedLevel.original)
      }
    } else if (level.first) {
      nextLevelOriginals.add(levelOriginal)
    }
  }
  return [...nextLevelOriginals][0] // assuming there can only be one next level for the given levels and their sessions
}
Calculates all the next levels for a list of levels in a classroom/campaign based on the level sessions.
@param {Object[]} sessions - The list of level session objects.
@param {Object[]|Object} levels - The list of level objects, or an object with keys as level original id and value as level data.
@param {Object} levelStatusMap - Optional. Object with key as the level original id, and value as complete/started.
@param {Object} classroom - classroom
@param {string} classroom - course id
@returns {string} - Next level's original id.