<?php

// --- Function setSettings ---
function setSettings($field, $value)
{
    global $connection, $botState;
    $botState[$field] = $value;

    $stmt = $connection->prepare("SELECT * FROM `setting` WHERE `type` = 'BOT_STATES'");
    $stmt->execute();
    $isExists = $stmt->get_result();
    $stmt->close();
    if ($isExists->num_rows > 0)
        $query = "UPDATE `setting` SET `value` = ? WHERE `type` = 'BOT_STATES'";
    else
        $query = "INSERT INTO `setting` (`type`, `value`) VALUES ('BOT_STATES', ?)";
    $newData = json_encode($botState);

    $stmt = $connection->prepare($query);
    $stmt->bind_param("s", $newData);
    $stmt->execute();
    $stmt->close();
}

// --- Function getRejectedAgentList ---
function getRejectedAgentList()
{
    global $connection, $mainValues, $buttonValues;

    $stmt = $connection->prepare("SELECT * FROM `users` WHERE `is_agent` = 2");
    $stmt->execute();
    $list = $stmt->get_result();
    $stmt->close();

    if ($list->num_rows > 0) {
        $keys = array();
        $keys[] = [['text' => "آزاد ساختن", 'callback_data' => "NetFreedomVPN"], ['text' => "اسم کاربر", 'callback_data' => 'NetFreedomVPN'], ['text' => "آیدی عددی", 'callback_data' => "NetFreedomVPN"]];
        while ($row = $list->fetch_assoc()) {
            $userId = $row['userid'];

            $userDetail = bot('getChat', ['chat_id' => $userId])->result;
            $fullName = $userDetail->first_name . " " . $userDetail->last_name;

            $keys[] = [['text' => "✅", 'callback_data' => "releaseRejectedAgent" . $userId], ['text' => $fullName, 'callback_data' => "NetFreedomVPN"], ['text' => $userId, 'callback_data' => "NetFreedomVPN"]];
        }
        $keys[] = [['text' => $buttonValues['back_button'], 'callback_data' => "managePanel"]];
        return json_encode(['inline_keyboard' => $keys]);
    }
    else
        return null;
}

// --- Function getAgentDetails ---
function getAgentDetails($userId)
{
    global $connection, $mainVAlues, $buttonValues;

    $stmt = $connection->prepare("SELECT * FROM `users` WHERE `userid` = ? AND `is_agent` = 1");
    $stmt->bind_param("i", $userId);
    $stmt->execute();
    $agentDetail = $stmt->get_result();
    $stmt->close();


    $today = strtotime("today");
    $yesterday = strtotime("yesterday");
    $lastWeek = strtotime("last week");
    $lastMonth = strtotime("last month");

    $stmt = $connection->prepare("SELECT COUNT(`id`) AS `count`, SUM(`amount`) AS `total` FROM `orders_list` WHERE `date` >= ? AND `agent_bought` = 1 AND `userid` = ?");

    $stmt->bind_param("ii", $today, $userId);
    $stmt->execute();
    $todayIncome = $stmt->get_result()->fetch_assoc();

    $stmt->bind_param("ii", $yesterday, $userId);
    $stmt->execute();
    $yesterdayIncome = $stmt->get_result()->fetch_assoc();

    $stmt->bind_param("ii", $lastWeek, $userId);
    $stmt->execute();
    $lastWeekIncome = $stmt->get_result()->fetch_assoc();

    $stmt->bind_param("ii", $lastMonth, $userId);
    $stmt->execute();
    $lastMonthIncome = $stmt->get_result()->fetch_assoc();

    $stmt->close();


    return json_encode(['inline_keyboard' => [
            [
                ['text' => "(" . $todayIncome['count'] . ") " . number_format($todayIncome['total']), 'callback_data' => 'NetFreedomVPN'],
                ['text' => "درآمد امروز", 'callback_data' => 'NetFreedomVPN']
            ],
            [
                ['text' => "(" . $yesterdayIncome['count'] . ") " . number_format($yesterdayIncome['total']), 'callback_data' => "NetFreedomVPN"],
                ['text' => "درآمد دیروز", 'callback_data' => "NetFreedomVPN"]
            ],
            [
                ['text' => "(" . $lastWeekIncome['count'] . ") " . number_format($lastWeekIncome['total']), 'callback_data' => "NetFreedomVPN"],
                ['text' => "درآمد یک هفته", 'callback_data' => "NetFreedomVPN"]
            ],
            [
                ['text' => "(" . $lastMonthIncome['count'] . ") " . number_format($lastMonthIncome['total']), 'callback_data' => "NetFreedomVPN"],
                ['text' => "درآمد یک ماه", 'callback_data' => "NetFreedomVPN"]
            ],
            [['text' => $buttonValues['back_button'], 'callback_data' => "agentsList"]]
        ]]);
}

// --- Function checkSpam ---
function checkSpam()
{
    global $connection, $from_id, $userInfo, $admin;

    cleanupExpiredGifts();

    if ($userInfo != null && $from_id != $admin) {
        $rawSpamInfo = isset($userInfo['spam_info']) ? (string)$userInfo['spam_info'] : '{}';
        $spamInfo = json_decode($rawSpamInfo, true) ?: array();
        $spamDate = isset($spamInfo['date']) ? $spamInfo['date'] : 0;
        if (isset($spamInfo['banned'])) {
            if (time() <= $spamInfo['banned'])
                return $spamInfo['banned'];
        }

        if (time() <= $spamDate)
            $spamInfo['count'] += 1;
        else {
            $spamInfo['count'] = 1;
            $spamInfo['date'] = strtotime("+1 minute");
        }
        if ($spamInfo['count'] >= 50) {
            $spamInfo['banned'] = strtotime("+1 day");
        }
        $spamInfo = json_encode($spamInfo);

        $stmt = $connection->prepare("UPDATE `users` SET `spam_info` = ? WHERE `userid` = ?");
        $stmt->bind_param("si", $spamInfo, $from_id);
        $stmt->execute();
        $stmt->close();
    }
    else
        return null;
}

// --- Function getAgentsList ---
function getAgentsList($offset = 0)
{
    global $connection, $mainValues, $buttonValues;
    $limit = 15;

    $stmt = $connection->prepare("SELECT * FROM `users` WHERE `is_agent` = 1 LIMIT ? OFFSET ?");
    $stmt->bind_param('ii', $limit, $offset);
    $stmt->execute();
    $agentList = $stmt->get_result();
    $stmt->close();

    $keys = array();
    if ($agentList->num_rows == 0 && $offset == 0)
        return null;

    $keys[] = [['text' => "حذف", 'callback_data' => "NetFreedomVPN"], ['text' => "درصد تخفیف", 'callback_data' => "NetFreedomVPN"], ['text' => "تاریخ نمایندگی", 'callback_data' => "NetFreedomVPN"], ['text' => "اسم نماینده", 'callback_data' => "NetFreedomVPN"], ['text' => "آیدی عددی", 'callback_data' => "NetFreedomVPN"]];
    if ($agentList->num_rows > 0) {
        while ($row = $agentList->fetch_assoc()) {
            $userId = $row['userid'];

            $userDetail = bot('getChat', ['chat_id' => $userId])->result;
            $userUserName = $userDetail->username;
            $fullName = trim(($userDetail->first_name ?? "") . " " . ($userDetail->last_name ?? ""));
            $joinedDate = jdate("Y-m-d H:i", $row['agent_date']);

            $keys[] = [['text' => "❌", 'callback_data' => "removeAgent" . $userId], ['text' => "⚙️", 'callback_data' => "agentPercentDetails" . $userId], ['text' => $joinedDate, 'callback_data' => "NetFreedomVPN"], ['text' => $fullName, 'callback_data' => "agentDetails" . $userId], ['text' => $userId, 'callback_data' => "agentDetails" . $userId]];
        }
    }
    if ($offset == 0 && $limit <= $agentList->num_rows)
        $keys[] = [
            ['text' => " »» صفحه بعدی »»", 'callback_data' => "nextAgentList" . ($offset + $limit)]
        ];
    elseif ($limit <= $agentList->num_rows)
        $keys[] = [
            ['text' => " »» صفحه بعدی »»", 'callback_data' => "nextAgentList" . ($offset + $limit)],
            ['text' => " «« صفحه قبلی ««", 'callback_data' => "nextAgentList" . ($offset - $limit)]
        ];
    elseif ($offset != 0)
        $keys[] = [
            ['text' => " «« صفحه قبلی ««", 'callback_data' => "nextAgentList" . ($offset - $limit)]
        ];

    $keys[] = [['text' => $buttonValues['back_button'], 'callback_data' => "managePanel"]];
    return json_encode(['inline_keyboard' => $keys]);
}

// --- Function getAgentDiscounts ---
function getAgentDiscounts($agentId)
{
    global $connection, $mainValues, $buttonValues, $botState;

    $stmt = $connection->prepare("SELECT * FROM `users` WHERE `is_agent` = 1 AND `userid` = ?");
    $stmt->bind_param("i", $agentId);
    $stmt->execute();
    $agentInfo = $stmt->get_result()->fetch_assoc();
    $stmt->close();
    $keys = array();

    $discounts = json_decode($agentInfo['discount_percent'], true);

    $normal = $discounts['normal'];
    $keys[] = [['text' => " ", 'callback_data' => "NetFreedomVPN"],
        ['text' => $normal . "%", 'callback_data' => "editAgentDiscountNormal" . $agentId . "_0"],
        ['text' => "عمومی", 'callback_data' => "NetFreedomVPN"]];

    if ($botState['agencyPlanDiscount'] == "on") {
        foreach ($discounts['plans'] as $planId => $discount) {
            $stmt = $connection->prepare("SELECT * FROM `server_plans` WHERE `id` = ?");
            $stmt->bind_param('i', $planId);
            $stmt->execute();
            $info = $stmt->get_result()->fetch_assoc();
            $stmt->close();

            $stmt = $connection->prepare("SELECT * FROM `server_categories` WHERE `id` = ?");
            $stmt->bind_param("i", $info['catid']);
            $stmt->execute();
            $catInfo = $stmt->get_result()->fetch_assoc();
            $stmt->close();

            $keys[] = [['text' => "❌", 'callback_data' => "removePercentOfAgentPlan" . $agentId . "_" . $planId],
                ['text' => $discount . "%", 'callback_data' => "editAgentDiscountPlan" . $agentId . "_" . $planId],
                ['text' => $info['title'] . " " . $catInfo['title'], 'callback_data' => "NetFreedomVPN"]];
        }
    }
    else {
        $serversList = (isset($discounts['servers']) && is_array($discounts['servers'])) ? $discounts['servers'] : [];
        foreach ($serversList as $serverId => $discount) {
            $stmt = $connection->prepare("SELECT * FROM `server_info` WHERE `id` = ?");
            $stmt->bind_param('i', $serverId);
            $stmt->execute();
            $info = $stmt->get_result()->fetch_assoc();
            $stmt->close();

            $keys[] = [['text' => "❌", 'callback_data' => "removePercentOfAgentServer" . $agentId . "_" . $serverId],
                ['text' => $discount . "%", 'callback_data' => "editAgentDiscountServer" . $agentId . "_" . $serverId],
                ['text' => $info['title'], 'callback_data' => "NetFreedomVPN"]];
        }
    }
    if ($botState['agencyPlanDiscount'] == "on")
        $keys[] = [['text' => "افزودن تخفیف پلن", 'callback_data' => "addDiscountPlanAgent" . $agentId]];
    else
        $keys[] = [['text' => "افزودن تخفیف سرور", 'callback_data' => "addDiscountServerAgent" . $agentId]];
    $keys[] = [['text' => $buttonValues['back_button'], 'callback_data' => "agentsList"]];
    return json_encode(['inline_keyboard' => $keys]);
}

// --- Function RandomString ---
function RandomString($count = 9, $type = "all")
{
    $characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456789';
    if ($type == "all")
        $characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456789';
    elseif ($type == "small")
        $characters = 'abcdef123456789';
    elseif ($type == "domain")
        $characters = 'abcdefghijklmnopqrstuvwxyz';

    $randstring = null;
    for ($i = 0; $i < $count; $i++) {
        $randstring .= $characters[
            rand(0, strlen($characters) - 1)
            ];
    }
    return $randstring;
}

// --- Function generateUID ---
function generateUID()
{
    $randomString = openssl_random_pseudo_bytes(16);
    $time_low = bin2hex(substr($randomString, 0, 4));
    $time_mid = bin2hex(substr($randomString, 4, 2));
    $time_hi_and_version = bin2hex(substr($randomString, 6, 2));
    $clock_seq_hi_and_reserved = bin2hex(substr($randomString, 8, 2));
    $node = bin2hex(substr($randomString, 10, 6));

    $time_hi_and_version = hexdec($time_hi_and_version);
    $time_hi_and_version = $time_hi_and_version >> 4;
    $time_hi_and_version = $time_hi_and_version | 0x4000;

    $clock_seq_hi_and_reserved = hexdec($clock_seq_hi_and_reserved);
    $clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved >> 2;
    $clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved | 0x8000;

    return sprintf('%08s-%04s-%04x-%04x-%012s', $time_low, $time_mid, $time_hi_and_version, $clock_seq_hi_and_reserved, $node);
}

// --- Function checkStep ---
function checkStep($table)
{
    global $connection;
    $stmt = null;

    if ($table == "server_plans")
        $stmt = $connection->prepare("SELECT * FROM `server_plans` WHERE `active` = 0");
    if ($table == "server_categories")
        $stmt = $connection->prepare("SELECT * FROM `server_categories` WHERE `active` = 0");

    $stmt->execute();
    $res = $stmt->get_result()->fetch_assoc();
    $stmt->close();
    return $res['step'];
}

// --- Function setUser ---
function setUser($value = 'none', $field = 'step')
{
    global $connection, $from_id, $username, $first_name, $userInfo;

    $stmt = $connection->prepare("SELECT * FROM `users` WHERE `userid`=?");
    $stmt->bind_param("i", $from_id);
    $stmt->execute();
    $uinfo = $stmt->get_result();
    $stmt->close();


    if ($uinfo->num_rows == 0) {
        $stmt = $connection->prepare("INSERT INTO `users` (`userid`, `name`, `username`, `refcode`, `wallet`, `date`)
                            VALUES (?,?,?, 0,0,?)");
        $time = time();
        $stmt->bind_param("issi", $from_id, $first_name, $username, $time);
        $stmt->execute();
        $stmt->close();
    }

    if ($field == "wallet")
        $stmt = $connection->prepare("UPDATE `users` SET `wallet` = ? WHERE `userid` = ?");
    elseif ($field == "phone")
        $stmt = $connection->prepare("UPDATE `users` SET `phone` = ? WHERE `userid` = ?");
    elseif ($field == "refered_by")
        $stmt = $connection->prepare("UPDATE `users` SET `refered_by` = ? WHERE `userid` = ?");
    elseif ($field == "step")
        $stmt = $connection->prepare("UPDATE `users` SET `step` = ? WHERE `userid` = ?");
    elseif ($field == "freetrial")
        $stmt = $connection->prepare("UPDATE `users` SET `freetrial` = ? WHERE `userid` = ?");
    elseif ($field == "isAdmin")
        $stmt = $connection->prepare("UPDATE `users` SET `isAdmin` = ? WHERE `userid` = ?");
    elseif ($field == "first_start")
        $stmt = $connection->prepare("UPDATE `users` SET `first_start` = ? WHERE `userid` = ?");
    elseif ($field == "temp")
        $stmt = $connection->prepare("UPDATE `users` SET `temp` = ? WHERE `userid` = ?");
    elseif ($field == "is_agent")
        $stmt = $connection->prepare("UPDATE `users` SET `is_agent` = ? WHERE `userid` = ?");
    elseif ($field == "discount_percent")
        $stmt = $connection->prepare("UPDATE `users` SET `discount_percent` = ? WHERE `userid` = ?");
    elseif ($field == "agent_date")
        $stmt = $connection->prepare("UPDATE `users` SET `agent_date` = ? WHERE `userid` = ?");
    elseif ($field == "spam_info")
        $stmt = $connection->prepare("UPDATE `users` SET `spam_info` = ? WHERE `userid` = ?");
    elseif ($field == "name")
        $stmt = $connection->prepare("UPDATE `users` SET `name` = ? WHERE `userid` = ?");

    $stmt->bind_param("si", $value, $from_id);
    $stmt->execute();
    $stmt->close();
    if (is_array($userInfo)) {
        $userInfo[$field] = $value;
    }
}

// --- Function generateRandomString ---
function generateRandomString($length, $protocol)
{
    return ($protocol == 'trojan') ? substr(md5(time()), 5, 15) : generateUID();
}

// --- Function addBorderImage ---
function addBorderImage($add)
{
    if (!file_exists($add)) return;
    $im = @ImageCreateFromPNG($add);
    if ($im === false) return;
    $border = 30;
    $width = ImageSx($im);
    $height = ImageSy($im);
    $img_adj_width = $width + 2 * $border;
    $img_adj_height = $height + 2 * $border;
    $newimage = imagecreatetruecolor($img_adj_width, $img_adj_height);
    $border_color = imagecolorallocate($newimage, 255, 255, 255);
    imagefilledrectangle($newimage, 0, 0, $img_adj_width, $img_adj_height, $border_color);
    imageCopyResized($newimage, $im, $border, $border, 0, 0, $width, $height, $width, $height);
    ImagePNG($newimage, $add, 5);
    imagedestroy($im);
    imagedestroy($newimage);
}

// --- Function sumerize ---
function sumerize($amount)
{
    $gb = $amount / (1024 * 1024 * 1024);
    if ($gb > 1) {
        return round($gb, 2) . " گیگابایت";
    }
    else {
        $gb *= 1024;
        return round($gb, 2) . " مگابایت";
    }

}

// --- Function sumerize2 ---
function sumerize2($amount)
{
    $gb = $amount / (1024 * 1024 * 1024);
    return round($gb, 2);
}

function wizwiz_getPlanSummaryTxt($d)
{
    global $connection;
    $t = "📋 <b>مشخصات پلن در حال ساخت:</b>\n\n";
    if (isset($d['title'])) $t .= "▪️ عنوان پلن: <code>{$d['title']}</code>\n";
    if (isset($d['price'])) $t .= "▪️ قیمت پلن: <code>" . number_format((float)$d['price']) . " تومان</code>\n";
    if (isset($d['cat_name'])) $t .= "▪️ دسته بندی: <code>{$d['cat_name']}</code>\n";
    if (isset($d['server_name'])) $t .= "▪️ سرور میزبان: <code>{$d['server_name']}</code>\n";
    if (isset($d['limitip'])) {
        $ipTxt = ($d['limitip'] == 0) ? "نامحدود ♾" : "{$d['limitip']} کاربره";
        $t .= "▪️ محدودیت کاربر: <code>{$ipTxt}</code>\n";
    }
    if (isset($d['acount'])) {
        $accTxt = ($d['acount'] == 0) ? "نامحدود ♾" : "{$d['acount']} عدد";
        $t .= "▪️ تعداد اکانت مجاز: <code>{$accTxt}</code>\n";
    }
    return $t . "---------------------------------------\n";
}

function cleanupExpiredGifts() {
    global $connection;
    $time = time() - (2 * 86400); // ۲ روز بعد از انقضا حذف شود
    $stmt = $connection->prepare("SELECT * FROM `orders_list` WHERE `status` = 1 AND `expire_date` > 0 AND `expire_date` < ? AND (`remark` LIKE 'Gift-%' OR `remark` LIKE 'agency(Gift)-%')");
    if ($stmt) {
        $stmt->bind_param("i", $time);
        $stmt->execute();
        $expiredGifts = $stmt->get_result();
        $stmt->close();

        while ($row = $expiredGifts->fetch_assoc()) {
            $id = $row['id'];
            $server_id = $row['server_id'];
            $uuid = $row['uuid'];
            $remark = $row['remark'];
            $inbound_id = $row['inbound_id'];

            $stmt_srv = $connection->prepare("SELECT `type` FROM `server_config` WHERE `id` = ?");
            if ($stmt_srv) {
                $stmt_srv->bind_param("i", $server_id);
                $stmt_srv->execute();
                $serverTypeRow = $stmt_srv->get_result()->fetch_assoc();
                $stmt_srv->close();

                if ($serverTypeRow) {
                    $serverType = $serverTypeRow['type'];
                    if ($serverType == 'marzban') {
                        if (function_exists('deleteMarzban')) {
                            deleteMarzban($server_id, $remark);
                        }
                    } else {
                        if (function_exists('deleteClient')) {
                            deleteClient($server_id, $inbound_id, $uuid, 1);
                        }
                    }
                }
            }

            $stmt_up = $connection->prepare("UPDATE `orders_list` SET `status` = 0 WHERE `id` = ?");
            if ($stmt_up) {
                $stmt_up->bind_param("i", $id);
                $stmt_up->execute();
                $stmt_up->close();
            }
        }
    }
}

// --- Function getXuiSqliteConnection ---
function getXuiSqliteConnection()
{
    $paths = [
        '/etc/x-ui/x-ui.db',
        '/etc/x-ui-3x/x-ui.db',
        '/usr/local/x-ui/db/x-ui.db',
        '/db/x-ui.db'
    ];
    foreach ($paths as $path) {
        if (file_exists($path)) {
            try {
                $conn = new PDO("sqlite:" . $path);
                $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                return $conn;
            } catch (Exception $e) {
                error_log("SQLite connection failed for path $path: " . $e->getMessage());
            }
        }
    }
    return null;
}

// --- Function syncUserTrafficFromSqlite ---
function syncUserTrafficFromSqlite($tgId)
{
    global $connection;
    $db = getXuiSqliteConnection();
    if (!$db) {
        return false;
    }

    try {
        $pattern = "Client-" . $tgId . "-%";
        $stmt = $db->prepare("SELECT * FROM `client_traffics` WHERE `email` LIKE :pattern");
        $stmt->execute([':pattern' => $pattern]);
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

        if (empty($rows)) {
            return false;
        }

        foreach ($rows as $row) {
            $email = $row['email'];
            $enable = intval($row['enable']);
            $up = floatval($row['up']);
            $down = floatval($row['down']);
            $total = floatval($row['total']);
            $expiryTime = floatval($row['expiry_time']);

            $remark = str_replace('@tg.com', '', $email);
            $expireDateSec = ($expiryTime > 0) ? floor($expiryTime / 1000) : 0;

            $stmtMysql = $connection->prepare("UPDATE `orders_list` SET `status` = ?, `expire_date` = ? WHERE `remark` = ?");
            if ($stmtMysql) {
                $stmtMysql->bind_param("iis", $enable, $expireDateSec, $remark);
                $stmtMysql->execute();
                $stmtMysql->close();
            }
        }
        return true;
    } catch (Exception $e) {
        error_log("SQLite sync error for user $tgId: " . $e->getMessage());
        return false;
    }
}

// --- Function syncUserTraffic ---
function syncUserTraffic($tgId = null)
{
    global $connection;
    
    // حذف کانفیگ‌های قدیمی‌تر از ۶ ماه از دیتابیس ربات
    $sixMonthsAgo = time() - (6 * 30 * 86400);
    $connection->query("DELETE FROM `orders_list` WHERE `expire_date` > 0 AND `expire_date` < $sixMonthsAgo");
    
    // همگام‌سازی از طریق پایگاه داده محلی SQLite در صورت وجود شناسه عددی
    if ($tgId !== null) {
        syncUserTrafficFromSqlite($tgId);
    }

    // واکشی تمام سرورهای فعال جهت سینک از طریق API پنل سنایی
    $serversRes = $connection->query("SELECT * FROM `server_config`");
    if (!$serversRes) {
        return false;
    }

    while ($server = $serversRes->fetch_assoc()) {
        $serverType = $server['type'] ?? 'sanaei';
        if ($serverType == 'marzban') {
            continue;
        }

        $clients = [];

        // ۱. تلاش برای دریافت از لیست کلاینت‌های سراسری پنل سنایی
        if (function_exists('callXuiApi')) {
            $list = callXuiApi($server, '/panel/api/clients/list');
            if ($list && isset($list->success) && $list->success && isset($list->obj)) {
                foreach ($list->obj as $c) {
                    $email = is_object($c) ? ($c->email ?? '') : ($c['email'] ?? '');
                    if (empty($email)) continue;
                    
                    $clients[$email] = [
                        'email' => $email,
                        'tgId' => is_object($c) ? (isset($c->tgId) ? (int)$c->tgId : 0) : (isset($c['tgId']) ? (int)$c['tgId'] : 0),
                        'enable' => is_object($c) ? (isset($c->enable) ? ($c->enable ? 1 : 0) : 1) : (isset($c['enable']) ? ($c['enable'] ? 1 : 0) : 1),
                        'expiryTime' => is_object($c) ? (isset($c->expiryTime) ? floatval($c->expiryTime) : 0) : (isset($c['expiryTime']) ? floatval($c['expiryTime']) : 0),
                        'uuid' => is_object($c) ? ($c->uuid ?? ($c->password ?? '')) : ($c['uuid'] ?? ($c['password'] ?? '')),
                        'totalGB' => is_object($c) ? ($c->totalGB ?? 0) : ($c['totalGB'] ?? 0),
                        'limitIp' => is_object($c) ? ($c->limitIp ?? 0) : ($c['limitIp'] ?? 0),
                        'flow' => is_object($c) ? ($c->flow ?? '') : ($c['flow'] ?? ''),
                        'subId' => is_object($c) ? ($c->subId ?? '') : ($c['subId'] ?? ''),
                        'comment' => is_object($c) ? ($c->comment ?? '') : ($c['comment'] ?? ''),
                        'password' => is_object($c) ? ($c->password ?? null) : ($c['password'] ?? null),
                        'groupName' => is_object($c) ? ($c->groupName ?? ($c->group_name ?? ($c->group ?? ''))) : ($c['groupName'] ?? ($c['group_name'] ?? ($c['group'] ?? '')))
                    ];
                }
            }
        }

        // ۲. واکشی اطلاعات ورودی‌ها (Inbounds) برای پشتیبانی از سایر پنل‌ها و ادغام داده‌ها
        if (function_exists('getJson')) {
            $xuiRes = getJson($server['id']);
            if ($xuiRes && isset($xuiRes->success) && $xuiRes->success && isset($xuiRes->obj)) {
                foreach ($xuiRes->obj as $inbound) {
                    $inbound_id = $inbound->id;
                    $settings = json_decode($inbound->settings ?? '{}');
                    $clientStats = $inbound->clientStats ?? [];
                    if (!isset($settings->clients)) continue;

                    foreach ($settings->clients as $c) {
                        $email = is_object($c) ? ($c->email ?? '') : ($c['email'] ?? '');
                        if (empty($email)) continue;

                        $uuid = is_object($c) ? ($c->id ?? ($c->password ?? ($c->uuid ?? ''))) : ($c['id'] ?? ($c['password'] ?? ($c['uuid'] ?? '')));
                        $enable = is_object($c) ? (isset($c->enable) ? ($c->enable ? 1 : 0) : 1) : (isset($c['enable']) ? ($c['enable'] ? 1 : 0) : 1);
                        $expiryTime = is_object($c) ? (isset($c->expiryTime) ? floatval($c->expiryTime) : 0) : (isset($c['expiryTime']) ? floatval($c['expiryTime']) : 0);
                        $tgIdFromClient = is_object($c) ? (isset($c->tgId) ? (int)$c->tgId : 0) : (isset($c['tgId']) ? (int)$c['tgId'] : 0);

                        // بررسی کلاینت استتس برای فعال بودن و زمان انقضا
                        foreach ($clientStats as $stat) {
                            $statEmail = is_object($stat) ? ($stat->email ?? '') : ($stat['email'] ?? '');
                            if ($statEmail == $email) {
                                $statExpiryTime = is_object($stat) ? ($stat->expiryTime ?? 0) : ($stat['expiryTime'] ?? 0);
                                if ($statExpiryTime > 0 && $expiryTime == 0) {
                                    $expiryTime = floatval($statExpiryTime);
                                }
                                if (is_object($stat) && isset($stat->enable)) {
                                    $enable = $stat->enable ? 1 : 0;
                                } elseif (is_array($stat) && isset($stat['enable'])) {
                                    $enable = $stat['enable'] ? 1 : 0;
                                }
                                break;
                            }
                        }

                        if (!isset($clients[$email])) {
                            $clients[$email] = [
                                'email' => $email,
                                'tgId' => $tgIdFromClient,
                                'enable' => $enable,
                                'expiryTime' => $expiryTime,
                                'uuid' => $uuid,
                                'inbound_id' => $inbound_id,
                                'totalGB' => is_object($c) ? ($c->totalGB ?? 0) : ($c['totalGB'] ?? 0),
                                'limitIp' => is_object($c) ? ($c->limitIp ?? 0) : ($c['limitIp'] ?? 0),
                                'flow' => is_object($c) ? ($c->flow ?? '') : ($c['flow'] ?? ''),
                                'subId' => is_object($c) ? ($c->subId ?? '') : ($c['subId'] ?? ''),
                                'comment' => is_object($c) ? ($c->comment ?? '') : ($c['comment'] ?? ''),
                                'password' => is_object($c) ? ($c->password ?? null) : ($c['password'] ?? null),
                                'groupName' => is_object($c) ? ($c->groupName ?? ($c->group_name ?? ($c->group ?? ''))) : ($c['groupName'] ?? ($c['group_name'] ?? ($c['group'] ?? '')))
                            ];
                        }
                    }
                }
            }
        }

        // ۳. پردازش و همگام‌سازی کلاینت‌ها با دیتابیس ربات
        foreach ($clients as $email => $client) {
            $tgIdFromClient = $client['tgId'];
            
            // تطبیق نام کاربری با الگوهای مختلف (مانند Client-6076792583-1234 یا Ramtinmehraz-64054150)
            $parsedTgId = 0;
            if (preg_match('/^(?:[a-zA-Z]+-)?(\d+)(?:-|$|@)/i', $email, $matches)) {
                $parsedTgId = (int)$matches[1];
            }

            $targetTgId = ($tgIdFromClient > 0) ? $tgIdFromClient : $parsedTgId;

            if ($tgId !== null && intval($targetTgId) !== intval($tgId)) {
                continue;
            }

            if ($targetTgId <= 0) {
                continue;
            }

            $enable = $client['enable'];
            $expiryTime = $client['expiryTime'];
            $expireDateSec = ($expiryTime > 0) ? floor($expiryTime / 1000) : 0;
            $uuid = $client['uuid'];

            // بررسی وجود رکورد در دیتابیس بر اساس uuid یا token/subId
            $orderExists = false;
            $orderId = 0;
            $existingDate = '';
            $subId = $client['subId'] ?? '';
            $cleanRemark = str_replace('@tg.com', '', $email);
            
            $existingUserid = '';
            if (!empty($uuid) || !empty($subId)) {
                $checkStmt = $connection->prepare("SELECT `id`, `date`, `userid` FROM `orders_list` WHERE (`uuid` = ? AND `uuid` != '') OR (`token` = ? AND `token` != '')");
                $checkStmt->bind_param("ss", $uuid, $subId);
                $checkStmt->execute();
                $checkRes = $checkStmt->get_result()->fetch_assoc();
                $checkStmt->close();
                if ($checkRes) {
                    $orderExists = true;
                    $orderId = $checkRes['id'];
                    $existingDate = $checkRes['date'] ?? '';
                    $existingUserid = $checkRes['userid'] ?? '';
                }
            }

            // فال‌بک: اگر با uuid/token پیدا نشد، با ری‌مارک کلاینت بررسی شود
            if (!$orderExists && !empty($cleanRemark)) {
                $checkStmt = $connection->prepare("SELECT `id`, `date`, `userid` FROM `orders_list` WHERE `remark` = ? AND `server_id` = ?");
                $checkStmt->bind_param("si", $cleanRemark, $server['id']);
                $checkStmt->execute();
                $checkRes = $checkStmt->get_result()->fetch_assoc();
                $checkStmt->close();
                if ($checkRes) {
                    $orderExists = true;
                    $orderId = $checkRes['id'];
                    $existingDate = $checkRes['date'] ?? '';
                    $existingUserid = $checkRes['userid'] ?? '';
                }
            }

            if (($targetTgId <= 0 || empty($targetTgId)) && !empty($existingUserid) && $existingUserid != '0') {
                $targetTgId = $existingUserid;
            }

            // واکشی لینک‌های کانفیگ به صورت آرایه از پنل سنایی
            $subLink = '';
            $configLinks = [];
            $linksResponse = callXuiApi($server, '/panel/api/clients/links/' . urlencode($email));
            if (is_object($linksResponse) && isset($linksResponse->success) && $linksResponse->success && is_array($linksResponse->obj)) {
                $configLinks = $linksResponse->obj;
            }
            if (!empty($configLinks)) {
                $subLink = json_encode($configLinks, JSON_UNESCAPED_SLASHES);
            } elseif (!empty($subId)) {
                $parsed = parse_url($server['panel_url']);
                $scheme = $parsed['scheme'] ?? 'https';
                $host = $parsed['host'] ?? $server['panel_url'];
                $host = str_replace(['http://', 'https://', '/'], '', $host);
                $subLink = "$scheme://$host:2096/sub/$subId";
            }

            $currDate = time();
            if ($orderExists) {
                // خودترمیمی ستون تاریخ در صورتی که به فرمت متنی ثبت شده باشد
                if (!empty($existingDate)) {
                    if (!is_numeric($existingDate)) {
                        $parsedTime = strtotime($existingDate);
                        $currDate = ($parsedTime !== false) ? $parsedTime : time();
                    } else {
                        $currDate = intval($existingDate);
                    }
                }
                
                // آپدیت دیتابیس ربات (پر کردن مقادیر ناقص سرور، اینباند، یوآی‌دی، ریمارک، لینک و توکن بر اساس مقادیر پنل)
                $fileid = 8;
                $inbound_id = 1;
                $stmtMysql = $connection->prepare("UPDATE `orders_list` SET `expire_date` = ?, `userid` = ?, `status` = ?, `uuid` = ?, `token` = ?, `link` = ?, `remark` = ?, `fileid` = ?, `inbound_id` = ?, `date` = ? WHERE `id` = ?");
                if ($stmtMysql) {
                    $stmtMysql->bind_param("issssssiiii", $expireDateSec, $targetTgId, $enable, $uuid, $subId, $subLink, $cleanRemark, $fileid, $inbound_id, $currDate, $orderId);
                    $stmtMysql->execute();
                    $stmtMysql->close();
                }
            } else {
                // اگر وجود نداشت، در دیتابیس درج شود
                $currDate = time();
                
                // مقادیر پیش‌فرض طبق درخواست کاربر
                $inbound_id = 1; 
                $fileid = 8;     
                $token = $subId;
                $status = 1;     
                
                // تشخیص نماینده بودن خرید
                $agentBought = 0;
                if (stripos($email, 'agency') !== false || stripos($email, 'agent') !== false || ($client['groupName'] ?? '') == 'agency') {
                    $agentBought = 1;
                }

                $stmtInsert = $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 (?, ?, '', ?, ?, ?, ?, ?, 'vless/vmess/trojan', ?, ?, 0, ?, ?, 0, 0, ?)");
                if ($stmtInsert) {
                    $stmtInsert->bind_param("ssiiissisiii", $targetTgId, $token, $fileid, $server['id'], $inbound_id, $cleanRemark, $uuid, $expireDateSec, $subLink, $status, $currDate, $agentBought);
                    $stmtInsert->execute();
                    $stmtInsert->close();
                }
            }

            // ۴. خودترمیمی (Self-healing) دسته‌بندی کلاینت یا رفع Telegram User ID صفر در پنل
            if (function_exists('determineClientGroup')) {
                $expectedGroup = determineClientGroup($email);
                $currentGroup = $client['groupName'];
                $currentTgId = (int)($client['tgId'] ?? 0);
                
                if (empty($currentGroup) || $currentGroup !== $expectedGroup || $currentTgId === 0) {
                    $postData = [
                        "email" => $email,
                        "totalGB" => floatval($client['totalGB']),
                        "expiryTime" => floatval($client['expiryTime']),
                        "tgId" => (int)$targetTgId,
                        "limitIp" => intval($client['limitIp']),
                        "enable" => $enable ? true : false,
                        "id" => $uuid,
                        "flow" => $client['flow'],
                        "subId" => $client['subId'],
                        "comment" => $client['comment'],
                        "group_name" => $expectedGroup,
                        "groupName" => $expectedGroup,
                        "group" => $expectedGroup
                    ];
                    if ($client['password'] !== null) {
                        $postData['password'] = $client['password'];
                    }
                    callXuiApi($server, '/panel/api/clients/update/' . urlencode($email), 'POST', $postData);
                }
            }
        }

        // حذف کانفیگ‌های اشتباه ایجاد شده (کانفیگ‌هایی که در پنل این سرور وجود ندارند)
        $dbConfigs = [];
        $getDbConfigs = $connection->prepare("SELECT `id`, `remark`, `uuid`, `token` FROM `orders_list` WHERE `server_id` = ?");
        if ($getDbConfigs) {
            $getDbConfigs->bind_param("i", $server['id']);
            $getDbConfigs->execute();
            $dbConfigsRes = $getDbConfigs->get_result();
            while ($dbRow = $dbConfigsRes->fetch_assoc()) {
                $dbConfigs[] = $dbRow;
            }
            $getDbConfigs->close();
        }
        foreach ($dbConfigs as $dbConfig) {
            $dbRemark = $dbConfig['remark'];
            $dbUuid = $dbConfig['uuid'];
            $dbToken = $dbConfig['token'];
            
            $foundInPanel = false;
            foreach ($clients as $email => $client) {
                $panelRemark = str_replace('@tg.com', '', $email);
                if ($dbRemark === $panelRemark || $dbRemark === $email) {
                    $foundInPanel = true;
                    break;
                }
                if (!empty($dbUuid) && (($client['uuid'] ?? '') === $dbUuid || ($client['subId'] ?? '') === $dbUuid)) {
                    $foundInPanel = true;
                    break;
                }
                if (!empty($dbToken) && (($client['uuid'] ?? '') === $dbToken || ($client['subId'] ?? '') === $dbToken)) {
                    $foundInPanel = true;
                    break;
                }
            }
            if (!$foundInPanel) {
                $delStmt = $connection->prepare("DELETE FROM `orders_list` WHERE `id` = ?");
                if ($delStmt) {
                    $delStmt->bind_param("i", $dbConfig['id']);
                    $delStmt->execute();
                    $delStmt->close();
                }
            }
        }
    }
    return true;
}

// --- Function sendNewMemberNotification ---
function sendNewMemberNotification($userId, $name, $username)
{
    global $connection, $admin, $buttonValues, $mainValues;
    if (intval($userId) == intval($admin)) {
        return;
    }

    $stmt = $connection->prepare("SELECT `join_notified` FROM `users` WHERE `userid` = ?");
    if ($stmt) {
        $stmt->bind_param("s", $userId);
        $stmt->execute();
        $res = $stmt->get_result()->fetch_assoc();
        $stmt->close();
        if ($res && intval($res['join_notified']) === 1) {
            return;
        }
    }

    $stmt = $connection->prepare("UPDATE `users` SET `join_notified` = 1 WHERE `userid` = ?");
    if ($stmt) {
        $stmt->bind_param("s", $userId);
        $stmt->execute();
        $stmt->close();
    }

    $keys = json_encode(['inline_keyboard' => [
        [['text' => $buttonValues['send_message_to_user'] ?? 'ارسال پیام به کاربر', 'callback_data' => 'sendMessageToUser' . $userId]]
    ]]);
    $fullNameHtml = "<a href='tg://user?id={$userId}'>" . htmlspecialchars($name) . "</a>";
    $usernameVal = !empty($username) ? str_replace('@', '', $username) : "بدون_یوزرنیم";
    $userIdCode = "<code>{$userId}</code>";
    $newJoinedMsg = str_replace(["FULLNAME", "USERNAME", "USERID"], [$fullNameHtml, $usernameVal, $userIdCode], $mainValues['new_member_joined'] ?? "📢 | یه گل جدید عضو ربات شد :\nنام و نام خانوادگی: FULLNAME\nنام کاربری: @USERNAME\nآیدی عددی: USERID");
    
    sendMessage($newJoinedMsg, $keys, "HTML", $admin);
}

/**
 * ایجاد و ارسال فایل خروجی .npvt مخصوص نرم‌افزار NapsternetV برای کاربر
 * 
 * @param string|array $configLinks لینک یا آرایه‌ای از لینک‌های کانفیگ
 * @param string $remark نام کانفیگ / نام فایل
 * @param int|string $targetUserId آیدی عددی کاربر تلگرام
 */
function sendNpvtDocument($configLinks, $remark, $targetUserId, $subLink = null) {
    if (empty($configLinks) && empty($subLink)) {
        return;
    }
    if (empty($targetUserId)) {
        return;
    }

    $linksArray = [];
    if (is_array($configLinks)) {
        $linksArray = array_values(array_filter($configLinks));
    } elseif (!empty($configLinks)) {
        $linksArray = [trim((string)$configLinks)];
    }

    $configName = !empty($remark) ? $remark : "NetFreedom-Config";
    $cleanRemark = preg_replace('/[^\w\-\.]+/u', '_', $configName);
    if (empty($cleanRemark)) {
        $cleanRemark = "config";
    }

    // محتوای متنی استاندارد جهت ایمپورت مستقیم در نرم‌افزارهای V2Ray / NapsternetV
    $fileContent = "=== NetFreedom Subscription & Configs ===\n\n";
    if (!empty($subLink)) {
        $fileContent .= "🌐 Subscription URL:\n" . $subLink . "\n\n";
    }
    if (!empty($linksArray)) {
        $fileContent .= "🔗 Direct Config Links:\n" . implode("\n\n", $linksArray) . "\n";
    }

    $tempDir = sys_get_temp_dir();
    $filePath = $tempDir . '/' . $cleanRemark . '.txt';

    file_put_contents($filePath, $fileContent);

    if (file_exists($filePath)) {
        $docFile = new CURLFile($filePath, 'text/plain', $cleanRemark . '.txt');
        $caption = "📄 <b>فایل متنی کانفیگ‌ها و لینک اشتراک</b>\n\n" .
                   "📌 <b>راهنمای اتصال در NapsternetV:</b>\n" .
                   "۱. لینک Subscription بالا یا داخل فایل را کپی کنید.\n" .
                   "۲. در برنامه NapsternetV روی ➕ بالای صفحه بزنید.\n" .
                   "۳. گزینه <b>Add Subscription Url</b> را انتخاب کرده و لینک را قرار دهید.";
        
        bot('sendDocument', [
            'chat_id' => $targetUserId,
            'document' => $docFile,
            'caption' => $caption,
            'parse_mode' => 'HTML'
        ]);

        @unlink($filePath);
    }
}


