<?php

declare(strict_types=1);

defined('APP_BOOTSTRAPPED') or exit('No direct access.');

if (defined('GAME_WALLET_GUARD_EXECUTED')) {
    return;
}

define('GAME_WALLET_GUARD_EXECUTED', true);

/*
|--------------------------------------------------------------------------
| Rekonsiliasi otomatis ketika pemain kembali ke website
|--------------------------------------------------------------------------
| Pasang include file ini pada BARIS PALING BAWAH bootstrap.php.
|
| play.php dan game-exit.php dikecualikan karena mempunyai alur wallet sendiri.
|--------------------------------------------------------------------------
*/

if (PHP_SAPI === 'cli') {
    return;
}

if (
    !isset($pdo) ||
    !($pdo instanceof PDO) ||
    empty($isLoggedIn) ||
    empty($userId)
) {
    return;
}

$gameWalletScriptName = str_replace(
    '\\',
    '/',
    (string) (
        $_SERVER['SCRIPT_NAME'] ??
        ''
    )
);

$gameWalletScriptBase = basename(
    $gameWalletScriptName
);

$gameWalletSkipScripts = [
    'play.php',
    'game-exit.php',
    'game-wallet-status.php',
    'qris_callback.php',
];

if (
    in_array(
        $gameWalletScriptBase,
        $gameWalletSkipScripts,
        true
    ) ||
    strpos(
        $gameWalletScriptName,
        '/api/'
    ) !== false
) {
    return;
}

try {
    /*
     * Guard harus aman meskipun SQL wallet belum dipasang.
     * Jangan memakai information_schema karena akun database cPanel
     * dapat tidak memiliki permission untuk membacanya.
     */
    try {
        $pdo->query(
            "SELECT id
             FROM game_sessions
             LIMIT 1"
        );

        $pdo->query(
            "SELECT id
             FROM game_wallet_operations
             LIMIT 1"
        );
    } catch (Throwable $tableException) {
        return;
    }

    $pendingWalletStatement =
        $pdo->prepare(
            "SELECT
                (
                    EXISTS(
                        SELECT 1
                        FROM game_sessions
                        WHERE user_id = :session_user_id
                          AND status = 'open'
                    )
                    OR
                    EXISTS(
                        SELECT 1
                        FROM game_wallet_operations
                        WHERE user_id = :operation_user_id
                          AND status IN (
                              'STARTED',
                              'LOCAL_DEBITED',
                              'PROVIDER_SUCCESS'
                          )
                    )
                ) AS needs_reconcile"
        );

    $pendingWalletStatement->execute([
        ':session_user_id' =>
            (int) $userId,
        ':operation_user_id' =>
            (int) $userId,
    ]);

    if (
        (int) $pendingWalletStatement
            ->fetchColumn() !== 1
    ) {
        return;
    }

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

    if (!is_file($serviceFile)) {
        throw new RuntimeException(
            'GameWalletService.php tidak ditemukan.'
        );
    }

    require_once $serviceFile;

    GameWalletService::bootApi();

    $walletService =
        new GameWalletService($pdo);

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

    $returnedAmount = 0.0;

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

    /*
     * Muat ulang sumber saldo dan variabel bootstrap.
     */
    $refreshStatement =
        $pdo->prepare(
            "SELECT *
             FROM users
             WHERE id = :user_id
             LIMIT 1"
        );

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

    $refreshedUser =
        $refreshStatement->fetch();

    if ($refreshedUser) {
        $currentUser = $refreshedUser;
        $loggedInUser = $refreshedUser;

        $username = (string) (
            $refreshedUser[
                'username'
            ] ?? $username
        );

        $rawBalance = (float) (
            $refreshedUser[
                'balance_local'
            ] ?? 0
        );

        $userBalance = number_format(
            $rawBalance,
            0,
            ',',
            '.'
        );

        $_SESSION['username'] =
            $username;

        $_SESSION['balance_local'] =
            $rawBalance;

        $_SESSION['balance'] =
            $rawBalance;
    }

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

    unset(
        $_SESSION['last_game'],
        $_SESSION['game_exit_token'],
        $_SESSION['game_wallet_warning']
    );
} catch (Throwable $exception) {
    /*
     * Jangan membuat seluruh website HTTP 500 hanya karena provider sedang
     * timeout. Session tetap OPEN dan tidak ada kredit lokal ganda.
     */
    error_log(
        'GAME WALLET BOOTSTRAP RECONCILE ERROR: ' .
        json_encode(
            [
                'user_id' => (int) $userId,
                'script' =>
                    $gameWalletScriptBase,
                'message' =>
                    $exception->getMessage(),
            ],
            JSON_UNESCAPED_SLASHES |
            JSON_UNESCAPED_UNICODE
        )
    );

    $_SESSION['game_wallet_warning'] =
        'Saldo game masih berada di provider dan sedang menunggu rekonsiliasi. Jangan melakukan deposit atau penarikan sampai saldo kembali ke saldo lokal.';
}
