<?php
declare(strict_types=1);

function manager_continue_group_users(array $state, array $finishedSeason, string $user): array {
  $targetLevel = manager_continue_target_level($state, $finishedSeason, $user);
  $nextYear = manager_season_year($finishedSeason, $state) + 1;
  $gameKey = manager_continue_game_key($state, $finishedSeason);
  $group = [$user];
  foreach (array_keys($state['users'] ?? []) as $name) {
    $name = clean_name((string)$name);
    if ($name === '' || $name === $user) continue;
    if (!isset($state['users'][$name]) || !has_team($state['users'][$name])) continue;
    $season = manager_current_game_season_for_user($state, $gameKey, $name);
    if ($season === null) continue;
    if (($season['status'] ?? '') !== 'finished') continue;
    if (manager_season_year($season, $state) + 1 !== $nextYear) continue;
    if (manager_continue_target_level($state, $season, $name) !== $targetLevel) continue;
    $group[] = $name;
  }
  return array_values(array_unique($group));
}

function manager_continue_target_level(array $state, array $finishedSeason, string $user): int {
  $baseLevel = clamp_int((int)($finishedSeason['divisionLevel'] ?? 5), 1, 5);
  $outcome = (string)($finishedSeason['outcome'][$user] ?? '');
  if ($outcome === 'promoted') return max(1, $baseLevel - 1);
  if ($outcome === 'relegated') return min(5, $baseLevel + 1);
  return $baseLevel;
}

function manager_season_root_id(array $state, array $season): string {
  $id = (string)($season['id'] ?? '');
  $root = $id;
  $seen = [];
  while (true) {
    $from = (string)($season['continuedFrom'] ?? '');
    if ($from === '' || isset($seen[$from])) break;
    $seen[$from] = true;
    $root = $from;
    if (empty($state['managerSeasons'][$from]) || !is_array($state['managerSeasons'][$from])) break;
    $season = $state['managerSeasons'][$from];
  }
  return $root !== '' ? $root : $id;
}

function manager_continue_game_key(array $state, array $season): string {
  $gameId = trim((string)($season['managerGameId'] ?? $season['saveGameId'] ?? ''));
  if ($gameId !== '') return 'game:' . $gameId;
  return 'root:' . manager_season_root_id($state, $season);
}

function manager_current_game_season_for_user(array $state, string $gameKey, string $user): ?array {
  $user = clean_name($user);
  if ($user === '' || $gameKey === '') return null;
  $best = null;
  $bestScore = -1;
  $consider = function ($id) use ($state, $gameKey, $user, &$best, &$bestScore): void {
    if (!is_string($id) || $id === '' || empty($state['managerSeasons'][$id]) || !is_array($state['managerSeasons'][$id])) return;
    $season = $state['managerSeasons'][$id];
    if (($season['status'] ?? '') === 'aborted') return;
    if (!manager_season_visible_to_user($season, $user)) return;
    if (manager_continue_game_key($state, $season) !== $gameKey) return;
    $score = manager_current_season_score($state, $season);
    if ($score > $bestScore) {
      $bestScore = $score;
      $best = $season;
    }
  };
  $consider($state['managerCurrentByUser'][$user] ?? null);
  foreach (($state['managerSeasons'] ?? []) as $id => $season) {
    if (!is_array($season)) continue;
    $consider((string)$id);
  }
  return $best;
}

function manager_continue_waiting_users(array $state, array $finishedSeason, string $user): array {
  if (($finishedSeason['status'] ?? '') !== 'finished') return [];
  $year = manager_season_year($finishedSeason, $state);
  $gameKey = manager_continue_game_key($state, $finishedSeason);
  $seen = [];
  foreach (($state['managerCurrentByUser'] ?? []) as $name => $seasonId) {
    $name = clean_name((string)$name);
    $seasonId = (string)$seasonId;
    if ($name === '' || $seasonId === '' || empty($state['managerSeasons'][$seasonId])) continue;
    if (manager_continue_game_key($state, $state['managerSeasons'][$seasonId]) !== $gameKey) continue;
    $seen[$name] = true;
  }
  foreach (($finishedSeason['humanManagers'] ?? []) as $name) $seen[clean_name((string)$name)] = true;
  foreach (($state['managerSeasons'] ?? []) as $season) {
    if (!is_array($season)) continue;
    if (($season['status'] ?? '') === 'aborted') continue;
    if (manager_continue_game_key($state, $season) !== $gameKey) continue;
    if (manager_season_year($season, $state) > $year) continue;
    foreach (($season['humanManagers'] ?? []) as $name) $seen[clean_name((string)$name)] = true;
  }
  unset($seen[$user], $seen['']);
  $waiting = [];
  foreach (array_keys($seen) as $name) {
    if (!isset($state['users'][$name])) continue;
    $season = manager_current_game_season_for_user($state, $gameKey, $name);
    if ($season === null) continue;
    if (manager_season_year($season, $state) > $year) continue;
    if (($season['status'] ?? '') !== 'finished') $waiting[] = $name;
  }
  return array_values(array_unique($waiting));
}

function continued_manager_season_id(array $state, string $fromSeasonId, string $user, int $targetLevel): ?string {
  $candidates = [];
  foreach (($state['managerSeasons'] ?? []) as $id => $season) {
    if (!is_array($season)) continue;
    if (($season['status'] ?? '') === 'aborted') continue;
    if ((string)($season['continuedFrom'] ?? '') !== $fromSeasonId) continue;
    if (!manager_season_visible_to_user($season, $user)) continue;
    $level = clamp_int((int)($season['continuedGroupLevel'] ?? $season['divisionLevel'] ?? 5), 1, 5);
    $candidates[] = [
      'id' => (string)$id,
      'year' => manager_season_year($season, $state),
      'level' => $level,
      'targetLevel' => $targetLevel,
      'exact' => $level === $targetLevel ? 1 : 0,
      'score' => manager_current_season_score($state, $season),
    ];
  }
  if (!$candidates) return null;
  usort($candidates, function ($a, $b) {
    return ((int)$b['year'] <=> (int)$a['year'])
      ?: ((int)$b['exact'] <=> (int)$a['exact'])
      ?: (abs((int)$a['level'] - (int)$a['targetLevel']) <=> abs((int)$b['level'] - (int)$b['targetLevel']))
      ?: ((int)$b['score'] <=> (int)$a['score']);
  });
  return (string)$candidates[0]['id'];
}
