<?php
declare(strict_types=1);

header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');

$profilesFile = dirname(__DIR__) . '/privatedata/players-profiles.json';

function json_response(array $data): void
{
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
    exit;
}

function clean_owner_key(string $value): string
{
    $value = trim(strtolower($value));
    $value = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $value) ?: $value;
    $value = preg_replace('/[^a-z0-9_-]+/i', '-', $value) ?? '';
    $value = preg_replace('/-+/', '-', $value) ?? '';
    return substr(trim(strtolower($value), '-_'), 0, 80) ?: 'default';
}

function normalize_player_key(string $name, string $initials): string
{
    $name = trim(strtolower($name));
    $initials = trim(strtolower($initials));

    $name = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $name) ?: $name;
    $initials = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $initials) ?: $initials;

    $name = preg_replace('/[^a-z0-9 -]/i', '', $name) ?? '';
    $initials = preg_replace('/[^a-z0-9]/i', '', $initials) ?? '';
    $name = preg_replace('/\s+/', '-', trim($name)) ?? '';

    return strtolower(trim($name . '-' . $initials, '-'));
}

function make_scoped_key(string $ownerKey, string $name, string $initials): string
{
    return clean_owner_key($ownerKey) . '__' . normalize_player_key($name, $initials);
}

function create_player_id(): string
{
    return 'player_' . bin2hex(random_bytes(8));
}

function profile_owner_matches(array $profile, string $ownerKey): bool
{
    $ownerKey = clean_owner_key($ownerKey);
    $profileOwner = clean_owner_key((string)($profile['owner_key'] ?? ''));

    if ($profileOwner !== '' && $profileOwner !== 'default' && $profileOwner === $ownerKey) {
        return true;
    }

    $owners = $profile['owners'] ?? [];
    if (is_array($owners)) {
        foreach ($owners as $owner) {
            if (clean_owner_key((string)$owner) === $ownerKey) {
                return true;
            }
        }
    }

    return false;
}

function ensure_profile_owner(array &$profile, string $ownerKey): void
{
    $ownerKey = clean_owner_key($ownerKey);
    $profileOwner = clean_owner_key((string)($profile['owner_key'] ?? ''));

    if ($profileOwner === '' || $profileOwner === 'default') {
        $profile['owner_key'] = $ownerKey;
    }

    $owners = $profile['owners'] ?? [];
    if (!is_array($owners)) {
        $owners = [];
    }

    $cleanOwners = [];
    foreach ($owners as $owner) {
        $clean = clean_owner_key((string)$owner);
        if ($clean !== '' && !in_array($clean, $cleanOwners, true)) {
            $cleanOwners[] = $clean;
        }
    }

    if (!in_array($ownerKey, $cleanOwners, true)) {
        $cleanOwners[] = $ownerKey;
    }

    $profile['owners'] = $cleanOwners;
}

function find_existing_profile_by_player_key(array $profiles, string $playerKey): array
{
    $matches = [];

    foreach ($profiles as $profileKey => $profile) {
        if (!is_array($profile)) {
            continue;
        }

        $existingPlayerKey = (string)($profile['player_key'] ?? '');
        if ($existingPlayerKey === '') {
            $existingPlayerKey = normalize_player_key(
                (string)($profile['name'] ?? ''),
                (string)($profile['initials'] ?? '')
            );
        }

        if ($existingPlayerKey === '' || $existingPlayerKey !== $playerKey) {
            continue;
        }

        $matches[] = [
            'profile_key' => (string)$profileKey,
            'profile' => $profile
        ];
    }

    return $matches;
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    json_response(['ok' => false, 'error' => 'Méthode non autorisée']);
}

$raw = file_get_contents('php://input');
$input = json_decode($raw ?: '', true);

if (!is_array($input)) {
    json_response(['ok' => false, 'error' => 'Données invalides']);
}

$name = trim((string)($input['name'] ?? ''));
$initials = strtoupper(trim((string)($input['initials'] ?? '')));
$initials = preg_replace('/[^A-Z0-9]/i', '', $initials) ?? '';
$initials = substr($initials, 0, 2);
$ownerKey = clean_owner_key((string)($input['owner_key'] ?? 'default'));
$confirmExisting = filter_var($input['confirm_existing'] ?? false, FILTER_VALIDATE_BOOLEAN);

if ($name === '' || $initials === '') {
    json_response(['ok' => false, 'error' => 'Prénom ou initiale manquant']);
}

$playerKey = normalize_player_key($name, $initials);
if ($playerKey === '') {
    json_response(['ok' => false, 'error' => 'Identité joueur invalide']);
}

if (!is_dir(dirname($profilesFile))) {
    if (!mkdir(dirname($profilesFile), 0755, true) && !is_dir(dirname($profilesFile))) {
        json_response(['ok' => false, 'error' => 'Impossible de créer le dossier privatedata']);
    }
}

if (!is_file($profilesFile)) {
    file_put_contents($profilesFile, "{}", LOCK_EX);
}

$scopedKey = make_scoped_key($ownerKey, $name, $initials);
$handle = fopen($profilesFile, 'c+');

if (!$handle) {
    json_response(['ok' => false, 'error' => 'Impossible d’ouvrir le fichier joueurs']);
}

flock($handle, LOCK_EX);
rewind($handle);
$content = stream_get_contents($handle);
$profiles = json_decode((string)$content, true);

if (!is_array($profiles)) {
    $profiles = [];
}

$existingMatches = find_existing_profile_by_player_key($profiles, $playerKey);
$sameOwnerMatch = null;
$otherOwnerMatch = null;

foreach ($existingMatches as $match) {
    $profile = $match['profile'];
    if (profile_owner_matches($profile, $ownerKey)) {
        $sameOwnerMatch = $match;
        break;
    }
    if ($otherOwnerMatch === null) {
        $otherOwnerMatch = $match;
    }
}

// Cas 1 : le prénom + initiale existent déjà dans le même compte.
// On réutilise le profil existant, même si l'ancien stockage n'était pas encore sous la clé gift-xxx__prenom-i.
if ($sameOwnerMatch !== null) {
    $key = (string)$sameOwnerMatch['profile_key'];
    if (isset($profiles[$key]) && is_array($profiles[$key])) {
        ensure_profile_owner($profiles[$key], $ownerKey);
        $profiles[$key]['player_key'] = $playerKey;
        $profiles[$key]['name'] = trim((string)($profiles[$key]['name'] ?? $name)) ?: $name;
        $profiles[$key]['initials'] = trim((string)($profiles[$key]['initials'] ?? $initials)) ?: $initials;
        $profiles[$key]['last_seen_at'] = time();

        rewind($handle);
        ftruncate($handle, 0);
        fwrite($handle, json_encode($profiles, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
        fflush($handle);
        flock($handle, LOCK_UN);
        fclose($handle);

        json_response([
            'ok' => true,
            'reused_existing_same_account' => true,
            'player' => [
                'id' => $profiles[$key]['id'],
                'name' => $profiles[$key]['name'],
                'initials' => $profiles[$key]['initials'],
                'key' => $key,
                'owner_key' => clean_owner_key((string)($profiles[$key]['owner_key'] ?? $ownerKey))
            ]
        ]);
    }
}

// Cas 2 : il existe uniquement dans un autre compte.
// On avertit, puis on autorise après confirmation pour garder une utilisation souple.
if ($otherOwnerMatch !== null) {
    if (!$confirmExisting) {
        flock($handle, LOCK_UN);
        fclose($handle);
        json_response([
            'ok' => false,
            'code' => 'PLAYER_EXISTS_OTHER_ACCOUNT_CONFIRM',
            'error' => 'Ce profil existe déjà sur un autre compte. Confirmez-vous que c’est bien vous ?',
            'existing_player' => [
                'name' => (string)($otherOwnerMatch['profile']['name'] ?? $name),
                'initials' => (string)($otherOwnerMatch['profile']['initials'] ?? $initials),
                'owner_key' => clean_owner_key((string)($otherOwnerMatch['profile']['owner_key'] ?? ''))
            ]
        ]);
    }

    $key = (string)$otherOwnerMatch['profile_key'];
    if (isset($profiles[$key]) && is_array($profiles[$key])) {
        $profiles[$key]['last_seen_at'] = time();

        rewind($handle);
        ftruncate($handle, 0);
        fwrite($handle, json_encode($profiles, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
        fflush($handle);
        flock($handle, LOCK_UN);
        fclose($handle);

        json_response([
            'ok' => true,
            'confirmed_existing_other_account' => true,
            'warning' => 'Profil existant utilisé après confirmation.',
            'player' => [
                'id' => $profiles[$key]['id'],
                'name' => $profiles[$key]['name'],
                'initials' => $profiles[$key]['initials'],
                'key' => $key,
                'owner_key' => clean_owner_key((string)($profiles[$key]['owner_key'] ?? ''))
            ]
        ]);
    }
}

// Cas 3 : nouveau profil dans ce compte.
$key = $scopedKey;
$profiles[$key] = [
    'id' => create_player_id(),
    'owner_key' => $ownerKey,
    'owners' => [$ownerKey],
    'player_key' => $playerKey,
    'name' => $name,
    'initials' => $initials,
    'created_at' => time(),
    'last_seen_at' => time(),
    'games' => 0
];

rewind($handle);
ftruncate($handle, 0);
fwrite($handle, json_encode($profiles, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
fflush($handle);
flock($handle, LOCK_UN);
fclose($handle);

json_response([
    'ok' => true,
    'created' => true,
    'player' => [
        'id' => $profiles[$key]['id'],
        'name' => $profiles[$key]['name'],
        'initials' => $profiles[$key]['initials'],
        'key' => $key,
        'owner_key' => $ownerKey
    ]
]);
