<?php
declare(strict_types=1);

session_start();

if (empty($_SESSION['admin_parties_csrf'])) {
    $_SESSION['admin_parties_csrf'] = bin2hex(random_bytes(16));
}

if (isset($_GET['logout'])) {
    session_destroy();
    header('Location: ./');
    exit;
}

$configFile = dirname(__DIR__) . '/privatedata/admin-parties-config.php';
if (!file_exists($configFile)) {
    exit('Configuration admin manquante.');
}
require $configFile;

if (isset($_POST['password'])) {
    if (password_verify((string)$_POST['password'], $ADMIN_PARTIES_PASSWORD_HASH ?? '')) {
        $_SESSION['admin_parties_ok'] = true;
        header('Location: ./');
        exit;
    }
}

if (empty($_SESSION['admin_parties_ok'])) {
    ?>
    <!doctype html>
    <html lang="fr">
    <head>
        <meta charset="utf-8">
        <title>Admin parties Chrono Party</title>
    </head>
    <body style="background:#f6f4ff;font-family:Arial,sans-serif">
        <form method="post" style="max-width:400px;margin:80px auto;background:white;padding:25px;border-radius:18px;box-shadow:0 8px 25px rgba(0,0,0,.08)">
            <h2>Admin parties Chrono Party</h2>
            <input type="password" name="password" placeholder="Mot de passe" style="width:100%;padding:12px;box-sizing:border-box">
            <button style="margin-top:12px;padding:12px;width:100%;background:#7c5cff;color:white;border:0;border-radius:10px;font-weight:bold">Connexion</button>
        </form>
    </body>
    </html>
    <?php
    exit;
}

function e($value): string {
    return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
}

function formatDuration($seconds): string {
    $seconds = max(0, (int)$seconds);
    $min = floor($seconds / 60);
    $sec = $seconds % 60;
    return $min . ' min ' . str_pad((string)$sec, 2, '0', STR_PAD_LEFT) . ' s';
}

function sourceLabel(string $source): string {
    return match ($source) {
        'demo', 'demo2026' => 'Démo',
        'premium' => 'Premium',
        'gift' => 'Cadeau',
        'asso' => 'Association',
        'test' => 'Test',
        default => 'Inconnu',
    };
}

function difficultyName(string $difficulty): string {
    $difficulty = mb_strtolower(trim($difficulty));

    return match ($difficulty) {
        'facile', 'easy' => 'Facile',
        'moyen', 'medium' => 'Moyen',
        'difficile', 'hard' => 'Difficile',
        default => $difficulty !== '' ? ucfirst($difficulty) : '',
    };
}

function difficultiesLabel(array $party): string {
    $difficulties = $party['difficulties'] ?? [];

    if (!is_array($difficulties) || empty($difficulties)) {
        return 'Non enregistrée';
    }

    $labels = [];

    foreach ($difficulties as $difficulty) {
        $label = difficultyName((string)$difficulty);
        if ($label !== '') {
            $labels[] = $label;
        }
    }

    $labels = array_values(array_unique($labels));

    return empty($labels) ? 'Non enregistrée' : implode(' + ', $labels);
}

function gameModeLabel(array $party): string {
    return (($party['game_mode'] ?? 'classic') === 'coop') ? '👹 Coop Boss' : '🏆 Classique';
}

function coopBossLabel(array $party): string {
    if (($party['game_mode'] ?? 'classic') !== 'coop' || !is_array($party['coop'] ?? null)) {
        return '—';
    }

    $coop = $party['coop'];
    $icon = trim((string)($coop['icon'] ?? '👹'));
    $label = trim((string)($coop['label'] ?? 'Boss'));
    $used = (int)($coop['turns_used'] ?? 0);
    $max = (int)($coop['max_turns'] ?? 0);
    $won = !empty($coop['won']);
    $rankIcon = trim((string)($coop['rank_icon'] ?? ''));
    $rankLabel = trim((string)($coop['rank_label'] ?? ''));

    $result = $won ? 'Victoire' : 'Défaite';
    $rank = $rankLabel !== '' ? ' — ' . trim($rankIcon . ' ' . $rankLabel) : '';

    return trim($icon . ' ' . $label) . ' — ' . $result . ' — ' . $used . '/' . $max . ' tours' . $rank;
}

function readJsonFile(string $file, $default) {
    if (!file_exists($file)) {
        return $default;
    }

    $json = json_decode((string)file_get_contents($file), true);
    return is_array($json) ? $json : $default;
}

function writeJsonFile(string $file, $data): void {
    file_put_contents(
        $file,
        json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE),
        LOCK_EX
    );
}

function isPartyPublishedForStats(array $party): bool {
    $status = (string)($party['status'] ?? 'validated');

    if ($status !== 'validated') {
        return false;
    }

    return true;
}

function rebuildPlayersStats(array $allParties, string $playersFile): void {
    $playersStats = [];

    foreach ($allParties as $party) {
        if (!is_array($party) || !isPartyPublishedForStats($party)) {
            continue;
        }

        $winnerName = (string)($party['winner'] ?? '');

        foreach (($party['teams'] ?? []) as $team) {
            if (!is_array($team)) {
                continue;
            }

            $teamName = (string)($team['name'] ?? '');
            $teamScore = max(0, (int)($team['total'] ?? 0));
            $isWinner = ($winnerName !== '' && $teamName === $winnerName);

            foreach (($team['players'] ?? []) as $player) {
                if (!is_array($player)) {
                    continue;
                }

                $playerId = getPlayerId($player);
                $playerName = getPlayerName($player);

                if ($playerId === '' || $playerName === '') {
                    continue;
                }

                if (!isset($playersStats[$playerId])) {
                    $playersStats[$playerId] = [
                        'id' => $playerId,
                        'name' => $playerName,
                        'games_count' => 0,
                        'wins' => 0,
                        'total_score' => 0,
                        'last_played_at' => null,
                        'coop_boss_wins' => [
                            'easy' => 0,
                            'standard' => 0,
                            'hard' => 0,
                            'legend' => 0
                        ]
                    ];
                }

                $playersStats[$playerId]['name'] = $playerName;
                $playersStats[$playerId]['games_count']++;
                $playersStats[$playerId]['total_score'] += $teamScore;
                $playersStats[$playerId]['last_played_at'] = (string)($party['created_at'] ?? '');

                if ($isWinner) {
                    $playersStats[$playerId]['wins']++;
                }

                if (($party['game_mode'] ?? 'classic') === 'coop' && is_array($party['coop'] ?? null) && !empty($party['coop']['won'])) {
                    $bossLevel = (string)($party['coop']['level'] ?? '');

                    if (in_array($bossLevel, ['easy', 'standard', 'hard', 'legend'], true)) {
                        $playersStats[$playerId]['coop_boss_wins'][$bossLevel] =
                            max(0, (int)($playersStats[$playerId]['coop_boss_wins'][$bossLevel] ?? 0)) + 1;
                    }
                }
            }
        }
    }

    writeJsonFile($playersFile, $playersStats);
}

function antiCheatLabel(array $party): array {
    $status = (string)($party['status'] ?? 'validated');
    $suspicious = !empty($party['suspicious']) || (($party['anti_cheat']['status'] ?? '') === 'suspect');

    if ($status === 'excluded') {
        return ['🚫 Exclue', 'statusExcluded'];
    }

    if ($status === 'validated' && $suspicious) {
        return ['✅ Publiée forcée', 'statusForced'];
    }

    if ($status === 'suspect' || $suspicious) {
        return ['⚠️ Suspecte', 'statusSuspect'];
    }

    return ['✅ Valide', 'statusValidated'];
}

function antiCheatReasonsLabel(array $party): string {
    $reasons = $party['anti_cheat']['reasons'] ?? [];

    if (!is_array($reasons) || empty($reasons)) {
        return '—';
    }

    $clean = [];
    foreach ($reasons as $reason) {
        $reason = trim((string)$reason);
        if ($reason !== '') {
            $clean[] = $reason;
        }
    }

    return empty($clean) ? '—' : implode(' | ', $clean);
}

function getPlayerName($player): string {
    if (is_array($player)) {
        return trim((string)($player['name'] ?? ''));
    }
    return trim((string)$player);
}

function getPlayerId($player): string {
    if (is_array($player)) {
        return trim((string)($player['id'] ?? ''));
    }
    return '';
}

function partyHasPlayer(array $party, string $search): bool {
    if ($search === '') {
        return true;
    }

    $search = mb_strtolower($search);

    foreach (($party['teams'] ?? []) as $team) {
        foreach (($team['players'] ?? []) as $player) {
            $name = mb_strtolower(getPlayerName($player));
            if ($name !== '' && str_contains($name, $search)) {
                return true;
            }
        }

        foreach (($team['turnStats'] ?? []) as $turn) {
            $name = mb_strtolower((string)($turn['playerName'] ?? ''));
            if ($name !== '' && str_contains($name, $search)) {
                return true;
            }
        }
    }

    return false;
}

function queryUrl(array $changes = []): string {
    $params = $_GET;

    foreach ($changes as $key => $value) {
        if ($value === null || $value === '') {
            unset($params[$key]);
        } else {
            $params[$key] = $value;
        }
    }

    $query = http_build_query($params);
    return './' . ($query ? '?' . $query : '');
}

$file = dirname(__DIR__) . '/privatedata/parties.json';

if (isset($_POST['delete_party_id'])) {
    $csrfOk = hash_equals($_SESSION['admin_parties_csrf'] ?? '', (string)($_POST['csrf'] ?? ''));

    if ($csrfOk && file_exists($file)) {
        $deleteId = (string)$_POST['delete_party_id'];
        $allParties = readJsonFile($file, []);

        $allParties = array_values(array_filter($allParties, function($party) use ($deleteId) {
            return ($party['id'] ?? '') !== $deleteId;
        }));

        writeJsonFile($file, $allParties);
        rebuildPlayersStats($allParties, dirname(__DIR__) . '/privatedata/players.json');
    }

    header('Location: ' . queryUrl([]));
    exit;
}

if (isset($_POST['set_party_status_id'], $_POST['party_status'])) {
    $csrfOk = hash_equals($_SESSION['admin_parties_csrf'] ?? '', (string)($_POST['csrf'] ?? ''));

    if ($csrfOk && file_exists($file)) {
        $partyId = (string)$_POST['set_party_status_id'];
        $partyStatus = (string)$_POST['party_status'];

        if (in_array($partyStatus, ['validated', 'suspect', 'excluded'], true)) {
            $allParties = readJsonFile($file, []);

            foreach ($allParties as &$party) {
                if (($party['id'] ?? '') === $partyId) {
                    $party['status'] = $partyStatus;
                    break;
                }
            }
            unset($party);

            writeJsonFile($file, $allParties);
            rebuildPlayersStats($allParties, dirname(__DIR__) . '/privatedata/players.json');
        }
    }

    header('Location: ' . queryUrl([]));
    exit;
}

$parties = readJsonFile($file, []);

$filter = (string)($_GET['source'] ?? 'all');
$modeFilter = (string)($_GET['mode'] ?? 'all');
if (!in_array($modeFilter, ['all', 'classic', 'coop'], true)) {
    $modeFilter = 'all';
}
$searchPlayer = trim((string)($_GET['player'] ?? ''));
$dateFrom = trim((string)($_GET['date_from'] ?? ''));
$dateTo = trim((string)($_GET['date_to'] ?? ''));

$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 20;
if ($limit <= 0) {
    $limit = 20;
}

$filteredPartiesAll = array_values(array_filter($parties, function($party) use ($filter, $modeFilter, $searchPlayer, $dateFrom, $dateTo) {
    $source = (string)($party['source'] ?? 'unknown');

    if ($filter !== 'all') {
        if ($filter === 'demo') {
            if (!in_array($source, ['demo', 'demo2026'], true)) {
                return false;
            }
        } elseif ($source !== $filter) {
            return false;
        }
    }

    $gameMode = (($party['game_mode'] ?? 'classic') === 'coop') ? 'coop' : 'classic';
    if ($modeFilter !== 'all' && $gameMode !== $modeFilter) {
        return false;
    }

    if (!partyHasPlayer($party, $searchPlayer)) {
        return false;
    }

    $created = substr((string)($party['created_at'] ?? ''), 0, 10);

    if ($dateFrom !== '' && $created < $dateFrom) {
        return false;
    }

    if ($dateTo !== '' && $created > $dateTo) {
        return false;
    }

    return true;
}));

$totalParties = count($filteredPartiesAll);
$totalPlayers = 0;
$totalDuration = 0;
$totalFoundWords = 0;

$demoCount = 0;
$premiumCount = 0;
$giftCount = 0;
$assoCount = 0;
$testCount = 0;
$unknownCount = 0;
$classiqueCount = 0;
$coopCount = 0;
$coopWonCount = 0;
$coopLostCount = 0;
$validCount = 0;
$suspectCount = 0;
$forcedCount = 0;
$excludedCount = 0;

$playerStats = [];
$themeStats = [];
$difficultyStats = [];
$passedWordsStats = [];
$foundWordsStats = [];

foreach ($filteredPartiesAll as $party) {
    $totalPlayers += (int)($party['players_count'] ?? 0);
    $totalDuration += (int)($party['duration'] ?? 0);

    $source = (string)($party['source'] ?? 'unknown');

    if (in_array($source, ['demo', 'demo2026'], true)) {
        $demoCount++;
    } elseif ($source === 'premium') {
        $premiumCount++;
    } elseif ($source === 'gift') {
        $giftCount++;
    } elseif ($source === 'asso') {
        $assoCount++;
    } elseif ($source === 'test') {
        $testCount++;
    } else {
        $unknownCount++;
    }

    [$antiLabelTmp, $antiClassTmp] = antiCheatLabel($party);
    if ($antiClassTmp === 'statusValidated') {
        $validCount++;
    } elseif ($antiClassTmp === 'statusSuspect') {
        $suspectCount++;
    } elseif ($antiClassTmp === 'statusForced') {
        $forcedCount++;
    } elseif ($antiClassTmp === 'statusExcluded') {
        $excludedCount++;
    }

    if (($party['game_mode'] ?? 'classic') === 'coop') {
        $coopCount++;
        if (is_array($party['coop'] ?? null) && !empty($party['coop']['won'])) {
            $coopWonCount++;
        } else {
            $coopLostCount++;
        }
    } else {
        $classiqueCount++;
    }

    $winner = (string)($party['winner'] ?? '');

    foreach (($party['teams'] ?? []) as $team) {
        $teamName = (string)($team['name'] ?? '');
        $isWinnerTeam = ($teamName === $winner);

        foreach (($team['players'] ?? []) as $player) {
            $playerName = getPlayerName($player);
            $playerId = getPlayerId($player);

            if ($playerName === '') {
                continue;
            }

            $key = $playerId !== '' ? $playerId : $playerName;

            if (!isset($playerStats[$key])) {
                $playerStats[$key] = [
                    'id' => $playerId,
                    'name' => $playerName,
                    'games' => 0,
                    'wins' => 0,
                    'score' => 0,
                    'found' => 0
                ];
            }

            $playerStats[$key]['games']++;

            if ($isWinnerTeam) {
                $playerStats[$key]['wins']++;
            }
        }

        foreach (($team['turnStats'] ?? []) as $turn) {
            foreach (($turn['found'] ?? []) as $word) {
                $word = trim((string)$word);
                if ($word === '') {
                    continue;
                }

                $foundWordsStats[$word] = ($foundWordsStats[$word] ?? 0) + 1;
                $totalFoundWords++;
            }

            foreach (($turn['passed'] ?? []) as $word) {
                $word = trim((string)$word);
                if ($word === '') {
                    continue;
                }

                $passedWordsStats[$word] = ($passedWordsStats[$word] ?? 0) + 1;
            }
        }
    }

    foreach (($party['themes'] ?? []) as $theme) {
        $theme = trim((string)$theme);
        if ($theme === '') {
            continue;
        }
        $themeStats[$theme] = ($themeStats[$theme] ?? 0) + 1;
    }

$difficultyLabel = difficultiesLabel($party);

if ($difficultyLabel !== 'Non enregistrée') {
    $difficultyStats[$difficultyLabel] = ($difficultyStats[$difficultyLabel] ?? 0) + 1;
}
}

uasort($playerStats, function($a, $b) {
    if (($b['wins'] ?? 0) === ($a['wins'] ?? 0)) {
        return ($b['games'] ?? 0) <=> ($a['games'] ?? 0);
    }
    return ($b['wins'] ?? 0) <=> ($a['wins'] ?? 0);
});

arsort($themeStats);
arsort($difficultyStats);
arsort($passedWordsStats);
arsort($foundWordsStats);

$topPlayers = array_slice($playerStats, 0, 8, true);
$topThemes = array_slice($themeStats, 0, 8, true);
$topDifficulties = array_slice($difficultyStats, 0, 8, true);
$topPassedWords = array_slice($passedWordsStats, 0, 10, true);
$topFoundWords = array_slice($foundWordsStats, 0, 10, true);

$averageDuration = $totalParties > 0 ? floor($totalDuration / $totalParties) : 0;
$visibleParties = array_slice($filteredPartiesAll, 0, $limit);
?>
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>Admin parties Chrono Party</title>
<style>
body{font-family:Arial,sans-serif;background:#f6f4ff;margin:0;padding:30px;color:#1f1b3a}
h1{margin-bottom:5px}
a{color:#6f4cff;font-weight:bold}
.card{background:white;border-radius:18px;padding:20px;margin-bottom:20px;box-shadow:0 8px 25px rgba(0,0,0,.08)}
.stats{display:grid;grid-template-columns:repeat(5,1fr);gap:15px}
.stats strong{font-size:26px;color:#7c5cff}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:20px}
.filters{display:flex;gap:10px;flex-wrap:wrap;margin:20px 0}
.filters a,.limitLinks a{padding:10px 14px;border-radius:999px;text-decoration:none;background:#fff;color:#1f1b3a;box-shadow:0 4px 12px rgba(0,0,0,.08)}
.filters a.active,.limitLinks a.active{background:#7c5cff;color:#fff}
.searchBox{display:grid;grid-template-columns:2fr 1fr 1fr auto;gap:10px;align-items:end}
.searchBox label{font-size:12px;font-weight:bold;color:#555}
.searchBox input{width:100%;padding:11px;border:1px solid #ddd;border-radius:10px;box-sizing:border-box}
.searchBox button{padding:12px 18px;border:0;border-radius:10px;background:#7c5cff;color:white;font-weight:bold;cursor:pointer}
table{width:100%;border-collapse:collapse;background:white;border-radius:16px;overflow:hidden}
th,td{padding:12px;border-bottom:1px solid #eee;text-align:left;font-size:14px;vertical-align:top}
th{background:#7c5cff;color:white}
.badge{display:inline-block;padding:5px 9px;border-radius:999px;background:#eee;font-size:12px}
.score{font-weight:bold}
details{cursor:pointer}
small{color:#666}
.rankline{display:flex;justify-content:space-between;gap:12px;border-bottom:1px solid #eee;padding:8px 0}
.deleteBtn{background:#e53935;color:white;border:0;border-radius:8px;padding:7px 10px;cursor:pointer}
.turnDetail{margin-top:10px;padding:10px;border-radius:12px;background:#f4f1ff;border:1px solid #ddd}
.turnDetail small{display:block;margin-top:4px;line-height:1.5;max-height:70px;overflow:auto}
.notice{font-size:13px;color:#666;margin-top:-8px;margin-bottom:14px}
.publicLink,.playerLink{display:inline-block;margin-top:6px;color:#7c5cff;font-weight:bold;text-decoration:none}
.actionBtn{display:inline-block;padding:8px 10px;border-radius:10px;background:#f4f1ff;color:#6f4cff;text-decoration:none;font-size:13px;white-space:nowrap;border:0;cursor:pointer;font-weight:bold}
.coopAdminCard{margin:12px 0;padding:14px;border-radius:16px;background:linear-gradient(135deg,#f4f1ff,#eefaff);border:1px solid #d9d1ff}
.coopAdminTitle{font-size:18px;font-weight:900;color:#4b2fd6;margin-bottom:10px}
.coopAdminGrid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-top:10px}
.coopAdminBox{background:#fff;border-radius:12px;padding:10px;border:1px solid #eee}
.coopAdminBox small{display:block;color:#666;margin-bottom:4px}
.coopAdminBox strong{font-size:18px;color:#1f1b3a}
.coopVictory{color:#12833e;font-weight:900}
.coopDefeat{color:#c62828;font-weight:900}
.coopTurnGrid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}
.coopTurnDetail{background:#fffaf0;border-color:#ffe1a6}
@media(max-width:900px){.coopAdminGrid,.coopTurnGrid{grid-template-columns:1fr}}

.columnFilters th{background:#f4f1ff;color:#1f1b3a;padding:8px}
.columnFilters input,.columnFilters select{
  width:100%;
  min-width:72px;
  box-sizing:border-box;
  padding:8px 9px;
  border:1px solid #ddd;
  border-radius:10px;
  background:#fff;
  color:#1f1b3a;
  font-size:12px;
}
.columnFilters .resetColumnFilters{
  width:100%;
  padding:8px 9px;
  border:0;
  border-radius:10px;
  background:#7c5cff;
  color:white;
  font-weight:bold;
  cursor:pointer;
}
.tableFilterInfo{
  display:inline-block;
  margin-left:10px;
  font-size:13px;
  color:#666;
  font-weight:bold;
}
.quickFilterBar{
  display:grid;
  grid-template-columns:1fr auto;
  gap:10px;
  margin:12px 0 14px;
  align-items:center;
}
.quickFilterBar input{
  width:100%;
  box-sizing:border-box;
  padding:12px 14px;
  border:2px solid #e4ddff;
  border-radius:14px;
  background:#fff;
  color:#1f1b3a;
  font-weight:bold;
}
.quickFilterBar button{
  padding:12px 16px;
  border:0;
  border-radius:14px;
  background:#7c5cff;
  color:white;
  font-weight:bold;
  cursor:pointer;
  white-space:nowrap;
}
@media(max-width:900px){.quickFilterBar{grid-template-columns:1fr}}
.statusValidated{background:#e8fff1;color:#178a45}
.statusSuspect{background:#fff7d6;color:#9a6a00}
.statusForced{background:#eefaff;color:#0369a1}
.statusExcluded{background:#fff0f0;color:#c62828}
@media(max-width:900px){
    .stats{grid-template-columns:repeat(2,1fr)}
    .grid2{grid-template-columns:1fr}
    .searchBox{grid-template-columns:1fr}
    body{padding:15px}
    table{font-size:12px}
}
</style>
</head>
<body>

<h1>Admin parties Chrono Party</h1>
<p><a href="?logout=1">Déconnexion</a></p>
<div class="filters">
    <a href="<?= e(queryUrl(['source' => 'all'])) ?>" class="<?= $filter === 'all' ? 'active' : '' ?>">Toutes</a>
    <a href="<?= e(queryUrl(['source' => 'demo'])) ?>" class="<?= $filter === 'demo' ? 'active' : '' ?>">Démo</a>
    <a href="<?= e(queryUrl(['source' => 'premium'])) ?>" class="<?= $filter === 'premium' ? 'active' : '' ?>">Premium</a>
    <a href="<?= e(queryUrl(['source' => 'gift'])) ?>" class="<?= $filter === 'gift' ? 'active' : '' ?>">Cadeau</a>
    <a href="<?= e(queryUrl(['source' => 'asso'])) ?>" class="<?= $filter === 'asso' ? 'active' : '' ?>">Association</a>
    <a href="<?= e(queryUrl(['source' => 'test'])) ?>" class="<?= $filter === 'test' ? 'active' : '' ?>">Test</a>
</div>

<div class="filters">
    <a href="<?= e(queryUrl(['mode' => 'all'])) ?>" class="<?= $modeFilter === 'all' ? 'active' : '' ?>">Tous modes</a>
    <a href="<?= e(queryUrl(['mode' => 'classic'])) ?>" class="<?= $modeFilter === 'classic' ? 'active' : '' ?>">Classique</a>
    <a href="<?= e(queryUrl(['mode' => 'coop'])) ?>" class="<?= $modeFilter === 'coop' ? 'active' : '' ?>">Coop Boss</a>
</div>

<div class="card">
    <form method="get" class="searchBox">
        <input type="hidden" name="source" value="<?= e($filter) ?>">
        <input type="hidden" name="mode" value="<?= e($modeFilter) ?>">
        <input type="hidden" name="limit" value="<?= e($limit) ?>">

        <div>
            <label>Recherche joueur</label>
            <input type="text" name="player" value="<?= e($searchPlayer) ?>" placeholder="Ex : Giovanni, Sandrine, Bruno...">
        </div>

        <div>
            <label>Date début</label>
            <input type="date" name="date_from" value="<?= e($dateFrom) ?>">
        </div>

        <div>
            <label>Date fin</label>
            <input type="date" name="date_to" value="<?= e($dateTo) ?>">
        </div>

        <button type="submit">Filtrer</button>
    </form>

    <?php if ($searchPlayer !== '' || $dateFrom !== '' || $dateTo !== ''): ?>
        <p style="margin-bottom:0">
            <a href="<?= e(queryUrl(['player' => null, 'date_from' => null, 'date_to' => null])) ?>">Réinitialiser les filtres</a>
        </p>
    <?php endif; ?>
</div>

<div class="card stats">
    <div><strong><?= e($totalParties) ?></strong><br><small>Parties trouvées</small></div>
    <div><strong><?= e($totalPlayers) ?></strong><br><small>Joueurs cumulés</small></div>
    <div><strong><?= e($totalFoundWords) ?></strong><br><small>Mots trouvés</small></div>
    <div><strong><?= e(formatDuration($averageDuration)) ?></strong><br><small>Durée moyenne</small></div>
    <div><strong><?= e($classiqueCount) ?></strong><br><small>Parties classiques</small></div>
    <div><strong><?= e($coopCount) ?></strong><br><small>Parties Coop Boss</small></div>
    <div><strong><?= e($coopWonCount) ?></strong><br><small>Boss vaincus</small></div>
    <div><strong><?= e($coopLostCount) ?></strong><br><small>Boss gagnants</small></div>
    <div><strong><?= e($validCount) ?></strong><br><small>Parties valides</small></div>
    <div><strong><?= e($suspectCount) ?></strong><br><small>À vérifier</small></div>
    <div><strong><?= e($forcedCount) ?></strong><br><small>Publiées forcées</small></div>
    <div><strong><?= e($excludedCount) ?></strong><br><small>Exclues</small></div>
    <div><strong><?= e($demoCount) ?></strong><br><small>Parties démo</small></div>
    <div><strong><?= e($premiumCount) ?></strong><br><small>Parties premium</small></div>
    <div><strong><?= e($giftCount) ?></strong><br><small>Parties cadeau</small></div>
    <div><strong><?= e($assoCount) ?></strong><br><small>Parties association</small></div>
    <div><strong><?= e($testCount) ?></strong><br><small>Parties test</small></div>
    <div><strong><?= e($unknownCount) ?></strong><br><small>Parties inconnues</small></div>
</div>

<div class="grid2">

    <details class="card adminAccordion">
        <summary>🏆 Top joueurs</summary>
        <?php if (empty($topPlayers)): ?>
            <small>Aucune donnée joueur.</small>
        <?php else: ?>
            <?php foreach ($topPlayers as $stats): ?>
                <?php
                    $games = (int)($stats['games'] ?? 0);
                    $wins = (int)($stats['wins'] ?? 0);
                    $rate = $games > 0 ? round(($wins / $games) * 100) : 0;
                    $playerId = (string)($stats['id'] ?? '');
                ?>
                <div class="rankline">
                    <span>
                        <?= e($stats['name'] ?? '') ?>
                        <?php if ($playerId !== ''): ?>
                            <br><a class="playerLink" href="https://chrono-party.e-u.fr/joueur/?id=<?= urlencode($playerId) ?>" target="_blank">Fiche joueur</a>
                        <?php endif; ?>
                    </span>
                    <strong><?= e($wins) ?> victoire(s) / <?= e($games) ?> partie(s) — <?= e($rate) ?>%</strong>
                </div>
            <?php endforeach; ?>
        <?php endif; ?>
    </details>

    <details class="card adminAccordion">
        <summary>⭐ Thèmes les plus joués</summary>
        <?php if (empty($topThemes)): ?>
            <small>Aucune donnée thème.</small>
        <?php else: ?>
            <?php foreach ($topThemes as $theme => $count): ?>
                <div class="rankline">
                    <span><?= e($theme) ?></span>
                    <strong><?= e($count) ?></strong>
                </div>
            <?php endforeach; ?>
        <?php endif; ?>
    </details>

    <details class="card adminAccordion">
        <summary>🎚️ Difficultés les plus jouées</summary>
        <?php if (empty($topDifficulties)): ?>
            <small>Aucune donnée difficulté pour les anciennes parties.</small>
        <?php else: ?>
            <?php foreach ($topDifficulties as $difficulty => $count): ?>
                <div class="rankline">
                    <span><?= e($difficulty) ?></span>
                    <strong><?= e($count) ?></strong>
                </div>
            <?php endforeach; ?>
        <?php endif; ?>
    </details>

    <details class="card adminAccordion">
        <summary>✅ Mots les plus trouvés</summary>
        <?php if (empty($topFoundWords)): ?>
            <small>Aucune donnée de mots trouvés.</small>
        <?php else: ?>
            <?php foreach ($topFoundWords as $word => $count): ?>
                <div class="rankline">
                    <span><?= e($word) ?></span>
                    <strong><?= e($count) ?> fois</strong>
                </div>
            <?php endforeach; ?>
        <?php endif; ?>
    </details>

    <details class="card adminAccordion">
        <summary>⏭️ Mots les plus passés</summary>
        <?php if (empty($topPassedWords)): ?>
            <small>Aucune donnée de mots passés.</small>
        <?php else: ?>
            <?php foreach ($topPassedWords as $word => $count): ?>
                <div class="rankline">
                    <span><?= e($word) ?></span>
                    <strong><?= e($count) ?> fois</strong>
                </div>
            <?php endforeach; ?>
        <?php endif; ?>
    </details>

</div>

<div class="card">
    <h2>Historique des parties</h2>

    <p class="notice">
        Affichage : <?= e(count($visibleParties)) ?> partie(s) sur <?= e($totalParties) ?>.<span id="columnFilterInfo" class="tableFilterInfo"></span>
    </p>

    <div class="limitLinks" style="margin-bottom:15px">
        Voir :
        <a href="<?= e(queryUrl(['limit' => 20])) ?>" class="<?= $limit === 20 ? 'active' : '' ?>">20</a>
        <a href="<?= e(queryUrl(['limit' => 50])) ?>" class="<?= $limit === 50 ? 'active' : '' ?>">50</a>
        <a href="<?= e(queryUrl(['limit' => 100])) ?>" class="<?= $limit === 100 ? 'active' : '' ?>">100</a>
        <a href="<?= e(queryUrl(['limit' => 5000])) ?>" class="<?= $limit === 5000 ? 'active' : '' ?>">Toutes</a>
    </div>

    <div class="quickFilterBar">
        <input type="text" id="globalTableFilter" placeholder="Recherche simple : joueur, code, compte, statut, score, boss...">
        <button type="button" id="resetAllTableFilters">Réinitialiser</button>
    </div>

    <table id="partiesHistoryTable">
        <thead>
        <tr>
            <th>Date</th>
            <th>Source</th>
            <th>Mode</th>
            <th>Statut</th>
            <th>Compte</th>
            <th>Code accès</th>
            <th>Durée</th>
            <th>Joueurs</th>
            <th>Équipes</th>
            <th>Manches</th>
            <th>Difficulté</th>
            <th>Gagnant</th>
            <th>Boss / Résultat</th>
            <th>Scores</th>
            <th>Accès</th>
            <th>Détail</th>
            <th>Suppr.</th>
        </tr>
        <tr class="columnFilters">
            <th><input type="text" data-column-filter="0" data-autosuggest="1" placeholder="Filtrer date"></th>
            <th><input type="text" data-column-filter="1" data-autosuggest="1" placeholder="Source"></th>
            <th><select data-column-filter="2"><option value="">Tous</option><option value="classique">Classique</option><option value="coop">Coop</option></select></th>
            <th><select data-column-filter="3"><option value="">Tous</option><option value="valide">Valide</option><option value="suspecte">Suspecte</option><option value="publiée forcée">Publiée forcée</option><option value="exclue">Exclue</option></select></th>
            <th><input type="text" data-column-filter="4" data-autosuggest="1" placeholder="Compte"></th>
            <th><input type="text" data-column-filter="5" data-autosuggest="1" placeholder="Code"></th>
            <th><input type="text" data-column-filter="6" data-autosuggest="1" placeholder="Durée"></th>
            <th><input type="text" data-column-filter="7" data-autosuggest="1" placeholder="Joueurs"></th>
            <th><input type="text" data-column-filter="8" data-autosuggest="1" placeholder="Équipes"></th>
            <th><input type="text" data-column-filter="9" data-autosuggest="1" placeholder="Manches"></th>
            <th><input type="text" data-column-filter="10" data-autosuggest="1" placeholder="Difficulté"></th>
            <th><input type="text" data-column-filter="11" data-autosuggest="1" placeholder="Gagnant"></th>
            <th><input type="text" data-column-filter="12" data-autosuggest="1" placeholder="Boss"></th>
            <th><input type="text" data-column-filter="13" data-autosuggest="1" placeholder="Score"></th>
            <th><button type="button" class="resetColumnFilters">Reset</button></th>
            <th><input type="text" data-column-filter="15" data-autosuggest="1" placeholder="Détail"></th>
            <th></th>
        </tr>
        </thead>
        <tbody>
        <?php if (empty($visibleParties)): ?>
            <tr>
                <td colspan="17">Aucune partie trouvée.</td>
            </tr>
        <?php endif; ?>

        <?php foreach ($visibleParties as $party): ?>
            <?php
                $partyId = (string)($party['id'] ?? '');
                $publicUrl = '/jeux/partie/?id=' . rawurlencode($partyId);
                $partyStatus = (string)($party['status'] ?? 'validated');
                [$statusLabel, $statusClass] = antiCheatLabel($party);
                $isCurrentlyPublished = ($partyStatus === 'validated');
                $nextPartyStatus = $isCurrentlyPublished ? 'excluded' : 'validated';
                $statusButtonLabel = $statusLabel;
            ?>
            <tr>
                <td><?= e($party['created_at'] ?? '') ?></td>
                <td><span class="badge"><?= e(sourceLabel((string)($party['source'] ?? 'unknown'))) ?></span></td>
                <td><span class="badge"><?= e(gameModeLabel($party)) ?></span></td>
                <td>
                    <?php if ($partyId !== ''): ?>
                        <form method="post">
                            <input type="hidden" name="csrf" value="<?= e($_SESSION['admin_parties_csrf']) ?>">
                            <input type="hidden" name="set_party_status_id" value="<?= e($partyId) ?>">
                            <input type="hidden" name="party_status" value="<?= e($nextPartyStatus) ?>">
                            <button type="submit" class="actionBtn <?= e($statusClass) ?>">
                                <?= e($statusButtonLabel) ?>
                            </button>
                        </form>
                        <?php if ($partyStatus === 'suspect' || (!empty($party['suspicious']) && $partyStatus !== 'validated')): ?>
                            <small style="display:block;margin-top:6px;color:#8a5a00;font-weight:bold">Cliquer pour publier quand même</small>
                        <?php elseif ($partyStatus === 'excluded'): ?>
                            <small style="display:block;margin-top:6px;color:#c62828;font-weight:bold">Cliquer pour revalider</small>
                        <?php elseif ($statusClass === 'statusValidated' || $statusClass === 'statusForced'): ?>
                            <small style="display:block;margin-top:6px;color:#666">Cliquer pour exclure</small>
                        <?php endif; ?>

                        <?php if (antiCheatReasonsLabel($party) !== '—'): ?>
                            <small style="display:block;margin-top:6px;color:#8a5a00;line-height:1.35"><?= e(antiCheatReasonsLabel($party)) ?></small>
                        <?php endif; ?>
                    <?php else: ?>
                        —
                    <?php endif; ?>
                </td>
                <td><?= e($party['client_name'] ?? '—') ?></td>
                <td><strong><?= e($party['gift_code'] ?? '—') ?></strong></td>
                <td><?= e(formatDuration($party['duration'] ?? 0)) ?></td>
                <td><?= e($party['players_count'] ?? 0) ?></td>
                <td><?= e($party['teams_count'] ?? 0) ?></td>
                <td><?= e($party['rounds_played'] ?? 0) ?></td>
                <td><?= e(difficultiesLabel($party)) ?></td>
                <td><strong><?= e($party['winner'] ?? '') ?></strong></td>
                <td><small><?= e(coopBossLabel($party)) ?></small></td>
                <td>
                    <?php if (($party['game_mode'] ?? 'classic') === 'coop' && is_array($party['coop'] ?? null)): ?>
                        <?php $coop = $party['coop']; ?>
                        <div class="score">
                            <?= !empty($coop['won']) ? '🏆 Boss vaincu' : '💀 Boss gagnant' ?>
                        </div>
                        <small><?= e((int)($coop['turns_used'] ?? 0)) ?>/<?= e((int)($coop['max_turns'] ?? 0)) ?> tours joueur</small>
                    <?php else: ?>
                        <?php foreach (($party['scores'] ?? []) as $score): ?>
                            <div class="score">
                                <?= e($score['name'] ?? '') ?> : <?= e($score['total'] ?? 0) ?>
                            </div>
                        <?php endforeach; ?>
                    <?php endif; ?>
                </td>
                <td>
                    <?php if ($partyId !== ''): ?>
                        <a class="actionBtn" href="<?= e($publicUrl) ?>" target="_blank">Voir partie</a>
                    <?php else: ?>
                        —
                    <?php endif; ?>
                </td>
                <td>
                    <details>
                        <summary>Voir</summary>
                        <br>

                        <strong>Joueurs :</strong><br>
                        <?php foreach (($party['teams'] ?? []) as $team): ?>
                            <small>
                                <?= e($team['name'] ?? '') ?> :
                                <?php
                                    $playerLabels = [];
                                    foreach (($team['players'] ?? []) as $player) {
                                        $name = getPlayerName($player);
                                        $id = getPlayerId($player);

                                        if ($name === '') {
                                            continue;
                                        }

                                        if ($id !== '') {
                                            $playerLabels[] = '<a href="https://chrono-party.e-u.fr/joueur/?id=' . urlencode($id) . '" target="_blank">' . e($name) . '</a>';
                                        } else {
                                            $playerLabels[] = e($name);
                                        }
                                    }
                                    echo implode(', ', $playerLabels);
                                ?>
                            </small><br>
                        <?php endforeach; ?>

                        <br><strong>Thèmes :</strong><br>
                        <small><?= e(implode(', ', $party['themes'] ?? [])) ?></small>

                        <br><br><strong>Difficulté :</strong><br>
                        <small><?= e(difficultiesLabel($party)) ?></small>

                        <?php if (($party['game_mode'] ?? 'classic') === 'coop' && is_array($party['coop'] ?? null)): ?>
                            <?php
                                $coop = $party['coop'];
                                $coopWon = !empty($coop['won']);
                                $coopUsed = (int)($coop['turns_used'] ?? 0);
                                $coopMax = (int)($coop['max_turns'] ?? 0);
                                $coopRemaining = (int)($coop['turns_remaining'] ?? 0);
                                $coopOver = (int)($coop['over_by'] ?? 0);
                                $coopPct = $coopMax > 0 ? min(100, round(($coopUsed / $coopMax) * 100)) : 0;
                            ?>
                            <div class="coopAdminCard">
                                <div class="coopAdminTitle">
                                    <?= e(trim((string)($coop['icon'] ?? '👹') . ' ' . (string)($coop['label'] ?? 'Boss'))) ?>
                                    — <span class="<?= $coopWon ? 'coopVictory' : 'coopDefeat' ?>"><?= $coopWon ? 'Boss vaincu' : 'Boss gagnant' ?></span>
                                </div>
                                <div style="height:10px;background:#e8e2ff;border-radius:999px;overflow:hidden">
                                    <div style="width:<?= e($coopPct) ?>%;height:100%;background:<?= $coopWon ? '#23b26d' : '#e53935' ?>"></div>
                                </div>
                                <div class="coopAdminGrid">
                                    <div class="coopAdminBox"><small>Tours joueur</small><strong><?= e($coopUsed) ?>/<?= e($coopMax) ?></strong></div>
                                    <div class="coopAdminBox"><small>Restants</small><strong><?= e($coopRemaining) ?></strong></div>
                                    <div class="coopAdminBox"><small>Dépassement</small><strong><?= e($coopOver) ?></strong></div>
                                    <div class="coopAdminBox"><small>Rang</small><strong><?= e(trim((string)($coop['rank_icon'] ?? '') . ' ' . (string)($coop['rank_label'] ?? ''))) ?></strong></div>
                                </div>
                            </div>
                        <?php endif; ?>

                        <?php foreach (($party['teams'] ?? []) as $team): ?>
                            <?php
                            $turns = $team['turnStats'] ?? [];
                            if (!is_array($turns) || empty($turns)) {
                                continue;
                            }
                            ?>

                            <br><br><strong><?= e($team['name'] ?? '') ?> — Détail des tours :</strong><br>

                            <?php foreach ($turns as $turn): ?>
                                <div class="turnDetail">
                                    <strong>
                                        Manche <?= e($turn['round'] ?? '?') ?>
                                        — <?= e($turn['playerName'] ?? 'Joueur') ?>
                                    </strong>

                                    <br>
                                    ✅ Trouvés :
                                    <strong><?= e($turn['foundCount'] ?? 0) ?></strong>

                                    <?php if (!empty($turn['found']) && is_array($turn['found'])): ?>
                                        <br>
                                        <small><?= e(implode(', ', $turn['found'])) ?></small>
                                    <?php endif; ?>

                                    <?php if (!empty($turn['passed']) && is_array($turn['passed'])): ?>
                                        <br><br>
                                        ⏭️ Passés :
                                        <small><?= e(implode(', ', $turn['passed'])) ?></small>
                                    <?php endif; ?>
                                </div>
                            <?php endforeach; ?>
                        <?php endforeach; ?>

                        <br><br>
                        <a class="publicLink" href="<?= e($publicUrl) ?>" target="_blank">
                            Voir la page publique de cette partie
                        </a>

                        <br><br><strong>ID :</strong><br>
                        <small><?= e($partyId) ?></small>
                    </details>
                </td>
                <td>
                    <form method="post" onsubmit="return confirm('Supprimer cette partie ?');">
                        <input type="hidden" name="csrf" value="<?= e($_SESSION['admin_parties_csrf']) ?>">
                        <input type="hidden" name="delete_party_id" value="<?= e($partyId) ?>">
                        <button type="submit" class="deleteBtn">🗑️</button>
                    </form>
                </td>
            </tr>
        <?php endforeach; ?>
        </tbody>
    </table>
</div>


<script>
(function(){
  const table = document.getElementById('partiesHistoryTable');
  if(!table) return;

  const filters = Array.from(table.querySelectorAll('[data-column-filter]'));
  const resetBtn = table.querySelector('.resetColumnFilters');
  const resetAllBtn = document.getElementById('resetAllTableFilters');
  const globalFilter = document.getElementById('globalTableFilter');
  const info = document.getElementById('columnFilterInfo');

  function normalize(value){
    return (value || '')
      .toString()
      .toLowerCase()
      .normalize('NFD')
      .replace(/[\u0300-\u036f]/g, '')
      .replace(/\s+/g, ' ')
      .trim();
  }

  function cleanCellValue(value){
    return (value || '')
      .toString()
      .replace(/Cliquer pour exclure/gi, '')
      .replace(/Cliquer pour publier quand même/gi, '')
      .replace(/Voir partie/gi, '')
      .replace(/Voir/gi, '')
      .replace(/\s+/g, ' ')
      .trim();
  }

  function getRows(){
    return Array.from(table.querySelectorAll('tbody tr')).filter(row => row.querySelectorAll('td').length > 1);
  }

  function buildDatalists(){
    const rows = getRows();

    filters.forEach(input => {
      if(input.tagName === 'SELECT') return;
      if(input.getAttribute('data-autosuggest') !== '1') return;

      const col = parseInt(input.getAttribute('data-column-filter'), 10);
      if(Number.isNaN(col)) return;

      const datalistId = 'columnFilterList_' + col;
      let datalist = document.getElementById(datalistId);
      if(!datalist){
        datalist = document.createElement('datalist');
        datalist.id = datalistId;
        document.body.appendChild(datalist);
      }

      const values = [];
      const seen = new Set();

      rows.forEach(row => {
        const cell = row.querySelectorAll('td')[col];
        if(!cell) return;
        let value = cleanCellValue(cell.innerText || cell.textContent);
        if(!value) return;

        // Si la cellule contient plusieurs lignes, on ajoute aussi chaque ligne séparée.
        const candidates = [value].concat(value.split(/\n|\|/).map(v => cleanCellValue(v)));

        candidates.forEach(candidate => {
          if(!candidate || candidate.length > 70) return;
          const key = normalize(candidate);
          if(!key || seen.has(key)) return;
          seen.add(key);
          values.push(candidate);
        });
      });

      values.sort((a,b) => a.localeCompare(b, 'fr', {numeric:true, sensitivity:'base'}));
      datalist.innerHTML = values.slice(0, 80).map(value => {
        const option = document.createElement('option');
        option.value = value;
        return option.outerHTML;
      }).join('');

      input.setAttribute('list', datalistId);
    });
  }

  function applyColumnFilters(){
    const globalValue = normalize(globalFilter ? globalFilter.value : '');

    const activeFilters = filters
      .map(input => ({
        col: parseInt(input.getAttribute('data-column-filter'), 10),
        value: normalize(input.value)
      }))
      .filter(item => item.value !== '' && !Number.isNaN(item.col));

    let visible = 0;
    const rows = getRows();

    rows.forEach(row => {
      const rowText = normalize(row.innerText || row.textContent);
      const cells = row.querySelectorAll('td');

      const globalOk = globalValue === '' || rowText.includes(globalValue);

      const columnsOk = activeFilters.every(filter => {
        const cell = cells[filter.col];
        return cell && normalize(cell.innerText || cell.textContent).includes(filter.value);
      });

      const show = globalOk && columnsOk;
      row.style.display = show ? '' : 'none';
      if(show) visible++;
    });

    if(info){
      const activeCount = activeFilters.length + (globalValue !== '' ? 1 : 0);
      info.textContent = activeCount ? ' — filtre actif : ' + visible + ' résultat(s)' : '';
    }
  }

  function resetAllFilters(){
    filters.forEach(input => { input.value = ''; });
    if(globalFilter) globalFilter.value = '';
    applyColumnFilters();
  }

  filters.forEach(input => {
    input.addEventListener('input', applyColumnFilters);
    input.addEventListener('change', applyColumnFilters);
  });

  if(globalFilter){
    globalFilter.addEventListener('input', applyColumnFilters);
  }

  if(resetBtn){
    resetBtn.addEventListener('click', resetAllFilters);
  }

  if(resetAllBtn){
    resetAllBtn.addEventListener('click', resetAllFilters);
  }

  buildDatalists();
})();
</script>

</body>
</html>