<?php

declare(strict_types=1);

/*
|--------------------------------------------------------------------------
| BOOTSTRAP UTAMA APLIKASI
|--------------------------------------------------------------------------
| File ini wajib dipanggil paling awal oleh semua halaman:
|
| require_once __DIR__ . '/bootstrap.php';
|
| Jangan menjalankan session_start() lagi di halaman lain.
|--------------------------------------------------------------------------
*/

/*
|--------------------------------------------------------------------------
| Cegah bootstrap diproses dua kali
|--------------------------------------------------------------------------
*/

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

define('APP_BOOTSTRAPPED', true);

/*
|--------------------------------------------------------------------------
| Mode error
|--------------------------------------------------------------------------
| Saat website sudah stabil, biarkan display_errors = 0.
| Error tetap dicatat ke error_log server.
|--------------------------------------------------------------------------
*/

ini_set('display_errors', '0');
ini_set('display_startup_errors', '0');
ini_set('log_errors', '1');

error_reporting(E_ALL);

/*
|--------------------------------------------------------------------------
| Zona waktu
|--------------------------------------------------------------------------
*/

date_default_timezone_set('Asia/Jakarta');

/*
|--------------------------------------------------------------------------
| Lokasi aplikasi
|--------------------------------------------------------------------------
*/

define('PUBLIC_PATH', __DIR__);
define('APP_PATH', PUBLIC_PATH . '/_app');
define('APP_CONFIG_PATH', APP_PATH . '/config');
define('APP_SRC_PATH', APP_PATH . '/src');

/*
|--------------------------------------------------------------------------
| Periksa folder wajib
|--------------------------------------------------------------------------
*/

$requiredDirectories = [
    'PUBLIC_PATH' => PUBLIC_PATH,
    'APP_PATH' => APP_PATH,
    'APP_CONFIG_PATH' => APP_CONFIG_PATH,
    'APP_SRC_PATH' => APP_SRC_PATH,
];

$missingDirectories = [];

foreach ($requiredDirectories as $name => $directory) {
    if (!is_dir($directory)) {
        $missingDirectories[$name] = $directory;
    }
}

if (!empty($missingDirectories)) {
    http_response_code(500);

    header(
        'Content-Type: text/plain; charset=UTF-8'
    );

    echo "STRUKTUR APLIKASI BELUM LENGKAP\n\n";
    echo "Lokasi bootstrap:\n";
    echo __FILE__ . "\n\n";

    echo "Folder public yang dibaca:\n";
    echo PUBLIC_PATH . "\n\n";

    echo "Folder yang tidak ditemukan:\n";

    foreach ($missingDirectories as $name => $directory) {
        echo '- ' . $name . ': ' . $directory . "\n";
    }

    echo "\nBuat folder tersebut melalui File Manager cPanel.";

    exit;
}

/*
|--------------------------------------------------------------------------
| Session tunggal seluruh website
|--------------------------------------------------------------------------
| Semua halaman harus memakai nama session yang sama: USERSESSID.
|--------------------------------------------------------------------------
*/

if (session_status() === PHP_SESSION_NONE) {
    /*
     * Pengaturan ini wajib dijalankan sebelum session_start().
     */
    ini_set('session.use_strict_mode', '1');
    ini_set('session.use_only_cookies', '1');
    ini_set('session.use_trans_sid', '0');

    session_name('USERSESSID');

    $isHttps =
        !empty($_SERVER['HTTPS']) &&
        strtolower((string) $_SERVER['HTTPS']) !== 'off';

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

    session_start();
}

/*
|--------------------------------------------------------------------------
| Pastikan session yang aktif benar
|--------------------------------------------------------------------------
*/

if (
    session_status() !== PHP_SESSION_ACTIVE ||
    session_name() !== 'USERSESSID'
) {
    http_response_code(500);

    header(
        'Content-Type: text/plain; charset=UTF-8'
    );

    echo "SESSION WEBSITE TIDAK SESUAI\n\n";
    echo "Session yang seharusnya: USERSESSID\n";
    echo "Session yang aktif: " . session_name() . "\n\n";
    echo "Pastikan bootstrap.php dipanggil sebelum file lain.";

    exit;
}

/*
|--------------------------------------------------------------------------
| Helper escape HTML
|--------------------------------------------------------------------------
*/

if (!function_exists('e')) {
    function e($value): string
    {
        return htmlspecialchars(
            (string) $value,
            ENT_QUOTES | ENT_SUBSTITUTE,
            'UTF-8'
        );
    }
}

/*
|--------------------------------------------------------------------------
| Muat koneksi database
|--------------------------------------------------------------------------
| Urutan lokasi:
| 1. public_html/config/database.php
| 2. public_html/_app/config/database.php
|--------------------------------------------------------------------------
*/

$databaseCandidates = [
    PUBLIC_PATH . '/config/database.php',
    APP_CONFIG_PATH . '/database.php',
];


$databaseFile = '';

foreach ($databaseCandidates as $candidate) {
    if (is_file($candidate)) {
        $databaseFile = $candidate;
        break;
    }
}

if ($databaseFile === '') {
    http_response_code(500);

    header(
        'Content-Type: text/plain; charset=UTF-8'
    );

    echo "FILE DATABASE TIDAK DITEMUKAN\n\n";

    foreach ($databaseCandidates as $candidate) {
        echo '- ' . $candidate . "\n";
    }

    exit;
}

if (!isset($pdo) || !($pdo instanceof PDO)) {
    require_once $databaseFile;
}

if (!isset($pdo) || !($pdo instanceof PDO)) {
    http_response_code(500);

    header(
        'Content-Type: text/plain; charset=UTF-8'
    );

    echo "KONEKSI PDO TIDAK TERSEDIA\n\n";
    echo "File yang dibaca:\n";
    echo $databaseFile . "\n\n";
    echo "Pastikan config/database.php membuat variabel \$pdo.";

    exit;
}

$pdo->setAttribute(
    PDO::ATTR_ERRMODE,
    PDO::ERRMODE_EXCEPTION
);

$pdo->setAttribute(
    PDO::ATTR_DEFAULT_FETCH_MODE,
    PDO::FETCH_ASSOC
);

$pdo->setAttribute(
    PDO::ATTR_EMULATE_PREPARES,
    false
);


/*
|--------------------------------------------------------------------------
| Pemeriksaan maintenance
|--------------------------------------------------------------------------
| Wajib dijalankan setelah koneksi PDO tersedia dan sebelum output HTML.
|--------------------------------------------------------------------------
*/

require_once
    '/home/thgejabu/backoffice_app/src/maintenance_guard.php';

maintenanceGuard($pdo);

/*
|--------------------------------------------------------------------------
| Registry sesi member
|--------------------------------------------------------------------------
| Helper ini menyimpan hash session, memeriksa revoke, dan memperbarui
| aktivitas terakhir. Tidak menyimpan PHP session ID asli.
|--------------------------------------------------------------------------
*/

$memberSessionRegistryFile =
    APP_SRC_PATH .
    '/member_session_registry.php';

$memberSessionRegistryReady = false;

if (is_file($memberSessionRegistryFile)) {
    require_once
        $memberSessionRegistryFile;

    $memberSessionRegistryReady =
        function_exists(
            'memberSessionGuard'
        );
} else {
    error_log(
        'MEMBER SESSION REGISTRY NOT FOUND: ' .
        $memberSessionRegistryFile
    );
}

/*
|--------------------------------------------------------------------------
| Nilai awal pengguna
|--------------------------------------------------------------------------
| Variabel ini otomatis tersedia di seluruh halaman yang memanggil bootstrap.
|--------------------------------------------------------------------------
*/

$currentUser = null;

$isLoggedIn = false;
$userId = 0;

$username = 'Pengunjung';

$rawBalance = 0.0;
$userBalance = '0';

$userInitial = 'M';

/*
|--------------------------------------------------------------------------
| Ambil user berdasarkan session user_id
|--------------------------------------------------------------------------
| Username TIDAK dibaca dari $_SESSION['username'].
| Username selalu dibaca ulang dari tabel users.
|--------------------------------------------------------------------------
*/

$userId = isset($_SESSION['user_id'])
    ? (int) $_SESSION['user_id']
    : 0;

if ($userId > 0) {
    try {
        $userStatement = $pdo->prepare(
            'SELECT *
             FROM users
             WHERE id = :user_id
             LIMIT 1'
        );

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

        $userRow = $userStatement->fetch();

        if (is_array($userRow) && !empty($userRow)) {
            /*
             * Validasi status akun.
             * Mendukung ACTIVE, AKTIF, 1, ON, TRUE.
             * Jika kolom status tidak ada, akun dianggap aktif.
             */
            $accountIsActive = true;

            if (array_key_exists('status', $userRow)) {
                $statusValue = strtoupper(
                    trim(
                        (string) $userRow['status']
                    )
                );

                $accountIsActive = in_array(
                    $statusValue,
                    [
                        'ACTIVE',
                        'AKTIF',
                        '1',
                        'ON',
                        'TRUE',
                    ],
                    true
                );
            }

            if ($accountIsActive) {
                $currentUser = $userRow;
                $isLoggedIn = true;

                $username = trim(
                    (string) (
                        $userRow['username'] ??
                        ''
                    )
                );

                if ($username === '') {
                    $username = 'Member';
                }

                /*
                 * Dukungan beberapa nama kolom saldo.
                 */
                if (
                    array_key_exists(
                        'balance_local',
                        $userRow
                    )
                ) {
                    $rawBalance = (float)
                        $userRow['balance_local'];
                } elseif (
                    array_key_exists(
                        'saldo',
                        $userRow
                    )
                ) {
                    $rawBalance = (float)
                        $userRow['saldo'];
                } elseif (
                    array_key_exists(
                        'balance',
                        $userRow
                    )
                ) {
                    $rawBalance = (float)
                        $userRow['balance'];
                }

                /*
                 * Sinkronkan session lama supaya file lama tetap kompatibel.
                 * Sumber kebenarannya tetap data dari SQL di atas.
                 */
                $_SESSION['user_id'] =
                    (int) $userRow['id'];

                $_SESSION['username'] =
                    $username;

                $_SESSION['balance_local'] =
                    $rawBalance;

                $_SESSION['balance'] =
                    $rawBalance;

                if (
                    array_key_exists(
                        'email',
                        $userRow
                    )
                ) {
                    $_SESSION['email'] =
                        (string) $userRow['email'];
                }

                if (
                    array_key_exists(
                        'phone',
                        $userRow
                    )
                ) {
                    $_SESSION['phone'] =
                        (string) $userRow['phone'];
                }

                /*
                 * Daftarkan sesi pertama kali dan periksa apakah sesi
                 * sudah dicabut, logout, atau kedaluwarsa.
                 */
                if (
                    $memberSessionRegistryReady
                ) {
                    $memberSessionValid =
                        memberSessionGuard(
                            $pdo,
                            (int) $userRow['id'],
                            session_id(),
                            60
                        );

                    if (!$memberSessionValid) {
                        $_SESSION = [];

                        if (
                            ini_get(
                                'session.use_cookies'
                            )
                        ) {
                            $cookieParams =
                                session_get_cookie_params();

                            setcookie(
                                session_name(),
                                '',
                                [
                                    'expires' =>
                                        time() - 42000,
                                    'path' =>
                                        $cookieParams[
                                            'path'
                                        ],
                                    'domain' =>
                                        $cookieParams[
                                            'domain'
                                        ],
                                    'secure' =>
                                        (bool) $cookieParams[
                                            'secure'
                                        ],
                                    'httponly' =>
                                        (bool) $cookieParams[
                                            'httponly'
                                        ],
                                    'samesite' =>
                                        $cookieParams[
                                            'samesite'
                                        ] ?? 'Lax',
                                ]
                            );
                        }

                        session_destroy();

                        $acceptHeader =
                            strtolower(
                                (string) (
                                    $_SERVER[
                                        'HTTP_ACCEPT'
                                    ] ?? ''
                                )
                            );

                        $requestedWith =
                            strtolower(
                                (string) (
                                    $_SERVER[
                                        'HTTP_X_REQUESTED_WITH'
                                    ] ?? ''
                                )
                            );

                        $expectsJson =
                            str_contains(
                                $acceptHeader,
                                'application/json'
                            ) ||
                            $requestedWith ===
                                'xmlhttprequest';

                        if ($expectsJson) {
                            http_response_code(401);

                            header(
                                'Content-Type: application/json; charset=UTF-8'
                            );

                            echo json_encode(
                                [
                                    'success' => false,
                                    'message' =>
                                        'Sesi login sudah berakhir atau dicabut.',
                                    'reason' =>
                                        'session_revoked',
                                ],
                                JSON_UNESCAPED_UNICODE |
                                JSON_UNESCAPED_SLASHES
                            );

                            exit;
                        }

                        header(
                            'Location: /login.php?' .
                            http_build_query([
                                'reason' =>
                                    'session_revoked',
                            ])
                        );

                        exit;
                    }
                }

                $_SESSION['last_activity'] =
                    time();
            } else {
                /*
                 * Akun tidak aktif.
                 */
                unset(
                    $_SESSION['user_id'],
                    $_SESSION['username'],
                    $_SESSION['balance'],
                    $_SESSION['balance_local'],
                    $_SESSION['email'],
                    $_SESSION['phone']
                );

                $currentUser = null;
                $isLoggedIn = false;
                $userId = 0;
            }
        } else {
            /*
             * user_id session tidak ditemukan pada tabel users.
             */
            unset(
                $_SESSION['user_id'],
                $_SESSION['username'],
                $_SESSION['balance'],
                $_SESSION['balance_local'],
                $_SESSION['email'],
                $_SESSION['phone']
            );

            $currentUser = null;
            $isLoggedIn = false;
            $userId = 0;
        }
    } catch (Throwable $exception) {
        /*
         * Jangan menggunakan username session lama saat query gagal.
         */
        $currentUser = null;
        $isLoggedIn = false;

        $username = 'Pengunjung';
        $rawBalance = 0.0;

        error_log(
            'BOOTSTRAP USER ERROR: ' .
            $exception->getMessage()
        );
    }
}

/*
|--------------------------------------------------------------------------
| Format saldo
|--------------------------------------------------------------------------
*/

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

/*
|--------------------------------------------------------------------------
| Huruf awal username
|--------------------------------------------------------------------------
*/

$userInitialSource = preg_replace(
    '/[^A-Za-z0-9]/',
    '',
    $username
);

if (
    is_string($userInitialSource) &&
    $userInitialSource !== ''
) {
    $userInitial = strtoupper(
        function_exists('mb_substr')
            ? mb_substr(
                $userInitialSource,
                0,
                1,
                'UTF-8'
            )
            : substr(
                $userInitialSource,
                0,
                1
            )
    );
}

/*
|--------------------------------------------------------------------------
| Variabel kompatibilitas tambahan
|--------------------------------------------------------------------------
*/

$loggedInUser = $currentUser;

require_once APP_SRC_PATH . '/game_wallet_bootstrap_guard.php';