<?php

declare(strict_types=1);

/*
|--------------------------------------------------------------------------
| CRON REKONSILIASI SESSION GAME TERLALU LAMA
|--------------------------------------------------------------------------
| Hanya dapat dijalankan melalui CLI.
|
| Contoh:
| php /home/thgejabu/public_html/cron-game-wallet-reconcile.php --minutes=720
|--------------------------------------------------------------------------
*/

if (PHP_SAPI !== 'cli') {
    http_response_code(403);
    exit('CLI only.');
}

require_once __DIR__ . '/bootstrap.php';

$minutes = 720;

foreach ($argv as $argument) {
    if (
        preg_match(
            '/^--minutes=([0-9]+)$/',
            (string) $argument,
            $match
        ) === 1
    ) {
        $minutes = (int) $match[1];
    }
}

$minutes = max(
    60,
    min(
        10080,
        $minutes
    )
);

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

if (!is_file($serviceFile)) {
    fwrite(
        STDERR,
        "GameWalletService.php tidak ditemukan.\n"
    );

    exit(1);
}

require_once $serviceFile;

try {
    GameWalletService::bootApi();

    $walletService =
        new GameWalletService($pdo);

    /*
     * Angka interval sudah dipaksa integer 60-10080.
     */
    $statement = $pdo->query(
        "SELECT DISTINCT candidates.user_id
         FROM (
            SELECT user_id
            FROM game_sessions
            WHERE status = 'open'
              AND opened_at <
                    DATE_SUB(
                        CURRENT_TIMESTAMP,
                        INTERVAL " .
                        $minutes .
                        " MINUTE
                    )

            UNION ALL

            SELECT user_id
            FROM game_wallet_operations
            WHERE status IN (
                'STARTED',
                'LOCAL_DEBITED',
                'PROVIDER_SUCCESS'
            )
              AND updated_at <
                    DATE_SUB(
                        CURRENT_TIMESTAMP,
                        INTERVAL 5 MINUTE
                    )
         ) candidates
         ORDER BY candidates.user_id ASC
         LIMIT 100"
    );

    $userIds = array_map(
        'intval',
        $statement->fetchAll(
            PDO::FETCH_COLUMN
        )
    );

    $successCount = 0;
    $failedCount = 0;
    $returnedTotal = 0.0;

    foreach ($userIds as $userId) {
        try {
            $results =
                $walletService
                    ->exitOpenSessions(
                        $userId,
                        'closed'
                    );

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

            $successCount++;

            echo
                '[' .
                date('Y-m-d H:i:s') .
                '] user_id=' .
                $userId .
                " selesai\n";
        } catch (Throwable $exception) {
            $failedCount++;

            fwrite(
                STDERR,
                '[' .
                date('Y-m-d H:i:s') .
                '] user_id=' .
                $userId .
                ' gagal: ' .
                $exception->getMessage() .
                "\n"
            );
        }
    }

    echo
        "Selesai. user_sukses=" .
        $successCount .
        " user_gagal=" .
        $failedCount .
        " saldo_kembali=" .
        number_format(
            $returnedTotal,
            2,
            '.',
            ''
        ) .
        "\n";

    exit(
        $failedCount > 0
            ? 2
            : 0
    );
} catch (Throwable $exception) {
    fwrite(
        STDERR,
        'CRON GAME WALLET ERROR: ' .
        $exception->getMessage() .
        "\n"
    );

    exit(1);
}
