<?php

declare(strict_types=1);

/*
|--------------------------------------------------------------------------
| GAME EXIT
|--------------------------------------------------------------------------
| Dipanggil saat pemain kembali dari provider.
| Saldo aktual Nexus/SGX ditarik seluruhnya ke balance_local.
|--------------------------------------------------------------------------
*/

require_once __DIR__ . '/bootstrap.php';

header('X-Content-Type-Options: nosniff');
header('Referrer-Policy: same-origin');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');

function gameExitSafeReturnUrl(
    $value
): string {
    $value = trim((string) $value);

    if (
        $value === '' ||
        preg_match(
            '/^[A-Za-z][A-Za-z0-9+.-]*:/',
            $value
        ) ||
        strpos($value, '//') === 0 ||
        strpos($value, '\\') !== false ||
        preg_match(
            '/[\x00-\x1F\x7F]/',
            $value
        )
    ) {
        return 'index.php';
    }

    $value = ltrim($value, '/');

    return $value !== ''
        ? $value
        : 'index.php';
}

function gameExitError(
    string $message,
    string $returnUrl,
    int $statusCode = 502
): void {
    http_response_code($statusCode);

    $safeMessage = htmlspecialchars(
        $message,
        ENT_QUOTES | ENT_SUBSTITUTE,
        'UTF-8'
    );

    $safeReturnUrl = htmlspecialchars(
        $returnUrl,
        ENT_QUOTES | ENT_SUBSTITUTE,
        'UTF-8'
    );

    echo '<!doctype html>
<html lang="id">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Saldo Game Sedang Diamankan</title>
    <style>
        *{box-sizing:border-box}
        body{
            margin:0;
            min-height:100vh;
            display:grid;
            place-items:center;
            padding:18px;
            color:#fff;
            background:
                radial-gradient(circle at 50% 0,rgba(0,137,255,.28),transparent 300px),
                linear-gradient(180deg,#031431,#010610);
            font-family:Arial,Helvetica,sans-serif
        }
        .box{
            width:min(100%,440px);
            padding:23px;
            border:1px solid rgba(255,198,48,.42);
            border-radius:16px;
            background:linear-gradient(180deg,#092750,#031127);
            box-shadow:0 18px 40px rgba(0,0,0,.48);
            text-align:center
        }
        .icon{
            display:grid;
            width:58px;
            height:58px;
            margin:0 auto 13px;
            place-items:center;
            border:2px solid #ffd44f;
            border-radius:50%;
            color:#2e1800;
            background:linear-gradient(145deg,#fff3a0,#ffbc21);
            font-size:27px;
            font-weight:1000
        }
        h1{
            margin:0;
            color:#ffd34f;
            font-size:21px
        }
        p{
            margin:11px 0 0;
            color:#b3c4d9;
            font-size:13px;
            line-height:1.65
        }
        a{
            display:flex;
            min-height:43px;
            align-items:center;
            justify-content:center;
            margin-top:18px;
            border:1px solid #ffe382;
            border-radius:9px;
            color:#2b1600;
            background:linear-gradient(180deg,#ffe987,#f3ab16);
            font-size:12px;
            font-weight:1000;
            text-decoration:none
        }
    </style>
</head>
<body>
    <main class="box">
        <span class="icon">!</span>
        <h1>Saldo Game Sedang Diamankan</h1>
        <p>' . $safeMessage . '</p>
        <a href="' . $safeReturnUrl . '">COBA KEMBALI KE WEBSITE</a>
    </main>
</body>
</html>';

    exit;
}

$returnUrl = gameExitSafeReturnUrl(
    $_GET['return'] ?? 'index.php'
);

if (!$isLoggedIn || $userId <= 0) {
    header(
        'Location: login.php?next=' .
        rawurlencode(
            'game-exit.php?return=' .
            $returnUrl
        )
    );

    exit;
}

$providedToken = strtolower(
    trim(
        (string) (
            $_GET['token'] ?? ''
        )
    )
);

$sessionToken = strtolower(
    trim(
        (string) (
            $_SESSION[
                'game_exit_token'
            ] ?? ''
        )
    )
);

if (
    preg_match(
        '/^[a-f0-9]{64}$/',
        $providedToken
    ) !== 1 ||
    preg_match(
        '/^[a-f0-9]{64}$/',
        $sessionToken
    ) !== 1 ||
    !hash_equals(
        $sessionToken,
        $providedToken
    )
) {
    gameExitError(
        'Token keluar game tidak valid atau sudah kedaluwarsa. Buka kembali halaman website agar sistem melakukan rekonsiliasi saldo.',
        $returnUrl,
        403
    );
}

$serviceFile = defined('APP_SRC_PATH')
    ? APP_SRC_PATH . '/GameWalletService.php'
    : __DIR__ . '/_app/src/GameWalletService.php';

if (!is_file($serviceFile)) {
    gameExitError(
        'GameWalletService.php belum dipasang.',
        $returnUrl,
        500
    );
}

require_once $serviceFile;

try {
    GameWalletService::bootApi();

    $walletService =
        new GameWalletService($pdo);

    $results =
        $walletService->exitOpenSessions(
            $userId,
            'closed'
        );

    $returnedAmount = 0.0;

    foreach ($results as $result) {
        $returnedAmount += (float) (
            $result[
                'returned_amount'
            ] ?? 0
        );
    }

    $balanceStatement =
        $pdo->prepare(
            'SELECT balance_local
             FROM users
             WHERE id = :user_id
             LIMIT 1'
        );

    $balanceStatement->execute([
        ':user_id' => $userId,
    ]);

    $latestBalance = (float) (
        $balanceStatement->fetchColumn() ?:
        0
    );

    $_SESSION['balance_local'] =
        $latestBalance;

    $_SESSION['balance'] =
        $latestBalance;

    $_SESSION['game_wallet_notice'] = [
        'type' => 'success',
        'message' =>
            $returnedAmount > 0
                ? (
                    'Saldo game IDR ' .
                    number_format(
                        $returnedAmount,
                        0,
                        ',',
                        '.'
                    ) .
                    ' berhasil dikembalikan ke saldo lokal.'
                )
                : 'Sesi game berhasil ditutup.',
    ];

    unset(
        $_SESSION['last_game'],
        $_SESSION['game_exit_token']
    );

    header(
        'Location: ' . $returnUrl,
        true,
        302
    );

    exit;
} catch (Throwable $exception) {
    error_log(
        'GAME EXIT ERROR: ' .
        json_encode(
            [
                'user_id' => $userId,
                'message' =>
                    $exception->getMessage(),
            ],
            JSON_UNESCAPED_SLASHES |
            JSON_UNESCAPED_UNICODE
        )
    );

    $_SESSION['game_wallet_warning'] =
        'Saldo provider belum dapat diselesaikan. Sistem tidak melakukan kredit ganda dan akan mencoba rekonsiliasi pada akses berikutnya.';

    gameExitError(
        $exception->getMessage(),
        $returnUrl,
        502
    );
}
