<?php

/**
 * Reliable cart-to-cart pay approval (single request, idempotent, deadlock-safe panel writes).
 */
class PayApprovalService
{
    /**
     * @return array{ok:bool,alert:string,error?:string}
     */
    public static function approve(string $payHash): array
    {
        global $connection;

        @ignore_user_abort(true);
        @set_time_limit(0);

        $stmt = $connection->prepare('SELECT * FROM `pays` WHERE `hash_id` = ? LIMIT 1');
        $stmt->bind_param('s', $payHash);
        $stmt->execute();
        $payInfo = $stmt->get_result()->fetch_assoc();
        $stmt->close();

        if (!$payInfo) {
            return ['ok' => false, 'alert' => 'سفارش یافت نشد'];
        }
        if ($payInfo['state'] === 'approved') {
            return ['ok' => false, 'alert' => '✅ قبلاً تأیید شده'];
        }

        self::normalizeLegacyQueueState($payHash);

        $existingOrder = getOrderByPayHash($payHash);
        if ($existingOrder && ($payInfo['type'] ?? '') !== 'RENEW_SCONFIG') {
            return self::resendExistingOrder($payHash, $payInfo, $existingOrder);
        }

        if (!claimPayProcessing($payHash, 120)) {
            $existingOrder = getOrderByPayHash($payHash);
            if ($existingOrder) {
                return self::resendExistingOrder($payHash, $payInfo, $existingOrder);
            }
            return ['ok' => false, 'alert' => '⏳ این سفارش در حال پردازش است. چند ثانیه بعد دوباره بزنید.'];
        }

        try {
            if (($payInfo['type'] ?? '') === 'RENEW_SCONFIG') {
                $result = self::approveRenew($payHash, $payInfo);
            } else {
                $result = self::approvePurchase($payHash, $payInfo);
            }
            if (!$result['ok']) {
                releasePayProcessing($payHash);
            }
            return $result;
        } catch (Throwable $e) {
            global $admin;
            releasePayProcessing($payHash);
            if (!empty($admin)) {
                sendMessage("❌ خطای تأیید خرید:\n" . $e->getMessage(), null, null, $admin);
            }
            return ['ok' => false, 'alert' => '❌ خطای داخلی', 'error' => $e->getMessage()];
        }
    }

    private static function normalizeLegacyQueueState(string $payHash): void
    {
        global $connection;
        $stmt = $connection->prepare(
            "UPDATE `pays` SET `state` = 'have_sent' WHERE `hash_id` = ? AND `state` IN ('queued', 'processing')"
        );
        $stmt->bind_param('s', $payHash);
        $stmt->execute();
        $stmt->close();
    }

    /** @param array<string, mixed> $payInfo @param array<string, mixed> $existingOrder */
    private static function resendExistingOrder(string $payHash, array $payInfo, array $existingOrder): array
    {
        global $buttonValues, $mainValues;

        $uid = (int) $payInfo['user_id'];
        $remark = (string) $existingOrder['remark'];
        $fid = (int) $payInfo['plan_id'];

        $file_detail = self::loadPlan($fid);
        if (!$file_detail) {
            return ['ok' => false, 'alert' => '❌ پلن یافت نشد'];
        }

        $keyboard = json_encode(['inline_keyboard' => [[['text' => $buttonValues['back_to_main'], 'callback_data' => 'mainMenu']]]]);
        $server_id = (int) $existingOrder['server_id'];
        $serverType = (string) (self::loadServerConfig($server_id)['type'] ?? '');
        self::deliverOrderToCustomer($uid, $server_id, $serverType, $remark, $existingOrder, $keyboard, $fid);

        markPayApproved($payHash);
        self::markAdminDone($payInfo);
        self::notifyAdminConfigSent(
            $payInfo,
            $remark,
            (int) $file_detail['volume'],
            (int) $file_detail['days']
        );

        return ['ok' => true, 'alert' => (string) $mainValues['sending_config_to_user']];
    }

    /** @param array<string, mixed> $payInfo @return array{ok:bool,alert:string,error?:string} */
    private static function approveRenew(string $payHash, array $payInfo): array
    {
        global $mainValues;

        $uid = (int) $payInfo['user_id'];
        $fid = (int) $payInfo['plan_id'];
        $price = (int) $payInfo['price'];
        $file_detail = self::loadPlan($fid);
        if (!$file_detail) {
            return ['ok' => false, 'alert' => '❌ پلن یافت نشد'];
        }

        $days = (int) $file_detail['days'];
        $volume = (int) $file_detail['volume'];
        $server_id = (int) $file_detail['server_id'];
        $configInfo = json_decode((string) ($payInfo['description'] ?? ''), true) ?: [];
        $uuid = (string) ($configInfo['uuid'] ?? '');
        $remark = (string) ($configInfo['remark'] ?? '');
        $isUserApi = !empty($configInfo['marzban']) || !empty($configInfo['pasarguard']);
        $inbound_id = (int) $payInfo['volume'];
        $time = time();

        $response = withPanelWriteLock(function () use ($isUserApi, $server_id, $remark, $days, $volume, $inbound_id, $uuid) {
            if ($isUserApi) {
                return editUserApiPanelConfig($server_id, ['remark' => $remark, 'days' => $days, 'volume' => $volume]);
            }
            if ($inbound_id > 0) {
                return editClientTraffic($server_id, $inbound_id, $uuid, $volume, $days, 'renew');
            }
            return editInboundTraffic($server_id, $uuid, $volume, $days, 'renew');
        });

        if (is_null($response)) {
            return ['ok' => false, 'alert' => '🔻 مشکل فنی در اتصال به سرور', 'error' => 'connection failed'];
        }

        global $connection;
        $stmt = $connection->prepare('INSERT INTO `increase_order` VALUES (NULL, ?, ?, ?, ?, ?, ?)');
        $stmt->bind_param('iiisii', $uid, $server_id, $inbound_id, $remark, $price, $time);
        $stmt->execute();
        $stmt->close();

        sendMessage(
            str_replace(['REMARK', 'VOLUME', 'DAYS'], [$remark, $volume, $days], $mainValues['renewed_config_to_user']),
            getMainKeys(),
            null,
            null,
            $uid
        );
        sendMessage("✅سرویس $remark با موفقیت تمدید شد", null, null, $uid);

        markPayApproved($payHash);
        self::markAdminDone($payInfo);
        self::notifyAdminConfigSent($payInfo, $remark, $volume, $days);

        return ['ok' => true, 'alert' => '✅ تمدید انجام شد'];
    }

    /** @param array<string, mixed> $payInfo @return array{ok:bool,alert:string,error?:string} */
    private static function approvePurchase(string $payHash, array $payInfo): array
    {
        global $botState, $mainValues, $admin, $buttonValues;

        $uid = (int) $payInfo['user_id'];
        $fid = (int) $payInfo['plan_id'];
        $price = (int) $payInfo['price'];
        $file_detail = self::loadPlan($fid);
        if (!$file_detail) {
            return ['ok' => false, 'alert' => '❌ پلن یافت نشد'];
        }

        $days = (int) $file_detail['days'];
        $volume = (int) $file_detail['volume'];
        $protocol = (string) $file_detail['protocol'];
        $server_id = (int) $file_detail['server_id'];
        $netType = (string) $file_detail['type'];
        $acount = (int) $file_detail['acount'];
        $inbound_id = (int) $file_detail['inbound_id'];
        $limitip = (int) $file_detail['limitip'];
        $rahgozar = (int) $file_detail['rahgozar'];
        $accountCount = ((int) ($payInfo['agent_count'] ?? 0)) !== 0 ? (int) $payInfo['agent_count'] : 1;
        $eachPrice = (int) ($price / $accountCount);
        $date = time();
        $expire_microdate = (int) floor(microtime(true) * 1000) + (864000 * $days * 100);
        $expire_date = $date + (86400 * $days);

        if ($acount === 0 && planHasInbounds($file_detail)) {
            return ['ok' => false, 'alert' => (string) $mainValues['out_of_connection_capacity']];
        }

        $serverInfo = self::loadServerInfo($server_id);
        $serverConfig = self::loadServerConfig($server_id);
        if (!$serverInfo || !$serverConfig) {
            return ['ok' => false, 'alert' => '❌ سرور یافت نشد'];
        }

        if (!planHasInbounds($file_detail) && (int) ($serverInfo['ucount'] ?? 0) <= 0) {
            return ['ok' => false, 'alert' => (string) $mainValues['out_of_server_capacity']];
        }

        $srv_remark = (string) ($serverInfo['remark'] ?? '');
        $serverType = (string) ($serverConfig['type'] ?? '');
        $portType = (string) ($serverConfig['port_type'] ?? '');
        $keyboard = json_encode(['inline_keyboard' => [[['text' => $buttonValues['back_to_main'], 'callback_data' => 'mainMenu']]]]);

        $remark = '';
        for ($i = 1; $i <= $accountCount; $i++) {
            $remark = self::buildRemark($payInfo, $srv_remark, $uid);

            if (planHasInbounds($file_detail) && isXuiPanel($server_id) && panelClientExistsForRemark($server_id, $remark)) {
                $resume = self::completeExistingPanelClient(
                    $payHash,
                    $payInfo,
                    $uid,
                    $fid,
                    $server_id,
                    $inbound_id,
                    $remark,
                    $protocol,
                    $expire_date,
                    $eachPrice,
                    $date,
                    $rahgozar,
                    $keyboard
                );
                if ($resume['ok']) {
                    return self::finishPurchaseSuccess($payHash, $payInfo, $file_detail, $remark, $price, $uid, $volume, $days, $accountCount, $server_id, $fid);
                }
            }

            if (!planHasInbounds($file_detail) && isUserApiPanelType($serverType) && userApiPanelUserExists($server_id, $remark)) {
                $resume = self::completeExistingUserApiClient(
                    $payHash,
                    $payInfo,
                    $uid,
                    $fid,
                    $server_id,
                    $serverType,
                    $inbound_id,
                    $remark,
                    $protocol,
                    $expire_date,
                    $eachPrice,
                    $date,
                    $rahgozar,
                    $keyboard
                );
                if ($resume['ok']) {
                    return self::finishPurchaseSuccess($payHash, $payInfo, $file_detail, $remark, $price, $uid, $volume, $days, $accountCount, $server_id, $fid);
                }
            }

            $uniqid = generateRandomString(42, $protocol);
            $port = self::nextPort($portType);

            $response = withPanelWriteLock(function () use (
                $file_detail,
                $serverType,
                $server_id,
                $uniqid,
                $protocol,
                $port,
                $expire_microdate,
                $remark,
                $volume,
                $netType,
                $rahgozar,
                $fid,
                $inbound_id,
                $limitip,
                $days
            ) {
                if (!planHasInbounds($file_detail)) {
                    if (isUserApiPanelType($serverType)) {
                        return addUserApiPanelUser($server_id, $remark, $volume, $days, $fid);
                    }
                    $response = addUser($server_id, $uniqid, $protocol, $port, $expire_microdate, $remark, $volume, $netType, 'none', $rahgozar, $fid);
                    if (!$response->success && (isPanelDuplicateEmailError($response->msg ?? '') || strstr($response->msg ?? '', 'Duplicate email'))) {
                        return $response;
                    }
                    if (!$response->success && strstr($response->msg ?? '', 'Port already exists')) {
                        $port = rand(1111, 65000);
                        $response = addUser($server_id, $uniqid, $protocol, $port, $expire_microdate, $remark, $volume, $netType, 'none', $rahgozar, $fid);
                    }
                    return $response;
                }
                return addInboundAccount($server_id, $uniqid, $inbound_id, $expire_microdate, $remark, $volume, $limitip, null, $fid);
            });

            if ($response === null || $response === 'inbound not Found') {
                return ['ok' => false, 'alert' => '❌ اتصال به سرور برقرار نیست', 'error' => 'connection failed'];
            }

            if (is_object($response) && !$response->success) {
                if (planHasInbounds($file_detail) && isXuiPanel($server_id) && panelClientExistsForRemark($server_id, $remark)) {
                    $resume = self::completeExistingPanelClient(
                        $payHash,
                        $payInfo,
                        $uid,
                        $fid,
                        $server_id,
                        $inbound_id,
                        $remark,
                        $protocol,
                        $expire_date,
                        $eachPrice,
                        $date,
                        $rahgozar,
                        $keyboard
                    );
                    if ($resume['ok']) {
                        return self::finishPurchaseSuccess($payHash, $payInfo, $file_detail, $remark, $price, $uid, $volume, $days, $accountCount, $server_id, $fid);
                    }
                }

                if (!planHasInbounds($file_detail) && isUserApiPanelType($serverType) && (
                    ($response->msg ?? '') === 'User already exists' || userApiPanelUserExists($server_id, $remark)
                )) {
                    $resume = self::completeExistingUserApiClient(
                        $payHash,
                        $payInfo,
                        $uid,
                        $fid,
                        $server_id,
                        $serverType,
                        $inbound_id,
                        $remark,
                        $protocol,
                        $expire_date,
                        $eachPrice,
                        $date,
                        $rahgozar,
                        $keyboard
                    );
                    if ($resume['ok']) {
                        return self::finishPurchaseSuccess($payHash, $payInfo, $file_detail, $remark, $price, $uid, $volume, $days, $accountCount, $server_id, $fid);
                    }
                }

                $err = (string) ($response->msg ?? 'panel error');
                sendMessage('❌ | 😮 وای خطا داد لطفا سریع به مدیر بگو ...', null, null, $admin);
                sendMessage('خطای سرور ' . ($serverInfo['title'] ?? '') . ":\n\n" . $err, null, null, $admin);
                return ['ok' => false, 'alert' => '❌ خطای پنل', 'error' => $err];
            }

            $remark = syncRemarkFromPanelResponse($response, $remark);

            if (isUserApiPanelType($serverType)) {
                self::createAndDeliverUserApiOrder(
                    $payHash,
                    $payInfo,
                    $uid,
                    $fid,
                    $server_id,
                    $serverType,
                    $inbound_id,
                    $remark,
                    $protocol,
                    $expire_date,
                    $eachPrice,
                    $date,
                    $rahgozar,
                    $keyboard,
                    $response
                );
            } else {
                self::createAndDeliverXuiOrder(
                    $payHash,
                    $payInfo,
                    $uid,
                    $fid,
                    $server_id,
                    $inbound_id,
                    $remark,
                    $protocol,
                    $expire_date,
                    $eachPrice,
                    $date,
                    $rahgozar,
                    $keyboard
                );
            }
        }

        return self::finishPurchaseSuccess($payHash, $payInfo, $file_detail, $remark, $price, $uid, $volume, $days, $accountCount, $server_id, $fid);
    }

    /**
     * @param array<string, mixed> $payInfo
     * @param array<string, mixed> $file_detail
     * @return array{ok:bool,alert:string}
     */
    private static function finishPurchaseSuccess(
        string $payHash,
        array $payInfo,
        array $file_detail,
        string $remark,
        int $price,
        int $uid,
        int $volume,
        int $days,
        int $accountCount,
        int $server_id,
        int $fid
    ): array {
        global $mainValues;

        self::decrementCapacity($file_detail, $accountCount, $server_id, $fid);
        self::notifyAfterPurchase($payInfo, $file_detail, $remark, $price, $uid);
        markPayApproved($payHash);
        self::markAdminDone($payInfo);
        self::notifyAdminConfigSent($payInfo, $remark, $volume, $days);

        return ['ok' => true, 'alert' => (string) $mainValues['sending_config_to_user']];
    }

    /** @param array<string, mixed>|null $order */
    private static function deliverOrderToCustomer(
        int $uid,
        int $server_id,
        string $serverType,
        string $remark,
        ?array $order,
        string $keyboard,
        int $fid
    ): void {
        if (isUserApiPanelType($serverType)) {
            resendUserApiPanelOrderToCustomer($uid, $server_id, $remark, $order ?? [], $keyboard);
            return;
        }
        if (isXuiPanel($server_id)) {
            resendXuiPanelOrderToCustomer(
                $uid,
                $server_id,
                $remark,
                $order ?? [],
                $keyboard,
                $fid
            );
            return;
        }
        deliverPanelOrder($uid, $server_id, $remark, $keyboard, $fid, (int) ($order['inbound_id'] ?? 0));
    }

    /** @param array<string, mixed> $payInfo */
    private static function createAndDeliverUserApiOrder(
        string $payHash,
        array $payInfo,
        int $uid,
        int $fid,
        int $server_id,
        string $serverType,
        int $inbound_id,
        string $remark,
        string $protocol,
        int $expire_date,
        int $eachPrice,
        int $date,
        int $rahgozar,
        string $keyboard,
        $panelResponse
    ): void {
        $serverConfigRow = getServerInfoById($server_id);
        $delivery = SubscriptionDelivery::preparePurchaseDelivery($serverConfigRow, $serverType, $remark, $panelResponse, '', 0);
        if (empty($delivery['subLink']) && $serverType === 'pasarguard') {
            usleep(500000);
            $delivery = SubscriptionDelivery::preparePurchaseDelivery($serverConfigRow, $serverType, $remark, $panelResponse, '', 0);
        }
        self::persistOrder(
            $payHash,
            $uid,
            $delivery['token'],
            $fid,
            $server_id,
            $inbound_id,
            $remark,
            $delivery['uniqid'],
            $protocol,
            $expire_date,
            $delivery['vray_link'],
            $eachPrice,
            $date,
            $rahgozar,
            (int) ($payInfo['agent_bought'] ?? 0)
        );
        deliverUserApiPanelPurchaseToCustomer(
            $uid,
            $server_id,
            $serverType,
            $remark,
            $panelResponse,
            $protocol,
            0,
            0,
            $keyboard
        );
    }

    /** @param array<string, mixed> $payInfo */
    private static function createAndDeliverXuiOrder(
        string $payHash,
        array $payInfo,
        int $uid,
        int $fid,
        int $server_id,
        int $inbound_id,
        string $remark,
        string $protocol,
        int $expire_date,
        int $eachPrice,
        int $date,
        int $rahgozar,
        string $keyboard
    ): void {
        $delivery = prepareXuiOrderDelivery($server_id, $remark, $fid, $inbound_id);
        if (empty($delivery['subLink'])) {
            usleep(500000);
            $delivery = prepareXuiOrderDelivery($server_id, $remark, $fid, $inbound_id);
        }
        self::persistOrder(
            $payHash,
            $uid,
            $delivery['token'],
            $fid,
            $server_id,
            $inbound_id,
            $remark,
            $delivery['uniqid'],
            $protocol,
            $expire_date,
            $delivery['vray_link'],
            $eachPrice,
            $date,
            $rahgozar,
            (int) ($payInfo['agent_bought'] ?? 0)
        );
        deliverXuiPanelOrderToCustomer($uid, $server_id, $remark, $keyboard, $fid, $inbound_id, $delivery);
    }

    /** @param array<string, mixed> $payInfo */
    private static function buildRemark(array $payInfo, string $srvRemark, int $uid): string
    {
        global $botState;
        if (($botState['remark'] ?? '') === 'manual') {
            return (string) ($payInfo['description'] ?? '');
        }
        return buildOrderRemarkFromPay($payInfo, $srvRemark, $uid);
    }

    private static function nextPort(string $portType): int
    {
        $savedinfo = explode('-', (string) file_get_contents(__DIR__ . '/../settings/temp.txt'));
        $port = ((int) ($savedinfo[0] ?? 0)) + 1;
        $last_num = ((int) ($savedinfo[1] ?? 0)) + 1;
        if ($portType === 'auto') {
            file_put_contents(__DIR__ . '/../settings/temp.txt', $port . '-' . $last_num);
            return $port;
        }
        return rand(1111, 65000);
    }

    /** @param array<string, mixed> $payInfo @return array{ok:bool} */
    private static function completeExistingPanelClient(
        string $payHash,
        array $payInfo,
        int $uid,
        int $fid,
        int $server_id,
        int $inbound_id,
        string $remark,
        string $protocol,
        int $expire_date,
        int $eachPrice,
        int $date,
        int $rahgozar,
        string $keyboard
    ): array {
        $existingOrder = getOrderByPayHash($payHash);
        if ($existingOrder) {
            $serverType = (string) (self::loadServerConfig($server_id)['type'] ?? '');
            self::deliverOrderToCustomer($uid, $server_id, $serverType, $remark, $existingOrder, $keyboard, $fid);
            return ['ok' => true];
        }

        $service = getXuiV3Service($server_id);
        $targetIds = syncPlanInboundIdsWithPanel($fid, $server_id);
        if (empty($targetIds) && $inbound_id > 0) {
            $targetIds = [$inbound_id];
        }
        if (!empty($targetIds)) {
            withPanelWriteLock(function () use ($service, $remark, $targetIds) {
                $service->attachMissingInboundsOnce($remark, $targetIds);
            });
        }

        self::createAndDeliverXuiOrder(
            $payHash,
            $payInfo,
            $uid,
            $fid,
            $server_id,
            $inbound_id,
            $remark,
            $protocol,
            $expire_date,
            $eachPrice,
            $date,
            $rahgozar,
            $keyboard
        );

        return ['ok' => true];
    }

    /** @param array<string, mixed> $payInfo @return array{ok:bool} */
    private static function completeExistingUserApiClient(
        string $payHash,
        array $payInfo,
        int $uid,
        int $fid,
        int $server_id,
        string $serverType,
        int $inbound_id,
        string $remark,
        string $protocol,
        int $expire_date,
        int $eachPrice,
        int $date,
        int $rahgozar,
        string $keyboard
    ): array {
        $existingOrder = getOrderByPayHash($payHash);
        if ($existingOrder) {
            self::deliverOrderToCustomer($uid, $server_id, $serverType, $remark, $existingOrder, $keyboard, $fid);
            return ['ok' => true];
        }

        $user = getUserApiPanelUser($server_id, $remark);
        if (!is_object($user)) {
            return ['ok' => false];
        }

        $links = getUserApiPanelLinks($server_id, $remark);
        $panelResponse = (object) [
            'sub_link' => (string) ($user->subscription_url ?? ''),
            'vray_links' => $links,
        ];

        self::createAndDeliverUserApiOrder(
            $payHash,
            $payInfo,
            $uid,
            $fid,
            $server_id,
            $serverType,
            $inbound_id,
            $remark,
            $protocol,
            $expire_date,
            $eachPrice,
            $date,
            $rahgozar,
            $keyboard,
            $panelResponse
        );

        return ['ok' => true];
    }

    private static function persistOrder(
        string $payHash,
        int $uid,
        string $token,
        int $fid,
        int $server_id,
        int $inbound_id,
        string $remark,
        string $uniqid,
        string $protocol,
        int $expire_date,
        string $vray_link,
        int $eachPrice,
        int $date,
        int $rahgozar,
        int $agent_bought
    ): void {
        if (getOrderByPayHash($payHash)) {
            return;
        }
        global $connection;
        $stmt = $connection->prepare(
            "INSERT INTO `orders_list`
            (`userid`, `token`, `transid`, `fileid`, `server_id`, `inbound_id`, `remark`, `uuid`, `protocol`, `expire_date`, `link`, `amount`, `status`, `date`, `notif`, `rahgozar`, `agent_bought`)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, 0, ?, ?)"
        );
        $stmt->bind_param(
            'issiiisssisiiii',
            $uid,
            $token,
            $payHash,
            $fid,
            $server_id,
            $inbound_id,
            $remark,
            $uniqid,
            $protocol,
            $expire_date,
            $vray_link,
            $eachPrice,
            $date,
            $rahgozar,
            $agent_bought
        );
        $stmt->execute();
        $stmt->close();
    }

    /** @param array<string, mixed> $file_detail */
    private static function decrementCapacity(array $file_detail, int $accountCount, int $server_id, int $fid): void
    {
        global $connection;
        if (!planHasInbounds($file_detail)) {
            $stmt = $connection->prepare('UPDATE `server_info` SET `ucount` = `ucount` - ? WHERE `id`=?');
            $stmt->bind_param('ii', $accountCount, $server_id);
            $stmt->execute();
            $stmt->close();
            return;
        }
        $stmt = $connection->prepare('UPDATE `server_plans` SET `acount` = `acount` - ? WHERE id=?');
        $stmt->bind_param('ii', $accountCount, $fid);
        $stmt->execute();
        $stmt->close();
    }

    /** @param array<string, mixed> $payInfo @param array<string, mixed> $file_detail */
    private static function notifyAfterPurchase(array $payInfo, array $file_detail, string $remark, int $price, int $uid): void
    {
        global $connection, $admin, $from_id, $mainValues;

        $stmt = $connection->prepare('SELECT * FROM `users` WHERE `userid`=?');
        $stmt->bind_param('i', $uid);
        $stmt->execute();
        $user_detail = $stmt->get_result()->fetch_assoc();
        $stmt->close();
        if (!$user_detail) {
            return;
        }

        if (!empty($user_detail['refered_by'])) {
            ReferralService::onReferralPurchase($uid);
        }

        if ($admin != $from_id) {
            $msg = str_replace(
                ['USER-ID', 'USERNAME', 'NAME', 'PRICE', 'REMARK', 'FILENAME'],
                [$uid, $user_detail['username'] ?? '', $user_detail['name'] ?? '', $price, $remark, $file_detail['title'] ?? ''],
                $mainValues['invite_buy_new_account']
            );
            sendMessage($msg, null, null, $admin);
        }
    }

    /** @param array<string, mixed> $payInfo */
    private static function notifyAdminConfigSent(array $payInfo, string $remark, int $volume, int $days): void
    {
        global $mainValues, $admin, $from_id;

        $adminChat = !empty($payInfo['chat_id']) ? $payInfo['chat_id'] : ($from_id ?: $admin);
        if (empty($adminChat)) {
            return;
        }

        sendMessage(
            str_replace(['REMARK', 'VOLUME', 'DAYS'], [$remark, $volume, $days], $mainValues['sent_config_to_user']),
            null,
            'HTML',
            $adminChat
        );
    }

    /** @param array<string, mixed> $payInfo */
    private static function markAdminDone(?array $payInfo = null): void
    {
        global $markup;

        if ($payInfo && !empty($payInfo['message_id']) && !empty($payInfo['chat_id'])) {
            editKeys(
                json_encode(['inline_keyboard' => [[['text' => '✅', 'callback_data' => 'wizwizch']]]]),
                (int) $payInfo['message_id'],
                $payInfo['chat_id']
            );
            return;
        }

        if (!is_array($markup) || $markup === []) {
            return;
        }
        unset($markup[count($markup) - 1]);
        $markup[] = [['text' => '✅', 'callback_data' => 'wizwizch']];
        editKeys(json_encode(['inline_keyboard' => array_values($markup)], 488));
    }

    /** @return array<string, mixed>|null */
    private static function loadPlan(int $fid): ?array
    {
        global $connection;
        $stmt = $connection->prepare('SELECT * FROM `server_plans` WHERE `id`=?');
        $stmt->bind_param('i', $fid);
        $stmt->execute();
        $row = $stmt->get_result()->fetch_assoc();
        $stmt->close();
        return $row ?: null;
    }

    /** @return array<string, mixed>|null */
    private static function loadServerInfo(int $server_id): ?array
    {
        global $connection;
        $stmt = $connection->prepare('SELECT * FROM `server_info` WHERE `id`=?');
        $stmt->bind_param('i', $server_id);
        $stmt->execute();
        $row = $stmt->get_result()->fetch_assoc();
        $stmt->close();
        return $row ?: null;
    }

    /** @return array<string, mixed>|null */
    private static function loadServerConfig(int $server_id): ?array
    {
        global $connection;
        $stmt = $connection->prepare('SELECT * FROM `server_config` WHERE `id`=?');
        $stmt->bind_param('i', $server_id);
        $stmt->execute();
        $row = $stmt->get_result()->fetch_assoc();
        $stmt->close();
        return $row ?: null;
    }
}
