<?php
declare(strict_types=1);

header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');

$leaderboardFile = __DIR__ . '/leaderboard.json';
$maxEntries = 100;

function send_json(int $status, array $payload): void
{
    http_response_code($status);
    echo json_encode($payload);
    exit;
}

function sanitize_name($value): string
{
    $value = preg_replace('/[^a-z0-9 _-]/i', '', (string) ($value ?? '')) ?? '';
    return substr(trim($value), 0, 12);
}

function sanitize_score($value): int
{
    $score = filter_var($value, FILTER_VALIDATE_INT);
    if ($score === false || $score < 0) {
        return 0;
    }

    return $score;
}

function normalize_entries(array $entries, int $maxEntries): array
{
    $deduped = [];

    foreach ($entries as $entry) {
        $sanitized = [
            'name' => sanitize_name($entry['name'] ?? ''),
            'score' => sanitize_score($entry['score'] ?? 0),
            'createdAt' => is_string($entry['createdAt'] ?? null) ? $entry['createdAt'] : gmdate('c'),
        ];

        if ($sanitized['name'] === '' || $sanitized['score'] <= 0) {
            continue;
        }

        $key = strtolower($sanitized['name']);
        if (!isset($deduped[$key])) {
            $deduped[$key] = $sanitized;
            continue;
        }

        $existing = $deduped[$key];
        if ($sanitized['score'] > $existing['score']) {
            $deduped[$key] = $sanitized;
            continue;
        }

        if ($sanitized['score'] === $existing['score']) {
            $existingTime = strtotime($existing['createdAt']) ?: PHP_INT_MAX;
            $nextTime = strtotime($sanitized['createdAt']) ?: PHP_INT_MAX;
            if ($nextTime < $existingTime) {
                $deduped[$key] = $sanitized;
            }
        }
    }

    $entries = array_values($deduped);
    usort($entries, static function (array $a, array $b): int {
        if ($a['score'] !== $b['score']) {
            return $b['score'] <=> $a['score'];
        }

        return (strtotime($a['createdAt']) ?: PHP_INT_MAX) <=> (strtotime($b['createdAt']) ?: PHP_INT_MAX);
    });

    return array_slice($entries, 0, $maxEntries);
}

function ensure_leaderboard_file(string $path): void
{
    if (!file_exists($path)) {
        file_put_contents($path, "[]\n", LOCK_EX);
    }
}

function read_leaderboard(string $path, int $maxEntries): array
{
    ensure_leaderboard_file($path);
    $raw = file_get_contents($path);
    $parsed = json_decode($raw ?: '[]', true);

    if (!is_array($parsed)) {
        return [];
    }

    return normalize_entries($parsed, $maxEntries);
}

function write_leaderboard(string $path, array $entries, int $maxEntries): array
{
    $normalized = normalize_entries($entries, $maxEntries);
    file_put_contents($path, json_encode($normalized, JSON_PRETTY_PRINT) . "\n", LOCK_EX);
    return $normalized;
}

$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';

if ($method === 'GET') {
    send_json(200, ['entries' => read_leaderboard($leaderboardFile, $maxEntries)]);
}

if ($method !== 'POST') {
    send_json(405, ['error' => 'Method not allowed.']);
}

$rawBody = file_get_contents('php://input');
$payload = json_decode($rawBody ?: '{}', true);
if (!is_array($payload)) {
    send_json(400, ['error' => 'Invalid JSON payload.']);
}

$name = sanitize_name($payload['name'] ?? '');
$score = sanitize_score($payload['score'] ?? 0);

if ($name === '' || $score <= 0) {
    send_json(400, ['error' => 'A name and positive score are required.']);
}

$entries = read_leaderboard($leaderboardFile, $maxEntries);
$entries[] = [
    'name' => $name,
    'score' => $score,
    'createdAt' => gmdate('c'),
];

send_json(201, ['entries' => write_leaderboard($leaderboardFile, $entries, $maxEntries)]);
