<?php

declare(strict_types=1);

ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);

$isHttps = (
    (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ||
    (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https')
);

session_name('ADMINPANELSESSID');

session_set_cookie_params([
    'lifetime' => 0,
    'path'     => '/',
    'domain'   => '',
    'secure'   => $isHttps,
    'httponly' => true,
    'samesite' => 'Lax',
]);

session_start();


/*
|--------------------------------------------------------------------------
| Database
|--------------------------------------------------------------------------
*/

require_once dirname(__DIR__) . '/config/database.php';

if (!isset($pdo) || !$pdo instanceof PDO) {
    http_response_code(500);
    exit('Koneksi PDO tidak tersedia.');
}

/*
|--------------------------------------------------------------------------
| Helper JSON
|--------------------------------------------------------------------------
*/

function jsonResponse(array $data, int $httpCode = 200)
{
    http_response_code($httpCode);

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

    echo json_encode(
        $data,
        JSON_PRETTY_PRINT |
        JSON_UNESCAPED_UNICODE |
        JSON_UNESCAPED_SLASHES
    );

    exit;
}

/*
|--------------------------------------------------------------------------
| CSRF
|--------------------------------------------------------------------------
*/

if (
    empty($_SESSION['csrf_sync_games_sgx']) ||
    !is_string($_SESSION['csrf_sync_games_sgx'])
) {
    $_SESSION['csrf_sync_games_sgx'] = bin2hex(random_bytes(32));
}

/*
|--------------------------------------------------------------------------
| POST: sinkronisasi satu provider
|--------------------------------------------------------------------------
*/

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $csrfInput = (string) ($_POST['csrf_token'] ?? '');
    $csrfSession = (string) (
        $_SESSION['csrf_sync_games_sgx'] ?? ''
    );

    if (
        $csrfInput === '' ||
        $csrfSession === '' ||
        !hash_equals($csrfSession, $csrfInput)
    ) {
        jsonResponse([
            'success' => false,
            'message' => 'CSRF token tidak valid.',
        ], 419);
    }

    $providerCode = strtoupper(
        trim((string) ($_POST['provider_code'] ?? ''))
    );

    if (
        $providerCode === '' ||
        preg_match('/^[A-Z0-9_-]{1,50}$/', $providerCode) !== 1
    ) {
        jsonResponse([
            'success' => false,
            'message' => 'Provider code tidak valid.',
        ], 422);
    }

    /*
    |--------------------------------------------------------------------------
    | Pastikan provider memang berasal dari database
    |--------------------------------------------------------------------------
    */

    $checkProvider = $pdo->prepare("
        SELECT COUNT(*)
        FROM providers_sgx
        WHERE provider_code = :provider_code
    ");

    $checkProvider->execute([
        'provider_code' => $providerCode,
    ]);

    if ((int) $checkProvider->fetchColumn() < 1) {
        jsonResponse([
            'success' => false,
            'message' => 'Provider tidak ditemukan pada providers_sgx.',
        ], 404);
    }

    /*
    |--------------------------------------------------------------------------
    | Konfigurasi SGX
    |--------------------------------------------------------------------------
    */

    $apiUrl = trim(
        getenv('SGX_API_URL') ?: 'https://sgxcenter.xyz/api'
    );

    $agentCode = trim(
        getenv('SGX_AGENT_CODE') ?: 'rudal28'
    );

    /*
     * Sebaiknya signature disimpan melalui environment.
     * Bila environment belum tersedia, isi fallback di bawah.
     */
    $signature = trim(
        getenv('SGX_SIGNATURE') ?: '2036dc7347d1d3f1b799465a6a7b3d4e'
    );

    if (
        $apiUrl === '' ||
        filter_var($apiUrl, FILTER_VALIDATE_URL) === false ||
        strtolower(
            (string) parse_url($apiUrl, PHP_URL_SCHEME)
        ) !== 'https'
    ) {
        jsonResponse([
            'success' => false,
            'message' => 'URL API SGX tidak valid.',
        ], 500);
    }

    if ($agentCode === '') {
        jsonResponse([
            'success' => false,
            'message' => 'Agent code SGX belum dikonfigurasi.',
        ], 500);
    }

    if (
        $signature === '' ||
        $signature === 'MASUKKAN_SIGNATURE_SGX'
    ) {
        jsonResponse([
            'success' => false,
            'message' => 'Signature SGX belum dikonfigurasi.',
        ], 500);
    }

    /*
    |--------------------------------------------------------------------------
    | Payload game_list
    |--------------------------------------------------------------------------
    */

    $payload = [
        'command'       => 'game_list',
        'agent_code'    => $agentCode,
        'signature'     => $signature,
        'provider_code' => $providerCode,
    ];

    try {
        $jsonPayload = json_encode(
            $payload,
            JSON_UNESCAPED_SLASHES |
            JSON_UNESCAPED_UNICODE |
            JSON_THROW_ON_ERROR
        );
    } catch (JsonException $e) {
        error_log(
            'SGX game_list JSON error: ' . $e->getMessage()
        );

        jsonResponse([
            'success' => false,
            'message' => 'Gagal membuat payload SGX.',
        ], 500);
    }

    /*
    |--------------------------------------------------------------------------
    | Request game_list
    |--------------------------------------------------------------------------
    */

    $ch = curl_init();

    if ($ch === false) {
        jsonResponse([
            'success' => false,
            'message' => 'Gagal menginisialisasi cURL.',
        ], 500);
    }

    curl_setopt_array($ch, [
        CURLOPT_URL            => $apiUrl,
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => $jsonPayload,
        CURLOPT_RETURNTRANSFER => true,

        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT        => 60,

        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2,

        // Sesuai IP whitelist SGX
        CURLOPT_IPRESOLVE      => CURL_IPRESOLVE_V4,
        CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,

        CURLOPT_FOLLOWLOCATION => false,
        CURLOPT_MAXREDIRS      => 0,

        CURLOPT_ENCODING       => '',
        CURLOPT_USERAGENT      => 'SGX-PHP-Game-Sync/1.0',

        CURLOPT_HTTPHEADER => [
            'Accept: application/json',
            'Content-Type: application/json; charset=utf-8',
            'Content-Length: ' . strlen($jsonPayload),
            'Connection: close',
        ],
    ]);

    $responseBody = curl_exec($ch);

    $curlError = curl_error($ch);
    $curlErrno = curl_errno($ch);
    $curlInfo  = curl_getinfo($ch);

    $httpCode = (int) ($curlInfo['http_code'] ?? 0);
    $localIp = (string) ($curlInfo['local_ip'] ?? '');
    $remoteIp = (string) ($curlInfo['primary_ip'] ?? '');
    $contentType = (string) (
        $curlInfo['content_type'] ?? ''
    );

    curl_close($ch);

    if ($responseBody === false) {
        error_log(json_encode([
            'event'         => 'SGX_GAME_CURL_FAILED',
            'provider_code' => $providerCode,
            'curl_errno'    => $curlErrno,
            'curl_error'    => $curlError,
        ], JSON_UNESCAPED_UNICODE));

        jsonResponse([
            'success'    => false,
            'message'    => 'Tidak dapat terhubung ke API SGX.',
            'curl_errno' => $curlErrno,
            'curl_error' => $curlError,
        ], 502);
    }

    /*
    |--------------------------------------------------------------------------
    | Decode JSON
    |--------------------------------------------------------------------------
    */

    try {
        $response = json_decode(
            $responseBody,
            true,
            512,
            JSON_THROW_ON_ERROR
        );
    } catch (JsonException $e) {
        $safeBody = trim(
            preg_replace(
                '/\s+/',
                ' ',
                strip_tags((string) $responseBody)
            ) ?? ''
        );

        error_log(json_encode([
            'event'         => 'SGX_GAME_INVALID_JSON',
            'provider_code' => $providerCode,
            'http_code'     => $httpCode,
            'content_type'  => $contentType,
            'body_preview'  => substr($safeBody, 0, 1000),
        ], JSON_UNESCAPED_UNICODE));

        jsonResponse([
            'success'   => false,
            'message'   => 'Respons SGX bukan JSON yang valid.',
            'http_code' => $httpCode,
            'response'  => substr($safeBody, 0, 1000),
        ], 502);
    }

    /*
    |--------------------------------------------------------------------------
    | HTTP error
    |--------------------------------------------------------------------------
    */

    if ($httpCode < 200 || $httpCode >= 300) {
        $sgxMessage = trim(
            (string) (
                $response['message'] ??
                'Tidak ada pesan dari SGX.'
            )
        );

        error_log(json_encode([
            'event'         => 'SGX_GAME_HTTP_ERROR',
            'provider_code' => $providerCode,
            'http_code'     => $httpCode,
            'sgx_message'   => substr($sgxMessage, 0, 500),
        ], JSON_UNESCAPED_UNICODE));

        jsonResponse([
            'success'       => false,
            'provider_code' => $providerCode,
            'http_code'     => $httpCode,
            'message'       => 'API SGX menolak request game_list.',
            'sgx_message'   => $sgxMessage,
        ], $httpCode === 403 ? 403 : 502);
    }

    if (!is_array($response)) {
        jsonResponse([
            'success' => false,
            'message' => 'Format respons SGX tidak valid.',
        ], 502);
    }

    $apiStatus = (int) ($response['status'] ?? 0);

    $apiMessage = trim(
        (string) (
            $response['message'] ??
            'Unknown SGX error'
        )
    );

    /*
     * Contoh:
     * 400 INVALID_PARAMETER
     * 404 INVALID_PROVIDER_CODE
     */
    if ($apiStatus !== 200) {
        error_log(json_encode([
            'event'         => 'SGX_GAME_API_REJECTED',
            'provider_code' => $providerCode,
            'api_status'    => $apiStatus,
            'api_message'   => substr($apiMessage, 0, 500),
        ], JSON_UNESCAPED_UNICODE));

      if ($apiStatus === 400) {
    $returnCode = 422;
} elseif ($apiStatus === 404) {
    $returnCode = 404;
} else {
    $returnCode = 502;
}

        jsonResponse([
            'success'       => false,
            'provider_code' => $providerCode,
            'status'        => $apiStatus,
            'message'       => 'SGX gagal memproses game_list.',
            'sgx_message'   => $apiMessage,
        ], $returnCode);
    }

    $games = $response['data']['games'] ?? null;

    if (!is_array($games)) {
        jsonResponse([
            'success'       => false,
            'provider_code' => $providerCode,
            'message'       => 'Data games tidak ditemukan pada respons SGX.',
        ], 502);
    }

    /*
    |--------------------------------------------------------------------------
    | Query upsert game
    |--------------------------------------------------------------------------
    |
    | is_active, is_popular dan popular_order tidak disentuh ketika sync.
    |--------------------------------------------------------------------------
    */

    $sql = "
        INSERT INTO games_sgx (
            game_code,
            game_name,
            game_provider,
            game_type,
            game_image,
            game_status,
            is_active,
            is_popular,
            popular_order,
            sync_token,
            last_synced_at
        ) VALUES (
            :game_code,
            :game_name,
            :game_provider,
            :game_type,
            :game_image,
            :game_status,
            1,
            0,
            0,
            :sync_token,
            NOW()
        )
        ON DUPLICATE KEY UPDATE
            game_name      = VALUES(game_name),
            game_image     = VALUES(game_image),
            game_status    = VALUES(game_status),
            sync_token     = VALUES(sync_token),
            last_synced_at = NOW()
    ";

    $stmt = $pdo->prepare($sql);

    /*
    |--------------------------------------------------------------------------
    | Sync token
    |--------------------------------------------------------------------------
    |
    | Setelah sync berhasil, game lama yang tidak lagi dikirim SGX
    | akan dibuat game_status = 0.
    |--------------------------------------------------------------------------
    */

    $syncToken = bin2hex(random_bytes(16));

    $processed = 0;
    $inserted  = 0;
    $updated   = 0;
    $unchanged = 0;
    $skipped   = 0;
    $disabled  = 0;
    $errors    = [];

    try {
        $pdo->beginTransaction();

        foreach ($games as $index => $game) {
            if (!is_array($game)) {
                $skipped++;
                $errors[] = "Game index {$index} bukan array.";
                continue;
            }

            $gameCode = trim(
                (string) ($game['game_code'] ?? '')
            );

            $gameName = trim(
                (string) ($game['game_name'] ?? '')
            );

            $gameProvider = strtoupper(
                trim(
                    (string) (
                        $game['game_provider'] ??
                        $providerCode
                    )
                )
            );

            $gameType = strtoupper(
                trim((string) ($game['game_type'] ?? ''))
            );

            $gameImage = trim(
                (string) ($game['game_image'] ?? '')
            );

            $gameStatus = (
                (int) ($game['game_status'] ?? 0) === 1
            ) ? 1 : 0;

            /*
             * Game dari respons harus sesuai provider yang diminta.
             */
            if ($gameProvider !== $providerCode) {
                $skipped++;

                $errors[] = sprintf(
                    'Provider game tidak cocok pada index %d: %s',
                    $index,
                    $gameProvider
                );

                continue;
            }

            if (
                $gameCode === '' ||
                $gameName === '' ||
                $gameType === ''
            ) {
                $skipped++;

                $errors[] = sprintf(
                    'Data game tidak lengkap pada index %d.',
                    $index
                );

                continue;
            }

            if (strlen($gameCode) > 100) {
                $skipped++;

                $errors[] = sprintf(
                    'Game code terlalu panjang pada index %d.',
                    $index
                );

                continue;
            }

            if (mb_strlen($gameName, 'UTF-8') > 255) {
                $gameName = mb_substr(
                    $gameName,
                    0,
                    255,
                    'UTF-8'
                );
            }

            if (strlen($gameProvider) > 50) {
                $skipped++;
                $errors[] = "Provider terlalu panjang: {$gameProvider}";
                continue;
            }

            if (strlen($gameType) > 30) {
                $skipped++;
                $errors[] = "Game type terlalu panjang: {$gameType}";
                continue;
            }

            /*
             * Hanya simpan URL gambar HTTPS.
             */
            if (
                $gameImage === '' ||
                filter_var(
                    $gameImage,
                    FILTER_VALIDATE_URL
                ) === false ||
                strtolower(
                    (string) parse_url(
                        $gameImage,
                        PHP_URL_SCHEME
                    )
                ) !== 'https'
            ) {
                $gameImage = null;
            }

            $stmt->execute([
                'game_code'     => $gameCode,
                'game_name'     => $gameName,
                'game_provider' => $gameProvider,
                'game_type'     => $gameType,
                'game_image'    => $gameImage,
                'game_status'   => $gameStatus,
                'sync_token'    => $syncToken,
            ]);

            $affectedRows = $stmt->rowCount();

            if ($affectedRows === 1) {
                $inserted++;
            } elseif ($affectedRows === 2) {
                $updated++;
            } else {
                $unchanged++;
            }

            $processed++;
        }

        /*
         * Nonaktifkan status API untuk game lama yang tidak ditemukan
         * pada respons terbaru provider tersebut.
         *
         * is_active milik admin tidak ikut diubah.
         */
        $disableOld = $pdo->prepare("
            UPDATE games_sgx
            SET
                game_status = 0,
                last_synced_at = NOW()
            WHERE game_provider = :provider_code
              AND (
                    sync_token IS NULL
                    OR sync_token <> :sync_token
              )
        ");

        $disableOld->execute([
            'provider_code' => $providerCode,
            'sync_token'    => $syncToken,
        ]);

        $disabled = $disableOld->rowCount();

        $pdo->commit();
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }

        error_log(json_encode([
            'event'         => 'SGX_GAME_SYNC_FAILED',
            'provider_code' => $providerCode,
            'message'       => $e->getMessage(),
            'file'          => $e->getFile(),
            'line'          => $e->getLine(),
            'admin_id'      => $_SESSION['admin_id'] ?? null,
        ], JSON_UNESCAPED_UNICODE));

        jsonResponse([
            'success'       => false,
            'provider_code' => $providerCode,
            'message'       => 'Sinkronisasi game SGX gagal.',
            'detail'        => 'Periksa error log server.',
        ], 500);
    }

    jsonResponse([
        'success'       => true,
        'provider_code' => $providerCode,
        'message'       => "Game provider {$providerCode} berhasil disinkronkan.",

        'summary' => [
            'total_api' => count($games),
            'processed' => $processed,
            'inserted'  => $inserted,
            'updated'   => $updated,
            'unchanged' => $unchanged,
            'disabled'  => $disabled,
            'skipped'   => $skipped,
        ],

        'connection' => [
            'http_code' => $httpCode,
            'local_ip'  => $localIp,
            'remote_ip' => $remoteIp,
        ],

        'errors' => array_slice($errors, 0, 20),
    ]);
}

/*
|--------------------------------------------------------------------------
| GET: tampilkan halaman admin
|--------------------------------------------------------------------------
*/

if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
    header('Allow: GET, POST');

    jsonResponse([
        'success' => false,
        'message' => 'Metode request tidak diperbolehkan.',
    ], 405);
}

/*
|--------------------------------------------------------------------------
| Ambil provider unik
|--------------------------------------------------------------------------
|
| Provider code dapat muncul pada beberapa tipe.
| Karena game_list meminta provider_code, kita panggil satu kali per kode.
|--------------------------------------------------------------------------
*/

$providerQuery = $pdo->query("
    SELECT
        provider_code,
        GROUP_CONCAT(
            DISTINCT provider_name
            ORDER BY provider_name
            SEPARATOR ', '
        ) AS provider_names,
        COUNT(*) AS provider_rows
    FROM providers_sgx
    WHERE provider_status = 1
    GROUP BY provider_code
    ORDER BY provider_code ASC
");

$providers = $providerQuery->fetchAll(PDO::FETCH_ASSOC);

$csrfToken = htmlspecialchars(
    (string) $_SESSION['csrf_sync_games_sgx'],
    ENT_QUOTES,
    'UTF-8'
);

$actionUrl = htmlspecialchars(
    (string) ($_SERVER['PHP_SELF'] ?? ''),
    ENT_QUOTES,
    'UTF-8'
);

?>
<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">

    <meta
        name="viewport"
        content="width=device-width, initial-scale=1"
    >

    <title>Sinkronisasi Game SGX</title>

    <style>
        * {
            box-sizing: border-box;
        }

        body {
            margin: 0;
            min-height: 100vh;
            padding: 24px;
            background: #071426;
            color: #ffffff;
            font-family: Arial, Helvetica, sans-serif;
        }

        .container {
            width: 100%;
            max-width: 1000px;
            margin: 0 auto;
        }

        .card {
            padding: 24px;
            border: 1px solid rgba(255, 255, 255, .12);
            border-radius: 18px;
            background: #0d2038;
            box-shadow: 0 20px 60px rgba(0, 0, 0, .25);
        }

        h1 {
            margin: 0 0 8px;
            font-size: 28px;
        }

        .subtitle {
            margin: 0 0 24px;
            color: #b9cbe0;
            line-height: 1.6;
        }

        .actions {
            display: grid;
            grid-template-columns: 1fr auto auto;
            gap: 12px;
            margin-bottom: 20px;
        }

        select,
        button {
            min-height: 46px;
            border-radius: 10px;
            font-size: 15px;
        }

        select {
            width: 100%;
            padding: 0 12px;
            border: 1px solid rgba(255, 255, 255, .15);
            background: #08192c;
            color: #ffffff;
        }

        button {
            border: 0;
            padding: 0 18px;
            background: #f2b632;
            color: #111827;
            font-weight: 700;
            cursor: pointer;
        }

        button.secondary {
            background: #dbeafe;
        }

        button.stop {
            background: #ef4444;
            color: #ffffff;
        }

        button:disabled {
            cursor: not-allowed;
            opacity: .55;
        }

        .progress-wrap {
            overflow: hidden;
            height: 18px;
            margin: 20px 0 8px;
            border-radius: 999px;
            background: #06101e;
        }

        .progress {
            width: 0;
            height: 100%;
            background: linear-gradient(
                90deg,
                #f2b632,
                #ffd972
            );
            transition: width .25s ease;
        }

        .progress-text {
            margin-bottom: 20px;
            color: #c8d7e8;
            font-size: 14px;
        }

        .stats {
            display: grid;
            grid-template-columns: repeat(5, 1fr);
            gap: 12px;
            margin-bottom: 20px;
        }

        .stat {
            padding: 14px;
            border-radius: 12px;
            background: #08192c;
            text-align: center;
        }

        .stat strong {
            display: block;
            margin-bottom: 4px;
            font-size: 22px;
        }

        .stat span {
            color: #9fb4ca;
            font-size: 12px;
        }

        .log {
            height: 420px;
            overflow: auto;
            padding: 16px;
            border-radius: 12px;
            background: #030b15;
            color: #d6e4f2;
            font-family: Consolas, monospace;
            font-size: 13px;
            line-height: 1.6;
            white-space: pre-wrap;
        }

        .success {
            color: #7ef2a8;
        }

        .error {
            color: #ff8c8c;
        }

        .warning {
            color: #ffd972;
        }

        @media (max-width: 760px) {
            body {
                padding: 12px;
            }

            .actions {
                grid-template-columns: 1fr;
            }

            .stats {
                grid-template-columns: repeat(2, 1fr);
            }

            .log {
                height: 360px;
            }
        }
    </style>
</head>

<body>
<div class="container">
    <div class="card">
        <h1>Sinkronisasi Game SGX</h1>

        <p class="subtitle">
            Sinkronkan game berdasarkan provider code.
            Proses semua provider dijalankan satu per satu agar
            tidak mudah terkena timeout server.
        </p>

        <div class="actions">
            <select id="providerSelect">
                <option value="">
                    Pilih provider
                </option>

                <?php foreach ($providers as $provider): ?>
                    <?php
                    $code = htmlspecialchars(
                        (string) $provider['provider_code'],
                        ENT_QUOTES,
                        'UTF-8'
                    );

                    $names = htmlspecialchars(
                        (string) $provider['provider_names'],
                        ENT_QUOTES,
                        'UTF-8'
                    );
                    ?>

                    <option value="<?= $code ?>">
                        <?= $code ?> — <?= $names ?>
                    </option>
                <?php endforeach; ?>
            </select>

            <button
                type="button"
                id="syncSelectedButton"
                class="secondary"
            >
                Sync Pilihan
            </button>

            <button
                type="button"
                id="syncAllButton"
            >
                Sync Semua
            </button>
        </div>

        <button
            type="button"
            id="stopButton"
            class="stop"
            disabled
        >
            Hentikan Proses
        </button>

        <div class="progress-wrap">
            <div
                class="progress"
                id="progressBar"
            ></div>
        </div>

        <div
            class="progress-text"
            id="progressText"
        >
            Belum ada proses.
        </div>

        <div class="stats">
            <div class="stat">
                <strong id="statProviders">0</strong>
                <span>Provider selesai</span>
            </div>

            <div class="stat">
                <strong id="statGames">0</strong>
                <span>Game diproses</span>
            </div>

            <div class="stat">
                <strong id="statInserted">0</strong>
                <span>Game baru</span>
            </div>

            <div class="stat">
                <strong id="statUpdated">0</strong>
                <span>Game update</span>
            </div>

            <div class="stat">
                <strong id="statFailed">0</strong>
                <span>Provider gagal</span>
            </div>
        </div>

        <div class="log" id="logBox">Siap melakukan sinkronisasi.</div>
    </div>
</div>

<script>
'use strict';

const endpoint = <?= json_encode(
    $actionUrl,
    JSON_UNESCAPED_SLASHES
) ?>;

const csrfToken = <?= json_encode(
    $csrfToken,
    JSON_UNESCAPED_SLASHES
) ?>;

const providerCodes = <?= json_encode(
    array_values(
        array_map(
            static fn(array $provider): string =>
                (string) $provider['provider_code'],
            $providers
        )
    ),
    JSON_UNESCAPED_SLASHES |
    JSON_UNESCAPED_UNICODE
) ?>;

const syncAllButton = document.getElementById('syncAllButton');
const syncSelectedButton = document.getElementById(
    'syncSelectedButton'
);
const stopButton = document.getElementById('stopButton');
const providerSelect = document.getElementById('providerSelect');

const progressBar = document.getElementById('progressBar');
const progressText = document.getElementById('progressText');
const logBox = document.getElementById('logBox');

const statProviders = document.getElementById('statProviders');
const statGames = document.getElementById('statGames');
const statInserted = document.getElementById('statInserted');
const statUpdated = document.getElementById('statUpdated');
const statFailed = document.getElementById('statFailed');

let shouldStop = false;
let isRunning = false;

let totals = {
    providers: 0,
    games: 0,
    inserted: 0,
    updated: 0,
    failed: 0
};

function resetTotals() {
    totals = {
        providers: 0,
        games: 0,
        inserted: 0,
        updated: 0,
        failed: 0
    };

    updateStats();
}

function updateStats() {
    statProviders.textContent = String(totals.providers);
    statGames.textContent = String(totals.games);
    statInserted.textContent = String(totals.inserted);
    statUpdated.textContent = String(totals.updated);
    statFailed.textContent = String(totals.failed);
}

function appendLog(message, type = '') {
    const time = new Date().toLocaleTimeString('id-ID');

    const line = document.createElement('div');

    if (type) {
        line.className = type;
    }

    line.textContent = `[${time}] ${message}`;

    logBox.appendChild(line);
    logBox.scrollTop = logBox.scrollHeight;
}

function setRunning(running) {
    isRunning = running;

    syncAllButton.disabled = running;
    syncSelectedButton.disabled = running;
    providerSelect.disabled = running;
    stopButton.disabled = !running;
}

async function syncProvider(providerCode) {
    const body = new URLSearchParams();

    body.set('csrf_token', csrfToken);
    body.set('provider_code', providerCode);

    const response = await fetch(endpoint, {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type':
                'application/x-www-form-urlencoded;charset=UTF-8'
        },
        credentials: 'same-origin',
        body: body.toString()
    });

    let result;

    try {
        result = await response.json();
    } catch (error) {
        throw new Error(
            `Respons ${providerCode} bukan JSON. HTTP ${response.status}`
        );
    }

    if (!response.ok || result.success !== true) {
        const message =
            result.sgx_message ||
            result.message ||
            `HTTP ${response.status}`;

        throw new Error(message);
    }

    return result;
}

async function runSync(codes) {
    if (isRunning || codes.length === 0) {
        return;
    }

    resetTotals();

    logBox.textContent = '';
    shouldStop = false;

    setRunning(true);

    appendLog(
        `Memulai sinkronisasi ${codes.length} provider.`,
        'warning'
    );

    for (let index = 0; index < codes.length; index++) {
        if (shouldStop) {
            appendLog(
                'Proses dihentikan oleh admin.',
                'warning'
            );
            break;
        }

        const providerCode = codes[index];

        const percentBefore = Math.round(
            (index / codes.length) * 100
        );

        progressBar.style.width = `${percentBefore}%`;

        progressText.textContent =
            `Memproses ${providerCode} ` +
            `(${index + 1} dari ${codes.length})`;

        appendLog(
            `Mengambil game provider ${providerCode}...`
        );

        try {
            const result = await syncProvider(providerCode);
            const summary = result.summary || {};

            totals.providers++;
            totals.games += Number(summary.processed || 0);
            totals.inserted += Number(summary.inserted || 0);
            totals.updated += Number(summary.updated || 0);

            updateStats();

            appendLog(
                `${providerCode} berhasil — ` +
                `${summary.processed || 0} game, ` +
                `${summary.inserted || 0} baru, ` +
                `${summary.updated || 0} update, ` +
                `${summary.disabled || 0} dinonaktifkan.`,
                'success'
            );
        } catch (error) {
            totals.failed++;
            updateStats();

            appendLog(
                `${providerCode} gagal — ${error.message}`,
                'error'
            );
        }

        const percentAfter = Math.round(
            ((index + 1) / codes.length) * 100
        );

        progressBar.style.width = `${percentAfter}%`;

        /*
         * Jeda ringan agar request tidak terlalu agresif.
         */
        await new Promise(resolve => setTimeout(resolve, 200));
    }

    setRunning(false);

    if (!shouldStop) {
        progressBar.style.width = '100%';
        progressText.textContent = 'Sinkronisasi selesai.';

        appendLog(
            'Seluruh proses sinkronisasi selesai.',
            'success'
        );
    } else {
        progressText.textContent =
            'Sinkronisasi dihentikan.';
    }
}

syncAllButton.addEventListener('click', () => {
    runSync(providerCodes);
});

syncSelectedButton.addEventListener('click', () => {
    const selectedCode = providerSelect.value.trim();

    if (!selectedCode) {
        appendLog(
            'Silakan pilih provider terlebih dahulu.',
            'warning'
        );
        return;
    }

    runSync([selectedCode]);
});

stopButton.addEventListener('click', () => {
    shouldStop = true;
    stopButton.disabled = true;

    appendLog(
        'Permintaan menghentikan proses diterima.',
        'warning'
    );
});
</script>
</body>
</html>