<?php

/*
|--------------------------------------------------------------------------
| VIOLET ANTI-SPAM BOT
| Optimized Callback / Settings Edition
| PHP 7.4+
|--------------------------------------------------------------------------
*/

ini_set('display_errors', '0');
ini_set('display_startup_errors', '0');
error_reporting(E_ALL);
date_default_timezone_set('Asia/Tehran');

/*
|--------------------------------------------------------------------------
| CONFIG
|--------------------------------------------------------------------------
*/

define('BOT_TOKEN', '8998947098:AAHg2ncev7bhRchoTk6rCzKZHOKpeWbaiK0');
define('OWNER_ID', 8298437636);
define('DB_HOST', 'localhost');
define('DB_NAME', 'odarair1_spam');
define('DB_USER', 'odarair1_nothing');
define('DB_PASS', 'mohsenM2230570@');
define('BOT_NAME', 'ویولت');

/*
|--------------------------------------------------------------------------
| DATABASE
|--------------------------------------------------------------------------
*/

try {
    $pdo = new PDO(
        'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8mb4',
        DB_USER,
        DB_PASS,
        array(
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
            PDO::ATTR_PERSISTENT => false
        )
    );
    installDatabase($pdo);
} catch (Throwable $e) {
    error_log('[DB] ' . $e->getMessage());
    http_response_code(500);
    exit('Database Error');
}

/*
|--------------------------------------------------------------------------
| DATABASE INSTALL
|--------------------------------------------------------------------------
*/

function installDatabase($pdo)
{
    $pdo->exec("
        CREATE TABLE IF NOT EXISTS settings (
            id INT UNSIGNED NOT NULL AUTO_INCREMENT,
            chat_id BIGINT NOT NULL,
            is_active TINYINT(1) NOT NULL DEFAULT 0,
            expire_time BIGINT NOT NULL DEFAULT 0,
            group_owner_id BIGINT NULL,
            flood_limit INT NOT NULL DEFAULT 5,
            flood_window INT NOT NULL DEFAULT 3,
            word_filter_enabled TINYINT(1) NOT NULL DEFAULT 0,
            link_filter_enabled TINYINT(1) NOT NULL DEFAULT 0,
            max_warnings INT NOT NULL DEFAULT 4,
            member_mute_minutes INT NOT NULL DEFAULT 5,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            UNIQUE KEY unique_chat (chat_id)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    ");
    $pdo->exec("
        CREATE TABLE IF NOT EXISTS users (
            user_id BIGINT NOT NULL,
            chat_id BIGINT NOT NULL,
            warn_count INT NOT NULL DEFAULT 0,
            muted_until BIGINT NOT NULL DEFAULT 0,
            admin_clean_until BIGINT NOT NULL DEFAULT 0,
            PRIMARY KEY (user_id, chat_id)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    ");
    $pdo->exec("
        CREATE TABLE IF NOT EXISTS messages (
            id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
            user_id BIGINT NOT NULL,
            chat_id BIGINT NOT NULL,
            message_id BIGINT NOT NULL,
            created_at BIGINT NOT NULL,
            PRIMARY KEY (id),
            INDEX flood_index (user_id, chat_id, created_at),
            INDEX cleanup_index (chat_id, created_at)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    ");
    $pdo->exec("
        CREATE TABLE IF NOT EXISTS forbidden_words (
            chat_id BIGINT NOT NULL,
            word VARCHAR(191) NOT NULL,
            PRIMARY KEY (chat_id, word)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    ");
}

/*
|--------------------------------------------------------------------------
| TELEGRAM API
|--------------------------------------------------------------------------
*/

function telegram($method, $data = array())
{
    $url = 'https://api.telegram.org/bot' . BOT_TOKEN . '/' . $method;
    $ch = curl_init($url);
    curl_setopt_array($ch, array(
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query($data),
        CURLOPT_CONNECTTIMEOUT => 2,
        CURLOPT_TIMEOUT => 5,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2,
        CURLOPT_HTTPHEADER => array('Content-Type: application/x-www-form-urlencoded')
    ));
    $result = curl_exec($ch);
    $error = curl_error($ch);
    $httpCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    if ($error) {
        error_log('[Telegram][' . $method . '] ' . $error);
        return array('ok' => false, 'description' => $error, 'http_code' => $httpCode);
    }
    $json = json_decode((string)$result, true);
    if (!is_array($json)) {
        return array('ok' => false, 'description' => 'Invalid Telegram response', 'http_code' => $httpCode);
    }
    return $json;
}

/*
|--------------------------------------------------------------------------
| READ UPDATE
|--------------------------------------------------------------------------
*/

$raw = file_get_contents('php://input');
$update = json_decode($raw ?: '', true);
if (!is_array($update)) {
    exit('OK');
}

/*
|--------------------------------------------------------------------------
| CALLBACK
|--------------------------------------------------------------------------
*/

if (isset($update['callback_query'])) {
    $bot = new VioletAntiSpam($pdo, $update);
    $bot->handleCallback();
    exit('OK');
}

/*
|--------------------------------------------------------------------------
| MESSAGE
|--------------------------------------------------------------------------
*/

if (!isset($update['message'])) {
    exit('OK');
}
$bot = new VioletAntiSpam($pdo, $update);
$bot->run();
exit('OK');

/*
|--------------------------------------------------------------------------
| MAIN CLASS
|--------------------------------------------------------------------------
*/

class VioletAntiSpam
{
    private $pdo;
    private $update;
    private $message;
    private $chatId = 0;
    private $userId = 0;
    private $text = '';
    private $role = 'member';
    private $settings = array();
    private $settingsLoaded = false;
    private $groupCreator = 0;
    private $groupCreatorLoaded = false;
    private $botId = 0;
    private $roleCache = array();
    const ADMIN_MUTE_MINUTES = 2;

    public function __construct($pdo, $update)
    {
        $this->pdo = $pdo;
        $this->update = $update;
        if (isset($update['message'])) {
            $this->message = $update['message'];
            $this->chatId = (int)($this->message['chat']['id'] ?? 0);
            $this->userId = (int)($this->message['from']['id'] ?? 0);
            $this->text = trim((string)($this->message['text'] ?? ''));
        }
    }

    public function run()
    {
        if (!$this->chatId || !$this->userId) {
            return;
        }
        $chatType = $this->message['chat']['type'] ?? '';
        if (!in_array($chatType, array('group', 'supergroup'), true)) {
            return;
        }
        if (!empty($this->message['from']['is_bot'])) {
            return;
        }

        if ($this->userId === OWNER_ID) {
            if ($this->isActivationCommand($this->text)) {
                $minutes = $this->getActivationMinutes($this->text);
                if ($minutes > 0) {
                    $this->activate($minutes);
                } else {
                    $this->send("❌ <b>مدت فعال‌سازی نامعتبر است.</b>\n\nمثال:\n<code>فعال سازی اسپم ویولت 3000</code>");
                }
                return;
            }
            if (preg_match('/^تمدید\s*(\d+)$/u', $this->text, $m)) {
                $this->prepareSettings();
                $this->extend((int)$m[1]);
                return;
            }
            if ($this->normalizeText($this->text) === $this->normalizeText('غیرفعال سازی اسپم ویولت')) {
                $this->prepareSettings();
                $this->deactivate();
                return;
            }
            if ($this->text === 'ربات اسپم ویولت' || $this->text === 'پنل ویولت') {
                $this->prepareSettings();
                $this->role = 'creator';
                $this->showOwnerPanel();
                return;
            }
        }

        if ($this->text === 'تنظیمات اسپم') {
            $this->prepareSettings();
            $this->role = $this->userId === OWNER_ID ? 'creator' : $this->getUserRole($this->userId);
            if ($this->canUseSettings()) {
                $this->showSettingsPanel();
            } else {
                $this->send("⛔ <b>دسترسی ندارید.</b>\n\nاین بخش فقط برای مدیران مجاز گروه و مالک ربات است.");
            }
            return;
        }
        if ($this->text === 'راهنمای اسپم') {
            $this->showHelp();
            return;
        }

        $this->prepareSettings();

        if ($this->botWasAdded()) {
            $this->sendWelcome();
            return;
        }

        $this->role = ($this->userId === OWNER_ID) ? 'creator' : $this->getUserRole($this->userId);

        if (!$this->isActive()) {
            return;
        }

        if ($this->role === 'creator') {
            if ($this->text === 'حذف سکوت') {
                $this->unmuteFromReply();
                return;
            }
            if ($this->text === 'حذف اخطار') {
                $this->clearWarningsFromReply();
                return;
            }
        }
        if ($this->isGroupOwner()) {
            return;
        }

        if ($this->role === 'member' && $this->isMuted($this->userId)) {
            $this->deleteCurrentMessage();
            return;
        }

        if ($this->role === 'administrator' && $this->isAdminPending($this->userId)) {
            $this->deleteCurrentMessage();
            return;
        }

        $reason = $this->detectSpam();
        if ($reason !== null) {
            $this->punish($reason);
        }
    }

    private function isActivationCommand($text)
    {
        return (bool)preg_match('/^فعال\s*[-‌]?\s*سازی\s+اسپم\s+ویولت\s+(\d+)$/u', trim($text));
    }

    private function getActivationMinutes($text)
    {
        if (preg_match('/^فعال\s*[-‌]?\s*سازی\s+اسپم\s+ویولت\s+(\d+)$/u', trim($text), $m)) {
            return (int)$m[1];
        }
        return 0;
    }

    private function normalizeText($text)
    {
        $text = str_replace(array('ي', 'ى', 'ك', '‌'), array('ی', 'ی', 'ک', ''), $text);
        return preg_replace('/\s+/u', ' ', trim($text));
    }

    private function prepareSettings()
    {
        $this->settings = $this->getSettings();
        $this->settingsLoaded = true;
    }

    public function handleCallback()
    {
        $callback = $this->update['callback_query'] ?? array();
        $fromId = (int)($callback['from']['id'] ?? 0);
        $data = (string)($callback['data'] ?? '');
        $callbackId = (string)($callback['id'] ?? '');
        $message = $callback['message'] ?? array();
        $chatId = (int)($message['chat']['id'] ?? 0);

        if ($callbackId !== '') {
            $this->answerCallback($callbackId, '');
        }
        if (!$chatId) {
            return;
        }
        $this->chatId = $chatId;
        $this->userId = $fromId;

        if (strpos($data, 'owner|') === 0) {
            if ($fromId !== OWNER_ID) {
                $this->answerCallback($callbackId, '⛔ فقط مالک ربات دسترسی دارد.', true);
                return;
            }
            $this->role = 'creator';
            $this->handleOwnerCallback($callbackId, $data, $message);
            return;
        }

        if (strpos($data, 'settings|') === 0) {
            $this->role = ($fromId === OWNER_ID) ? 'creator' : $this->getUserRole($fromId);
            if (!$this->canUseSettings()) {
                $this->answerCallback($callbackId, '⛔ دسترسی ندارید.', true);
                return;
            }
            $this->handleSettingsCallback($callbackId, $data, $message);
            return;
        }

        if (strpos($data, 'admin|') === 0) {
            if ($fromId !== OWNER_ID) {
                $this->answerCallback($callbackId, '⛔ فقط مالک ربات می‌تواند تصمیم بگیرد.', true);
                return;
            }
            $this->role = 'creator';
            $this->handleAdminCallback($callbackId, $data, $message);
            return;
        }
    }

    private function handleOwnerCallback($callbackId, $data, $message)
    {
        $parts = explode('|', $data);
        $action = $parts[1] ?? '';
        switch ($action) {
            case 'panel':
                $this->settingsLoaded = false;
                $this->settings = array();
                $this->editOwnerPanel($message);
                break;
            case 'activate':
                $minutes = (int)($parts[2] ?? 0);
                if ($minutes <= 0) {
                    $this->answerCallback($callbackId, '⛔ زمان نامعتبر است.', true);
                    return;
                }
                $this->activate($minutes, true);
                $this->answerCallback($callbackId, '🟢 ربات فعال شد.');
                $this->editOwnerPanel($message);
                break;
            case 'deactivate':
                $this->deactivate(true);
                $this->answerCallback($callbackId, '🔴 ربات خاموش شد.');
                $this->editOwnerPanel($message);
                break;
            case 'add':
                $minutes = (int)($parts[2] ?? 0);
                $this->addTime($minutes);
                $this->answerCallback($callbackId, '➕ زمان اضافه شد.');
                $this->editOwnerPanel($message);
                break;
            case 'sub':
                $minutes = (int)($parts[2] ?? 0);
                $this->subtractTime($minutes);
                $this->answerCallback($callbackId, '➖ زمان کم شد.');
                $this->editOwnerPanel($message);
                break;
            case 'refresh':
                $this->settingsLoaded = false;
                $this->settings = array();
                $this->answerCallback($callbackId, '🔄 بروزرسانی شد.');
                $this->editOwnerPanel($message);
                break;
            case 'settings':
                $this->answerCallback($callbackId, '⚙️ تنظیمات');
                $this->editSettingsPanel($message);
                break;
            case 'help':
                $this->answerCallback($callbackId, '📖 راهنما');
                $this->editHelpPanel($message);
                break;
            case 'close':
                $this->answerCallback($callbackId, 'بسته شد.');
                $this->editText($message, '🤖 <b>پنل ویولت بسته شد.</b>');
                break;
        }
    }

    private function handleAdminCallback($callbackId, $data, $message)
    {
        $parts = explode('|', $data);
        $action = $parts[1] ?? '';
        $chatId = (int)($parts[2] ?? 0);
        $userId = (int)($parts[3] ?? 0);
        if (!$chatId || !$userId) {
            $this->answerCallback($callbackId, '❌ اطلاعات ناقص است.', true);
            return;
        }
        $this->chatId = $chatId;
        $role = $this->getUserRole($userId);
        if ($role === 'creator') {
            $this->clearAdminPending($userId);
            $this->answerCallback($callbackId, '⛔ مالک گروه قابل مجازات نیست.', true);
            return;
        }
        if ($role !== 'administrator') {
            $this->clearAdminPending($userId);
            $this->answerCallback($callbackId, 'ℹ️ این کاربر دیگر ادمین نیست.', true);
            return;
        }
        if ($action === 'mute') {
            $ok = $this->mute($userId, self::ADMIN_MUTE_MINUTES);
            $this->clearAdminPending($userId);
            if ($ok) {
                $this->answerCallback($callbackId, '🔇 ادمین ۲ دقیقه سکوت شد.');
                $this->editText($message, "🔇 <b>مجازات ادمین اعمال شد.</b>\n\n⏱ مدت سکوت: <b>۲ دقیقه</b>\n👤 آیدی: <code>{$userId}</code>");
            } else {
                $this->answerCallback($callbackId, '❌ سکوت انجام نشد.', true);
            }
            return;
        }
        if ($action === 'muteban') {
            $muteOk = $this->mute($userId, self::ADMIN_MUTE_MINUTES);
            $banOk = $this->ban($userId);
            $this->clearAdminPending($userId);
            if ($banOk) {
                $this->answerCallback($callbackId, '🔇🚫 سکوت + بن انجام شد.');
                $this->editText($message, "🔇🚫 <b>مجازات ادمین اعمال شد.</b>\n\n⏱ سکوت: <b>۲ دقیقه</b>\n🚫 سپس بن شد.\n👤 آیدی: <code>{$userId}</code>");
            } else {
                $this->answerCallback($callbackId, $muteOk ? '⚠️ سکوت انجام شد ولی بن ناموفق بود.' : '❌ عملیات ناموفق بود.', true);
            }
            return;
        }
        if ($action === 'ban') {
            $ok = $this->ban($userId);
            $this->clearAdminPending($userId);
            if ($ok) {
                $this->answerCallback($callbackId, '🚫 ادمین بن شد.');
                $this->editText($message, "🚫 <b>ادمین مستقیماً بن شد.</b>\n\n👤 آیدی: <code>{$userId}</code>");
            } else {
                $this->answerCallback($callbackId, '❌ بن انجام نشد.', true);
            }
            return;
        }
    }

    private function handleSettingsCallback($callbackId, $data, $message)
    {
        $parts = explode('|', $data);
        $action = $parts[1] ?? '';
        switch ($action) {
            case 'main':
                $this->editSettingsPanel($message);
                break;
            case 'flood':
                $this->editFloodPanel($message);
                break;
            case 'flood_set':
                $limit = max(2, min(100, (int)($parts[2] ?? 5)));
                $window = max(1, min(60, (int)($parts[3] ?? 3)));
                $this->updateSetting('flood_limit', $limit);
                $this->updateSetting('flood_window', $window);
                $this->answerCallback($callbackId, "🚦 {$limit} پیام / {$window} ثانیه");
                $this->editFloodPanel($message);
                break;
            case 'words':
                $current = !empty($this->getSettings()['word_filter_enabled']);
                $new = $current ? 0 : 1;
                $this->updateSetting('word_filter_enabled', $new);
                $this->answerCallback($callbackId, $new ? '🔤 ضدکلمات روشن شد.' : '🔤 ضدکلمات خاموش شد.');
                $this->editSettingsPanel($message);
                break;
            case 'links':
                $current = !empty($this->getSettings()['link_filter_enabled']);
                $new = $current ? 0 : 1;
                $this->updateSetting('link_filter_enabled', $new);
                $this->answerCallback($callbackId, $new ? '🔗 ضدلینک روشن شد.' : '🔗 ضدلینک خاموش شد.');
                $this->editSettingsPanel($message);
                break;
            case 'warnings':
                $value = max(2, min(10, (int)($parts[2] ?? 4)));
                $this->updateSetting('max_warnings', $value);
                $this->answerCallback($callbackId, "⚠️ سقف اخطار: {$value}");
                $this->editSettingsPanel($message);
                break;
            case 'mute':
                $value = max(1, min(60, (int)($parts[2] ?? 5)));
                $this->updateSetting('member_mute_minutes', $value);
                $this->answerCallback($callbackId, "🔇 سکوت اعضا: {$value} دقیقه");
                $this->editSettingsPanel($message);
                break;
            case 'words_list':
                $this->editWordsPanel($message);
                break;
            case 'help':
                $this->editHelpPanel($message);
                break;
            case 'back_owner':
                if ($this->userId === OWNER_ID) {
                    $this->editOwnerPanel($message);
                }
                break;
            case 'back':
                $this->editSettingsPanel($message);
                break;
        }
    }

    private function canUseSettings()
    {
        if ($this->userId === OWNER_ID) {
            return true;
        }
        return in_array($this->role, array('creator', 'administrator'), true);
    }

    private function showOwnerPanel()
    {
        if ($this->userId !== OWNER_ID) {
            return;
        }
        $this->send($this->ownerPanelText(), $this->ownerKeyboard());
    }

    private function editOwnerPanel($message)
    {
        $this->editText($message, $this->ownerPanelText(), $this->ownerKeyboard());
    }

    private function ownerPanelText()
    {
        $s = $this->getSettings();
        $active = $this->isSettingsActive($s);
        if ($active) {
            $remaining = max(0, (int)$s['expire_time'] - time());
            $status = '🟢 <b>فعال</b>';
            $time = '⏳ باقی‌مانده: <b>' . $this->humanTime($remaining) . '</b>';
        } else {
            $status = '🔴 <b>غیرفعال</b>';
            $time = '⏳ اشتراک فعال نیست.';
        }
        return "👑 <b>پنل مالک ربات ویولت</b>\n\n🤖 وضعیت: {$status}\n{$time}\n\n💡 این پنل فقط برای مالک اصلی ربات قابل استفاده است.\n\nاز دکمه‌های زیر برای مدیریت اشتراک و تنظیمات استفاده کنید.";
    }

    private function ownerKeyboard()
    {
        $s = $this->getSettings();
        $active = $this->isSettingsActive($s);
        return array(
            'inline_keyboard' => array(
                array(
                    array('text' => $active ? '🟢 فعال' : '🟢 فعال‌سازی', 'callback_data' => 'owner|activate|1440'),
                    array('text' => '🔴 خاموش', 'callback_data' => 'owner|deactivate')
                ),
                array(
                    array('text' => '➕ ۱ ساعت', 'callback_data' => 'owner|add|60'),
                    array('text' => '➕ ۱ روز', 'callback_data' => 'owner|add|1440'),
                    array('text' => '➕ ۷ روز', 'callback_data' => 'owner|add|10080')
                ),
                array(
                    array('text' => '➖ ۱ ساعت', 'callback_data' => 'owner|sub|60'),
                    array('text' => '➖ ۱ روز', 'callback_data' => 'owner|sub|1440')
                ),
                array(
                    array('text' => '⚙️ تنظیمات اسپم', 'callback_data' => 'owner|settings')
                ),
                array(
                    array('text' => '📖 راهنما', 'callback_data' => 'owner|help'),
                    array('text' => '🔄 بروزرسانی', 'callback_data' => 'owner|refresh')
                ),
                array(
                    array('text' => '✖️ بستن', 'callback_data' => 'owner|close')
                )
            )
        );
    }

    private function showSettingsPanel()
    {
        $s = $this->getSettings();
        $this->send($this->settingsText($s), $this->settingsKeyboard($s));
    }

    private function editSettingsPanel($message)
    {
        $s = $this->getSettings();
        $this->editText($message, $this->settingsText($s), $this->settingsKeyboard($s));
    }

    private function settingsText($s)
    {
        $active = $this->isSettingsActive($s) ? '🟢 روشن' : '🔴 خاموش';
        $words = !empty($s['word_filter_enabled']) ? '🟢 روشن' : '⚪ خاموش';
        $links = !empty($s['link_filter_enabled']) ? '🟢 روشن' : '⚪ خاموش';
        return "⚙️ <b>تنظیمات ضداسپم ویولت</b>\n\n🤖 وضعیت ربات: {$active}\n\n🚦 Flood:\n<b>{$s['flood_limit']} پیام</b> در <b>{$s['flood_window']} ثانیه</b>\n\n🔤 ضدکلمات: {$words}\n🔗 ضدلینک: {$links}\n\n⚠️ سقف اخطار: <b>{$s['max_warnings']}</b>\n🔇 سکوت اعضا: <b>{$s['member_mute_minutes']} دقیقه</b>\n\n🛡️ <b>ادمین‌ها</b>\nدر صورت اسپم، پیامشان حذف می‌شود و تا تصمیم مالک ربات، پیام‌های بعدی نیز حذف می‌شوند.\nدر صورت انتخاب Mute، مدت آن همیشه <b>۲ دقیقه</b> است.";
    }

    private function settingsKeyboard($s)
    {
        $words = !empty($s['word_filter_enabled']) ? '🔤 ضدکلمات: روشن' : '🔤 ضدکلمات: خاموش';
        $links = !empty($s['link_filter_enabled']) ? '🔗 ضدلینک: روشن' : '🔗 ضدلینک: خاموش';
        return array(
            'inline_keyboard' => array(
                array(
                    array('text' => '🚦 تنظیم Flood', 'callback_data' => 'settings|flood')
                ),
                array(
                    array('text' => $words, 'callback_data' => 'settings|words'),
                    array('text' => $links, 'callback_data' => 'settings|links')
                ),
                array(
                    array('text' => '⚠️ سقف اخطار', 'callback_data' => 'settings|warnings|4'),
                    array('text' => '🔇 مدت سکوت', 'callback_data' => 'settings|mute|5')
                ),
                array(
                    array('text' => '🔤 فهرست کلمات', 'callback_data' => 'settings|words_list')
                ),
                array(
                    array('text' => '📖 راهنمای کامل', 'callback_data' => 'settings|help')
                ),
                array(
                    array('text' => '🔄 بروزرسانی', 'callback_data' => 'settings|main')
                ),
                array(
                    array('text' => '👑 پنل مالک ربات', 'callback_data' => 'owner|panel')
                )
            )
        );
    }

    private function editFloodPanel($message)
    {
        $s = $this->getSettings();
        $text = "🚦 <b>تنظیم Flood</b>\n\nهر گزینه یعنی حداکثر تعداد پیام در بازه مشخص.\n\nوضعیت فعلی:\n<b>{$s['flood_limit']} پیام</b> در <b>{$s['flood_window']} ثانیه</b>";
        $keyboard = array(
            'inline_keyboard' => array(
                array(
                    array('text' => '3 پیام / 3 ثانیه', 'callback_data' => 'settings|flood_set|3|3'),
                    array('text' => '5 پیام / 3 ثانیه', 'callback_data' => 'settings|flood_set|5|3')
                ),
                array(
                    array('text' => '5 پیام / 5 ثانیه', 'callback_data' => 'settings|flood_set|5|5'),
                    array('text' => '8 پیام / 5 ثانیه', 'callback_data' => 'settings|flood_set|8|5')
                ),
                array(
                    array('text' => '10 پیام / 5 ثانیه', 'callback_data' => 'settings|flood_set|10|5'),
                    array('text' => '15 پیام / 10 ثانیه', 'callback_data' => 'settings|flood_set|15|10')
                ),
                array(
                    array('text' => '⬅️ بازگشت', 'callback_data' => 'settings|main')
                )
            )
        );
        $this->editText($message, $text, $keyboard);
    }

    private function editWordsPanel($message)
    {
        $stmt = $this->pdo->prepare('SELECT word FROM forbidden_words WHERE chat_id = ? ORDER BY word LIMIT 50');
        $stmt->execute(array($this->chatId));
        $words = $stmt->fetchAll(PDO::FETCH_COLUMN);
        if (!$words) {
            $list = '📭 <b>هنوز کلمه‌ای ثبت نشده.</b>';
        } else {
            $lines = array();
            foreach ($words as $i => $word) {
                $lines[] = ($i + 1) . '. ' . htmlspecialchars($word, ENT_QUOTES, 'UTF-8');
            }
            $list = implode("\n", $lines);
        }
        $text = "🔤 <b>کلمات ممنوع</b>\n\n{$list}\n\nبرای مدیریت کلمات:\n<code>افزودن کلمه کلمه</code>\n<code>حذف کلمه کلمه</code>";
        $keyboard = array(
            'inline_keyboard' => array(
                array(
                    array('text' => '🟢 ضدکلمات روشن/خاموش', 'callback_data' => 'settings|words')
                ),
                array(
                    array('text' => '⬅️ بازگشت', 'callback_data' => 'settings|main')
                )
            )
        );
        $this->editText($message, $text, $keyboard);
    }

    private function showHelp()
    {
        $this->send($this->helpText(), $this->helpKeyboard());
    }

    private function editHelpPanel($message)
    {
        $this->editText($message, $this->helpText(), $this->helpKeyboard());
    }

    private function helpText()
    {
        return "📖 <b>راهنمای ضداسپم ویولت</b>\n\n🚦 <b>Flood</b>\nتعداد پیام‌های سریع یک کاربر بررسی می‌شود. اگر از حد تنظیم‌شده عبور کند، اسپم محسوب می‌شود.\n\n🔤 <b>ضدکلمات</b>\nکلمات ممنوعه گروه را شناسایی و پیام متخلف را حذف می‌کند.\n\n🔗 <b>ضدلینک</b>\nارسال لینک‌های اینترنتی را شناسایی می‌کند.\n\n⚠️ <b>اخطار</b>\nکاربر عادی با تکرار تخلف اخطار دریافت می‌کند.\n\n🔇 <b>سکوت</b>\nبعد از رسیدن به مرحله مجازات، کاربر برای مدت تنظیم‌شده سکوت می‌شود.\n\n🛡️ <b>ادمین</b>\nادمین به‌صورت خودکار Mute نمی‌شود. پیامش حذف می‌شود و پیام‌های بعدی او نیز تا تصمیم مالک ربات حذف خواهند شد.\n\n🔇 <b>سکوت ادمین</b>\nاگر مالک ربات گزینه سکوت را انتخاب کند، ادمین دقیقاً <b>۲ دقیقه</b> سکوت می‌شود.\n\n👑 <b>مالک گروه</b>\nتنها مالک اصلی گروه می‌تواند سکوت را حذف کند یا اخطارها را پاک کند.\n\n👑 <b>مالک ربات</b>\nبا نوشتن <code>ربات اسپم ویولت</code> به پنل کامل مدیریت ربات دسترسی دارد.";
    }

    private function helpKeyboard()
    {
        return array(
            'inline_keyboard' => array(
                array(
                    array('text' => '⚙️ تنظیمات', 'callback_data' => 'settings|main')
                ),
                array(
                    array('text' => '⬅️ بازگشت', 'callback_data' => 'settings|main')
                )
            )
        );
    }

    private function botWasAdded()
    {
        if (!isset($this->message['new_chat_members'])) {
            return false;
        }
        $botId = $this->getBotId();
        foreach ($this->message['new_chat_members'] as $member) {
            if ((int)$member['id'] === $botId) {
                return true;
            }
        }
        return false;
    }

    private function sendWelcome()
    {
        $this->send(
            "🤖 <b>ربات ضداسپم ویولت</b>\n\n✅ با موفقیت به گروه اضافه شدم.\n\n⚠️ برای شروع، ابتدا دسترسی‌های مدیریتی لازم را به من بدهید.\n\n👑 مالک ربات برای مدیریت این گروه می‌تواند بنویسد:\n<code>ربات اسپم ویولت</code>\n\n⚙️ برای تنظیمات گروه:\n<code>تنظیمات اسپم</code>\n\n📖 برای مشاهده راهنما:\n<code>راهنمای اسپم</code>"
        );
    }

    private function getSettings()
    {
        if ($this->settingsLoaded && !empty($this->settings)) {
            return $this->settings;
        }
        if (!$this->chatId) {
            return array();
        }
        $stmt = $this->pdo->prepare('SELECT * FROM settings WHERE chat_id = ? LIMIT 1');
        $stmt->execute(array($this->chatId));
        $row = $stmt->fetch();
        if (!$row) {
            $creator = $this->getGroupCreator();
            $stmt = $this->pdo->prepare('INSERT INTO settings (chat_id, is_active, expire_time, group_owner_id) VALUES (?, 0, 0, ?)');
            $stmt->execute(array($this->chatId, $creator ?: null));
            $stmt = $this->pdo->prepare('SELECT * FROM settings WHERE chat_id = ? LIMIT 1');
            $stmt->execute(array($this->chatId));
            $row = $stmt->fetch();
        }
        if (!$row) {
            return array();
        }
        if (empty($row['group_owner_id'])) {
            $creator = $this->getGroupCreator();
            if ($creator) {
                $stmt = $this->pdo->prepare('UPDATE settings SET group_owner_id = ? WHERE chat_id = ?');
                $stmt->execute(array($creator, $this->chatId));
                $row['group_owner_id'] = $creator;
            }
        }
        $this->settings = $row;
        $this->settingsLoaded = true;
        return $this->settings;
    }

    private function updateSetting($key, $value)
    {
        $allowed = array('flood_limit', 'flood_window', 'word_filter_enabled', 'link_filter_enabled', 'max_warnings', 'member_mute_minutes');
        if (!in_array($key, $allowed, true)) {
            return;
        }
        $stmt = $this->pdo->prepare("UPDATE settings SET `$key` = ? WHERE chat_id = ?");
        $stmt->execute(array($value, $this->chatId));
        $this->settings[$key] = $value;
        $this->settingsLoaded = true;
    }

    private function isActive()
    {
        $s = $this->getSettings();
        if (!(int)$s['is_active']) {
            return false;
        }
        if ((int)$s['expire_time'] > 0 && (int)$s['expire_time'] <= time()) {
            $stmt = $this->pdo->prepare('UPDATE settings SET is_active = 0 WHERE chat_id = ?');
            $stmt->execute(array($this->chatId));
            $this->settings['is_active'] = 0;
            return false;
        }
        return true;
    }

    private function isSettingsActive($s)
    {
        return !empty($s['is_active']) && (empty($s['expire_time']) || (int)$s['expire_time'] > time());
    }

    private function activate($minutes, $silent = false)
    {
        $minutes = max(1, min(525600, (int)$minutes));
        $expire = time() + ($minutes * 60);
        $stmt = $this->pdo->prepare('UPDATE settings SET is_active = 1, expire_time = ? WHERE chat_id = ?');
        $stmt->execute(array($expire, $this->chatId));
        $this->settings['is_active'] = 1;
        $this->settings['expire_time'] = $expire;
        $this->settingsLoaded = true;
        if (!$silent) {
            $this->send("🟢 <b>ربات ویولت فعال شد.</b>\n\n⏳ مدت: <b>" . $this->humanTime($minutes * 60) . "</b>");
        }
    }

    private function extend($minutes)
    {
        $this->addTime($minutes);
        $this->send("🟢 <b>اشتراک ویولت تمدید شد.</b>\n\n➕ مدت اضافه‌شده: <b>" . $this->humanTime($minutes * 60) . "</b>");
    }

    private function deactivate($silent = false)
    {
        $stmt = $this->pdo->prepare('UPDATE settings SET is_active = 0 WHERE chat_id = ?');
        $stmt->execute(array($this->chatId));
        $this->settings['is_active'] = 0;
        $this->settingsLoaded = true;
        if (!$silent) {
            $this->send("🔴 <b>ضداسپم ویولت خاموش شد.</b>\n\n⚙️ تنظیمات گروه حذف نشده‌اند.");
        }
    }

    private function addTime($minutes)
    {
        $minutes = max(1, min(525600, (int)$minutes));
        $s = $this->getSettings();
        $base = max(time(), (int)$s['expire_time']);
        $newExpire = $base + ($minutes * 60);
        $stmt = $this->pdo->prepare('UPDATE settings SET is_active = 1, expire_time = ? WHERE chat_id = ?');
        $stmt->execute(array($newExpire, $this->chatId));
        $this->settings['is_active'] = 1;
        $this->settings['expire_time'] = $newExpire;
        $this->settingsLoaded = true;
    }

    private function subtractTime($minutes)
    {
        $minutes = max(1, min(525600, (int)$minutes));
        $s = $this->getSettings();
        $expire = (int)$s['expire_time'];
        if ($expire <= time()) {
            $this->deactivate(true);
            return;
        }
        $newExpire = $expire - ($minutes * 60);
        if ($newExpire <= time()) {
            $this->deactivate(true);
            return;
        }
        $stmt = $this->pdo->prepare('UPDATE settings SET is_active = 1, expire_time = ? WHERE chat_id = ?');
        $stmt->execute(array($newExpire, $this->chatId));
        $this->settings['is_active'] = 1;
        $this->settings['expire_time'] = $newExpire;
    }

    private function detectSpam()
    {
        if ($this->isFlood()) {
            return 'ارسال پشت‌سرهم پیام‌ها';
        }
        if (!empty($this->settings['word_filter_enabled']) && $this->containsForbiddenWord($this->text)) {
            return 'استفاده از کلمه ممنوع';
        }
        if (!empty($this->settings['link_filter_enabled']) && $this->containsLink($this->text)) {
            return 'ارسال لینک';
        }
        return null;
    }

    private function isFlood()
    {
        $limit = max(2, (int)$this->settings['flood_limit']);
        $window = max(1, (int)$this->settings['flood_window']);
        $now = time();
        $from = $now - $window;
        $stmt = $this->pdo->prepare('SELECT message_id FROM messages WHERE user_id = ? AND chat_id = ? AND created_at > ? ORDER BY created_at ASC');
        $stmt->execute(array($this->userId, $this->chatId, $from));
        $oldMessages = $stmt->fetchAll(PDO::FETCH_COLUMN);
        $count = count($oldMessages);
        $stmt = $this->pdo->prepare('INSERT INTO messages (user_id, chat_id, message_id, created_at) VALUES (?, ?, ?, ?)');
        $stmt->execute(array($this->userId, $this->chatId, (int)$this->message['message_id'], $now));
        if ($count + 1 >= $limit) {
            $this->deleteMessages($oldMessages);
            return true;
        }
        $cleanupBefore = $now - 120;
        $stmt = $this->pdo->prepare('DELETE FROM messages WHERE chat_id = ? AND created_at < ?');
        $stmt->execute(array($this->chatId, $cleanupBefore));
        return false;
    }

    private function containsForbiddenWord($text)
    {
        if (trim($text) === '') {
            return false;
        }
        $stmt = $this->pdo->prepare('SELECT word FROM forbidden_words WHERE chat_id = ?');
        $stmt->execute(array($this->chatId));
        $lower = mb_strtolower($text, 'UTF-8');
        foreach ($stmt->fetchAll(PDO::FETCH_COLUMN) as $word) {
            $word = trim($word);
            if ($word !== '' && mb_stripos($lower, $word, 0, 'UTF-8') !== false) {
                return true;
            }
        }
        return false;
    }

    private function containsLink($text)
    {
        return (bool)preg_match('~(?:https?://|www\.|t\.me/|telegram\.me/|tg://)\S+~iu', $text);
    }

    private function punish($reason)
    {
        $this->deleteCurrentMessage();
        if ($this->role === 'administrator') {
            $this->setAdminPending($this->userId);
            $this->sendAdminDecisionPanel($reason);
            return;
        }
        if ($this->role !== 'member') {
            return;
        }
        $warn = $this->getWarnCount($this->userId);
        $warn++;
        $this->setWarnCount($this->userId, $warn);
        $max = max(2, (int)$this->settings['max_warnings']);
        if ($warn >= $max) {
            if ($this->ban($this->userId)) {
                $this->clearUserData($this->userId);
                $this->send("🚫 <b>کاربر به دلیل تکرار اسپم بن شد.</b>\n\n👤 " . $this->userDisplay($this->userId) . "\n⚠️ اخطار: <b>{$warn}/{$max}</b>");
            }
            return;
        }
        if ($warn === 1) {
            $this->send("⚠️ <b>اخطار اول</b>\n\nپیام شما به دلیل <b>" . htmlspecialchars($reason, ENT_QUOTES, 'UTF-8') . "</b> حذف شد.\n\nلطفاً از تکرار آن خودداری کنید.");
            return;
        }
        $minutes = max(1, (int)$this->settings['member_mute_minutes']);
        $ok = $this->mute($this->userId, $minutes);
        if ($ok) {
            $this->send("🔇 <b>" . $this->userDisplay($this->userId) . " {$minutes} دقیقه سکوت شد.</b>\n\n⚠️ اخطار: <b>{$warn}/{$max}</b>\n📌 دلیل: " . htmlspecialchars($reason, ENT_QUOTES, 'UTF-8'));
        }
    }

    private function sendAdminDecisionPanel($reason)
    {
        $name = $this->userDisplay($this->userId);
        $reason = htmlspecialchars($reason, ENT_QUOTES, 'UTF-8');
        $text = "⚠️ <b>تخلف ادمین شناسایی شد</b>\n\n👤 {$name}\n📌 دلیل: <b>{$reason}</b>\n\n🗑 پیام متخلف حذف شد.\n\n⏳ تا زمان تصمیم مالک ربات، پیام‌های بعدی این ادمین نیز حذف می‌شوند.\n\n🔇 در صورت انتخاب Mute، مدت آن همیشه <b>۲ دقیقه</b> است.";
        $keyboard = array(
            'inline_keyboard' => array(
                array(
                    array('text' => '🔇 سکوت ۲ دقیقه', 'callback_data' => 'admin|mute|' . $this->chatId . '|' . $this->userId)
                ),
                array(
                    array('text' => '🔇 سکوت + 🚫 بن', 'callback_data' => 'admin|muteban|' . $this->chatId . '|' . $this->userId),
                    array('text' => '🚫 بن مستقیم', 'callback_data' => 'admin|ban|' . $this->chatId . '|' . $this->userId)
                )
            )
        );
        $this->send($text, $keyboard);
    }

    private function getWarnCount($userId)
    {
        $stmt = $this->pdo->prepare('SELECT warn_count FROM users WHERE user_id = ? AND chat_id = ?');
        $stmt->execute(array($userId, $this->chatId));
        $value = $stmt->fetchColumn();
        return $value === false ? 0 : (int)$value;
    }

    private function setWarnCount($userId, $count)
    {
        $stmt = $this->pdo->prepare('INSERT INTO users (user_id, chat_id, warn_count) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE warn_count = VALUES(warn_count)');
        $stmt->execute(array($userId, $this->chatId, $count));
    }

    private function mute($userId, $minutes)
    {
        $until = time() + ((int)$minutes * 60);
        $permissions = array(
            'can_send_messages' => false,
            'can_send_audios' => false,
            'can_send_documents' => false,
            'can_send_photos' => false,
            'can_send_videos' => false,
            'can_send_video_notes' => false,
            'can_send_voice_notes' => false,
            'can_send_polls' => false,
            'can_send_other_messages' => false,
            'can_add_web_page_previews' => false,
            'can_change_info' => false,
            'can_invite_users' => false,
            'can_pin_messages' => false,
            'can_manage_topics' => false
        );
        $response = telegram('restrictChatMember', array(
            'chat_id' => $this->chatId,
            'user_id' => $userId,
            'permissions' => json_encode($permissions, JSON_UNESCAPED_UNICODE),
            'until_date' => $until,
            'use_independent_chat_permissions' => true
        ));
        if (!($response['ok'] ?? false)) {
            error_log('[MUTE] ' . ($response['description'] ?? 'Unknown error'));
            return false;
        }
        $stmt = $this->pdo->prepare('INSERT INTO users (user_id, chat_id, muted_until) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE muted_until = VALUES(muted_until)');
        $stmt->execute(array($userId, $this->chatId, $until));
        return true;
    }

    private function isMuted($userId)
    {
        $stmt = $this->pdo->prepare('SELECT muted_until FROM users WHERE user_id = ? AND chat_id = ?');
        $stmt->execute(array($userId, $this->chatId));
        $until = (int)$stmt->fetchColumn();
        return $until > time();
    }

    private function setAdminPending($userId)
    {
        $until = time() + (86400 * 7);
        $stmt = $this->pdo->prepare('INSERT INTO users (user_id, chat_id, admin_clean_until) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE admin_clean_until = VALUES(admin_clean_until)');
        $stmt->execute(array($userId, $this->chatId, $until));
    }

    private function isAdminPending($userId)
    {
        $stmt = $this->pdo->prepare('SELECT admin_clean_until FROM users WHERE user_id = ? AND chat_id = ?');
        $stmt->execute(array($userId, $this->chatId));
        $until = (int)$stmt->fetchColumn();
        return $until > time();
    }

    private function clearAdminPending($userId)
    {
        $stmt = $this->pdo->prepare('UPDATE users SET admin_clean_until = 0 WHERE user_id = ? AND chat_id = ?');
        $stmt->execute(array($userId, $this->chatId));
    }

    private function unmuteFromReply()
    {
        $target = $this->getReplyTarget();
        if (!$target) {
            $this->send("❌ <b>نحوه استفاده:</b>\n\nروی پیام کاربر ریپلای کنید و بنویسید:\n<code>حذف سکوت</code>");
            return;
        }
        $permissions = array(
            'can_send_messages' => true,
            'can_send_audios' => true,
            'can_send_documents' => true,
            'can_send_photos' => true,
            'can_send_videos' => true,
            'can_send_video_notes' => true,
            'can_send_voice_notes' => true,
            'can_send_polls' => true,
            'can_send_other_messages' => true,
            'can_add_web_page_previews' => true,
            'can_change_info' => false,
            'can_invite_users' => true,
            'can_pin_messages' => false,
            'can_manage_topics' => false
        );
        $response = telegram('restrictChatMember', array(
            'chat_id' => $this->chatId,
            'user_id' => $target,
            'permissions' => json_encode($permissions, JSON_UNESCAPED_UNICODE),
            'use_independent_chat_permissions' => true
        ));
        if (!($response['ok'] ?? false)) {
            $this->send('❌ <b>رفع سکوت انجام نشد.</b>');
            return;
        }
        $stmt = $this->pdo->prepare('UPDATE users SET muted_until = 0 WHERE user_id = ? AND chat_id = ?');
        $stmt->execute(array($target, $this->chatId));
        $this->send("🔊 <b>سکوت کاربر برداشته شد.</b>\n\n" . $this->userDisplay($target));
    }

    private function clearWarningsFromReply()
    {
        $target = $this->getReplyTarget();
        if (!$target) {
            $this->send("❌ <b>نحوه استفاده:</b>\n\nروی پیام کاربر ریپلای کنید و بنویسید:\n<code>حذف اخطار</code>");
            return;
        }
        $count = $this->getWarnCount($target);
        if ($count <= 0) {
            $this->send('ℹ️ این کاربر اخطاری ندارد.');
            return;
        }
        $stmt = $this->pdo->prepare('UPDATE users SET warn_count = 0 WHERE user_id = ? AND chat_id = ?');
        $stmt->execute(array($target, $this->chatId));
        $this->send("✅ <b>اخطارهای کاربر پاک شد.</b>\n\n" . $this->userDisplay($target));
    }

    private function ban($userId)
    {
        $response = telegram('banChatMember', array(
            'chat_id' => $this->chatId,
            'user_id' => $userId,
            'revoke_messages' => true
        ));
        if (!($response['ok'] ?? false)) {
            error_log('[BAN] ' . ($response['description'] ?? 'Unknown error'));
            return false;
        }
        return true;
    }

    private function deleteCurrentMessage()
    {
        if (empty($this->message['message_id'])) {
            return;
        }
        telegram('deleteMessage', array(
            'chat_id' => $this->chatId,
            'message_id' => (int)$this->message['message_id']
        ));
    }

    private function deleteMessages($messageIds)
    {
        if (!is_array($messageIds)) {
            return;
        }
        foreach ($messageIds as $messageId) {
            telegram('deleteMessage', array(
                'chat_id' => $this->chatId,
                'message_id' => (int)$messageId
            ));
        }
    }

    private function clearUserData($userId)
    {
        $stmt = $this->pdo->prepare('DELETE FROM users WHERE user_id = ? AND chat_id = ?');
        $stmt->execute(array($userId, $this->chatId));
    }

    private function getUserRole($userId)
    {
        if (isset($this->roleCache[$userId])) {
            return $this->roleCache[$userId];
        }
        if ($userId === OWNER_ID) {
            $this->roleCache[$userId] = 'creator';
            return 'creator';
        }
        $response = telegram('getChatMember', array(
            'chat_id' => $this->chatId,
            'user_id' => $userId
        ));
        if (!($response['ok'] ?? false)) {
            return 'member';
        }
        $role = $response['result']['status'] ?? 'member';
        $this->roleCache[$userId] = $role;
        return $role;
    }

    private function getGroupCreator()
    {
        if ($this->groupCreatorLoaded) {
            return $this->groupCreator;
        }
        $this->groupCreatorLoaded = true;
        if (!$this->chatId) {
            return 0;
        }
        $response = telegram('getChatAdministrators', array(
            'chat_id' => $this->chatId
        ));
        if (!($response['ok'] ?? false)) {
            return 0;
        }
        foreach ($response['result'] as $admin) {
            if (($admin['status'] ?? '') === 'creator') {
                $this->groupCreator = (int)($admin['user']['id'] ?? 0);
                return $this->groupCreator;
            }
        }
        return 0;
    }

    private function isGroupOwner()
    {
        return ($this->role === 'creator') || (!empty($this->settings['group_owner_id']) && (int)$this->settings['group_owner_id'] === $this->userId);
    }

    private function getReplyTarget()
    {
        if (!isset($this->message['reply_to_message'])) {
            return null;
        }
        $reply = $this->message['reply_to_message'];
        if (isset($reply['from']['id'])) {
            $target = (int)$reply['from']['id'];
            if ($target === $this->getBotId()) {
                if (isset($reply['reply_to_message']['from']['id'])) {
                    return (int)$reply['reply_to_message']['from']['id'];
                }
                return null;
            }
            return $target;
        }
        return null;
    }

    private function getBotId()
    {
        if ($this->botId) {
            return $this->botId;
        }
        $response = telegram('getMe');
        $this->botId = (int)($response['result']['id'] ?? 0);
        return $this->botId;
    }

    private function userDisplay($userId)
    {
        $response = telegram('getChatMember', array(
            'chat_id' => $this->chatId,
            'user_id' => $userId
        ));
        $user = $response['result']['user'] ?? array();
        $name = trim(($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? ''));
        if ($name === '') {
            $name = 'کاربر';
        }
        $name = htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
        $username = '';
        if (!empty($user['username'])) {
            $username = ' @' . htmlspecialchars($user['username'], ENT_QUOTES, 'UTF-8');
        }
        return "<b>{$name}</b>{$username} <code>{$userId}</code>";
    }

    private function send($text, $keyboard = null)
    {
        $data = array(
            'chat_id' => $this->chatId,
            'text' => $text,
            'parse_mode' => 'HTML',
            'disable_web_page_preview' => true
        );
        if ($keyboard !== null) {
            $data['reply_markup'] = json_encode($keyboard, JSON_UNESCAPED_UNICODE);
        }
        telegram('sendMessage', $data);
    }

    private function editText($message, $text, $keyboard = null)
    {
        if (empty($message['message_id']) || empty($message['chat']['id'])) {
            return false;
        }
        $data = array(
            'chat_id' => (int)$message['chat']['id'],
            'message_id' => (int)$message['message_id'],
            'text' => $text,
            'parse_mode' => 'HTML',
            'disable_web_page_preview' => true
        );
        if ($keyboard !== null) {
            $data['reply_markup'] = json_encode($keyboard, JSON_UNESCAPED_UNICODE);
        }
        $response = telegram('editMessageText', $data);
        if (!($response['ok'] ?? false)) {
            $description = (string)($response['description'] ?? '');
            if (strpos($description, 'message is not modified') === false) {
                error_log('[EDIT] ' . $description);
            }
            return false;
        }
        return true;
    }

    private function answerCallback($id, $text = '', $alert = false)
    {
        if ($id === '') {
            return;
        }
        telegram('answerCallbackQuery', array(
            'callback_query_id' => $id,
            'text' => $text,
            'show_alert' => $alert
        ));
    }

    private function humanTime($seconds)
    {
        $seconds = max(0, (int)$seconds);
        $days = intdiv($seconds, 86400);
        $seconds %= 86400;
        $hours = intdiv($seconds, 3600);
        $seconds %= 3600;
        $minutes = intdiv($seconds, 60);
        $parts = array();
        if ($days > 0) {
            $parts[] = $days . ' روز';
        }
        if ($hours > 0) {
            $parts[] = $hours . ' ساعت';
        }
        if ($minutes > 0 || empty($parts)) {
            $parts[] = $minutes . ' دقیقه';
        }
        return implode(' و ', $parts);
    }
}