# =====================================================================
# 🌐 TELEGRAM VPS HOSTING PLATFORM - ENTERPRISE EDITION (UPDATED)
# Stack: Python 3.12+ | pyTelegramBotAPI (telebot) | SQLite3 | Subprocess | Psutil
# Description: Real python process execution, dynamic UI, Force Subscribe & CPA Task Engine.
# =====================================================================

import html
import logging
import os
import platform
import re
import shutil
import sqlite3
import subprocess
import sys
import threading
import time
import traceback
import uuid
from datetime import datetime, timedelta

import telebot
from telebot.types import (
    CallbackQuery,
    InlineKeyboardButton,
    InlineKeyboardMarkup,
    Message,
)

# المحاولة الآمنة لاستيراد psutil للتحكم بالعمليات
try:
    import psutil
except ImportError:
    psutil = None

# =====================================================================
# 1. SYSTEM CONFIGURATION & LOGGING
# =====================================================================

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] (%(name)s): %(message)s",
    handlers=[logging.StreamHandler(sys.stdout)]
)
logger = logging.getLogger("VPSHostingEngine")

BOT_TOKEN = "8540431092:AAH8sJpOhWjnHvHQgZej8eduv5Q0b2HOI8Y"
ADMIN_IDS = {
    6906464955,  # آيدي الأدمن الرئيسي
}
OWNER_USERNAME = "YOUSA45"  # معرف صاحب البوت للتواصل عند شراء VIP

ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
HOSTING_DIR = os.path.join(ROOT_DIR, "active_bots")
PENDING_DIR = os.path.join(ROOT_DIR, "pending_bots")
LOGS_DIR = os.path.join(ROOT_DIR, "bot_logs")
DB_PATH = os.path.join(ROOT_DIR, "vps_platform.db")
MAX_FILE_SIZE = 20 * 1024 * 1024  # 20 MB حد تليجرام الأقصى

for directory in [HOSTING_DIR, PENDING_DIR, LOGS_DIR]:
    os.makedirs(directory, exist_ok=True)

db_lock = threading.Lock()
ACTIVE_PROCESSES = {}


# =====================================================================
# 2. DATABASE ARCHITECTURE & MIGRATION LAYER
# =====================================================================

def get_db_connection() -> sqlite3.Connection:
    conn = sqlite3.connect(DB_PATH, check_same_thread=False)
    conn.row_factory = sqlite3.Row
    return conn

def init_database() -> None:
    """إنشاء جداول قاعدة البيانات اللازمة للمنصة بأمان تام."""
    with db_lock:
        conn = get_db_connection()
        try:
            conn.executescript("""
            CREATE TABLE IF NOT EXISTS users (
                user_id INTEGER PRIMARY KEY,
                first_name TEXT DEFAULT '',
                username TEXT DEFAULT '',
                referred_by INTEGER DEFAULT 0,
                referral_count INTEGER DEFAULT 0,
                can_upload INTEGER DEFAULT 1,
                is_banned INTEGER DEFAULT 0,
                is_vip INTEGER DEFAULT 0,
                unlimited_uploads INTEGER DEFAULT 0,
                joined_at TEXT
            );

            CREATE TABLE IF NOT EXISTS hosted_bots (
                bot_id TEXT PRIMARY KEY,
                user_id INTEGER,
                bot_name TEXT,
                file_path TEXT,
                log_path TEXT,
                pid INTEGER DEFAULT 0,
                status TEXT DEFAULT 'stopped',
                runtime_hours REAL DEFAULT 0.0,
                unlimited_time INTEGER DEFAULT 0,
                created_at TEXT
            );

            CREATE TABLE IF NOT EXISTS time_tasks (
                task_id TEXT PRIMARY KEY,
                task_name TEXT,
                token_url TEXT,
                is_active INTEGER DEFAULT 1,
                created_at TEXT
            );

            CREATE TABLE IF NOT EXISTS used_tokens (
                token_id TEXT,
                user_id INTEGER,
                PRIMARY KEY (token_id, user_id)
            );

            CREATE TABLE IF NOT EXISTS force_channels (
                channel_id TEXT PRIMARY KEY,
                channel_username TEXT,
                channel_title TEXT
            );

            CREATE TABLE IF NOT EXISTS settings (
                key TEXT PRIMARY KEY,
                value TEXT
            );
            """)
            conn.commit()
            logger.info("Database schema initialized successfully.")
        except Exception as e:
            logger.critical(f"Database initialization failed: {e}", exc_info=True)
        finally:
            conn.close()

init_database()


def db_query(query: str, params: tuple = (), fetch_one: bool = False, fetch_all: bool = False, commit: bool = False):
    """تنفيذ استعلامات قواعد البيانات مع قفل الخيوط الآمن."""
    with db_lock:
        conn = get_db_connection()
        try:
            cursor = conn.cursor()
            cursor.execute(query, params)
            if commit:
                conn.commit()
            if fetch_one:
                return cursor.fetchone()
            if fetch_all:
                return cursor.fetchall()
            return cursor
        except Exception as e:
            logger.error(f"DB Error on query [{query}]: {e}", exc_info=True)
            return None
        finally:
            conn.close()


# =====================================================================
# 3. HELPER FUNCTIONS (بما في ذلك الدالة المفقودة fetch_system_setting)
# =====================================================================

def fetch_system_setting(key: str) -> str:
    """جلب إعدادات النظام من قاعدة البيانات"""
    res = db_query("SELECT value FROM settings WHERE key = ?", (key,), fetch_one=True)
    return res["value"] if res else "off"


# =====================================================================
# 4. CORE SUBPROCESS & VPS PROCESS MANAGEMENT
# =====================================================================

def auto_install_requirements(script_path: str) -> bool:
    try:
        with open(script_path, 'r', encoding='utf-8', errors='ignore') as f:
            content = f.read()
        
        imports = re.findall(r'^\s*(?:import|from)\s+([a-zA-Z0-9_]+)', content, re.MULTILINE)
        standard_libs = {
            'os', 'sys', 'time', 'datetime', 'math', 'json', 're', 'logging', 
            'threading', 'subprocess', 'uuid', 'shutil', 'sqlite3', 'html', 
            'pathlib', 'typing', 'collections', 'functools', 'itertools', 'traceback'
        }
        external_libs = {lib for lib in imports if lib not in standard_libs and lib != 'telebot'}
        
        for lib in external_libs:
            logger.info(f"Auto-installing requirement package: {lib} ...")
            subprocess.run([sys.executable, "-m", "pip", "install", lib], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=60)
        return True
    except Exception as e:
        logger.error(f"Failed auto-installing requirements for {script_path}: {e}")
        return False


def start_bot_process(bot_id: str) -> bool:
    bot_rec = db_query("SELECT * FROM hosted_bots WHERE bot_id = ?", (bot_id,), fetch_one=True)
    if not bot_rec or not os.path.exists(bot_rec["file_path"]):
        return False

    # إذا لم يكن لديه وقت غير محدود وكان الوقت <= 0
    if bot_rec["unlimited_time"] == 0 and bot_rec["runtime_hours"] <= 0:
        db_query("UPDATE hosted_bots SET status = 'out_of_time' WHERE bot_id = ?", (bot_id,), commit=True)
        return False

    stop_bot_process(bot_id)

    script_path = bot_rec["file_path"]
    log_path = bot_rec["log_path"]

    auto_install_requirements(script_path)

    try:
        log_file = open(log_path, "a", encoding="utf-8")
        process = subprocess.Popen(
            [sys.executable, script_path],
            stdout=log_file,
            stderr=log_file,
            cwd=os.path.dirname(script_path)
        )
        
        pid = process.pid
        ACTIVE_PROCESSES[bot_id] = process
        db_query("UPDATE hosted_bots SET pid = ?, status = 'running' WHERE bot_id = ?", (pid, bot_id), commit=True)
        logger.info(f"Bot [{bot_id}] successfully started with PID: {pid}")
        return True
    except Exception as e:
        logger.error(f"Failed to start bot process {bot_id}: {e}", exc_info=True)
        db_query("UPDATE hosted_bots SET status = 'error' WHERE bot_id = ?", (bot_id,), commit=True)
        return False


def stop_bot_process(bot_id: str) -> bool:
    bot_rec = db_query("SELECT * FROM hosted_bots WHERE bot_id = ?", (bot_id,), fetch_one=True)
    if not bot_rec:
        return False

    pid = bot_rec["pid"]
    if bot_id in ACTIVE_PROCESSES:
        try:
            proc = ACTIVE_PROCESSES[bot_id]
            proc.terminate()
            proc.wait(timeout=3)
        except Exception:
            try:
                proc.kill()
            except Exception:
                pass
        finally:
            del ACTIVE_PROCESSES[bot_id]

    if pid and pid > 0:
        try:
            if psutil and psutil.pid_exists(pid):
                p = psutil.Process(pid)
                p.terminate()
                p.wait(2)
        except Exception as e:
            logger.warning(f"Could not terminate PID {pid} via psutil: {e}")

    db_query("UPDATE hosted_bots SET pid = 0, status = 'stopped' WHERE bot_id = ?", (bot_id,), commit=True)
    logger.info(f"Bot [{bot_id}] stopped successfully.")
    return True


# =====================================================================
# 5. BACKGROUND WORKER: TIME MONITOR & AUTO-STOP
# =====================================================================

def background_time_monitor_worker():
    logger.info("Background time monitor worker started.")
    while True:
        try:
            time.sleep(60)
            bots = db_query("SELECT * FROM hosted_bots WHERE status = 'running' AND unlimited_time = 0", fetch_all=True)
            if not bots:
                continue

            for b in bots:
                bot_id = b["bot_id"]
                current_hours = b["runtime_hours"]
                new_hours = current_hours - (1.0 / 60.0)
                
                if new_hours <= 0:
                    new_hours = 0.0
                    logger.info(f"Bot [{bot_id}] ran out of time. Terminating process...")
                    stop_bot_process(bot_id)
                    db_query("UPDATE hosted_bots SET runtime_hours = 0.0, status = 'out_of_time' WHERE bot_id = ?", (bot_id,), commit=True)
                    
                    try:
                        bot_owner = b["user_id"]
                        bot.send_message(bot_owner, f"⏳ <b>نفد وقت تشغيل البوت:</b> <code>{b['bot_name']}</code>\n\nتم إيقاف البوت تلقائياً. يرجى شحن الوقت عبر تنفيذ مهام الاختصار!")
                    except Exception:
                        pass
                else:
                    db_query("UPDATE hosted_bots SET runtime_hours = ? WHERE bot_id = ?", (new_hours, bot_id), commit=True)
        except Exception as e:
            logger.error(f"Error in background time monitor worker: {e}", exc_info=True)

threading.Thread(target=background_time_monitor_worker, daemon=True).start()


# =====================================================================
# 6. FORCE SUBSCRIBE HELPERS
# =====================================================================

def check_user_force_subscribe(user_id: int) -> bool:
    channels = db_query("SELECT * FROM force_channels", fetch_all=True)
    if not channels:
        return True

    for ch in channels:
        ch_id = ch["channel_id"]
        try:
            member = bot.get_chat_member(chat_id=ch_id, user_id=user_id)
            if member.status not in ['creator', 'administrator', 'member']:
                return False
        except Exception as e:
            logger.warning(f"Could not check subscription for channel {ch_id}: {e}")
            return False
    return True


# =====================================================================
# 7. UI KEYBOARDS SYSTEM
# =====================================================================

def get_main_menu_markup(is_admin: bool = False) -> InlineKeyboardMarkup:
    markup = InlineKeyboardMarkup()
    markup.row(InlineKeyboardButton("🚀 ⦗ استضافة بوت جديد ⦘", callback_data="menu_hosting"))
    markup.row(
        InlineKeyboardButton("🤖 ⦗ بوتاتي النشطة ⦘", callback_data="menu_my_bots"),
        InlineKeyboardButton("👥 ⦗ نظام الإحالات ⦘", callback_data="menu_referrals")
    )
    markup.row(
        InlineKeyboardButton("⏳ ⦗ مهام زيادة الوقت ⦘", callback_data="menu_tasks"),
        InlineKeyboardButton("👤 ⦗ حسابي الشخصي ⦘", callback_data="menu_profile")
    )
    markup.row(InlineKeyboardButton("💎 ⦗ شراء VIP (تواصل مع المالك) ⦘", url=f"https://t.me/{OWNER_USERNAME}"))
    if is_admin:
        markup.row(InlineKeyboardButton("🔐 ⦗ لوحة تحكم المشرف ⦘", callback_data="admin_main"))
    return markup


def get_back_markup() -> InlineKeyboardMarkup:
    markup = InlineKeyboardMarkup()
    markup.row(InlineKeyboardButton("🔙 ⦗ العودة للقائمة الرئيسية ⦘", callback_data="nav_home"))
    return markup


def get_bot_control_markup(bot_id: str, status: str, has_time: bool, unlimited_time: int) -> InlineKeyboardMarkup:
    markup = InlineKeyboardMarkup()
    
    if not has_time and unlimited_time == 0:
        markup.row(InlineKeyboardButton("⏳ ⦗ شحن وقت التشغيل (تنفيذ مهام) ⦘", callback_data="menu_tasks"))
    else:
        if status == 'running':
            markup.row(
                InlineKeyboardButton("⏸️ ⦗ إيقاف مؤقت ⦘", callback_data=f"bot_stop:{bot_id}"),
                InlineKeyboardButton("🔄 ⦗ إعادة تشغيل ⦘", callback_data=f"bot_restart:{bot_id}")
            )
        else:
            markup.row(
                InlineKeyboardButton("▶️ ⦗ تشغيل البوت ⦘", callback_data=f"bot_start:{bot_id}")
            )
            
    markup.row(
        InlineKeyboardButton("📝 ⦗ سجلات الـ Logs ⦘", callback_data=f"bot_logs:{bot_id}"),
        InlineKeyboardButton("🗑️ ⦗ حذف نهائي ⦘", callback_data=f"bot_delete:{bot_id}")
    )
    markup.row(InlineKeyboardButton("🔙 ⦗ عودة لقائمة بوتاتي ⦘", callback_data="menu_my_bots"))
    return markup


# =====================================================================
# 8. TELEBOT EVENT HANDLERS
# =====================================================================

bot = telebot.TeleBot(BOT_TOKEN, parse_mode="HTML")


@bot.message_handler(commands=['start'])
def cmd_start(message: Message):
    user_id = message.from_user.id
    args = message.text.split()
    
    if len(args) > 1 and args[1].isdigit():
        referrer_id = int(args[1])
        if referrer_id != user_id:
            existing = db_query("SELECT * FROM users WHERE user_id = ?", (user_id,), fetch_one=True)
            if not existing:
                db_query(
                    "INSERT INTO users (user_id, first_name, username, referred_by, referral_count, can_upload, is_banned, is_vip, unlimited_uploads, joined_at) VALUES (?, ?, ?, ?, 0, 1, 0, 0, 0, ?)",
                    (user_id, html.escape(message.from_user.first_name or ""), html.escape(message.from_user.username or ""), referrer_id, datetime.now().isoformat()),
                    commit=True
                )
                ref_user = db_query("SELECT * FROM users WHERE user_id = ?", (referrer_id,), fetch_one=True)
                if ref_user:
                    new_count = ref_user["referral_count"] + 1
                    new_uploads = ref_user["can_upload"] + 1
                    db_query("UPDATE users SET referral_count = ?, can_upload = ? WHERE user_id = ?", (new_count, new_uploads, referrer_id), commit=True)
                    try:
                        bot.send_message(referrer_id, f"🎉 <b>مبارك! انضم مستخدم جديد عبر رابط إحالتك.</b>\n\n◂ تم إضافة (+1) صلاحية رفع بوت جديد لحسابك!")
                    except Exception:
                        pass

    existing_user = db_query("SELECT * FROM users WHERE user_id = ?", (user_id,), fetch_one=True)
    if not existing_user:
        # كل مستخدم جديد يحصل على 1 رفع مجاني افتراضياً عند البدء
        db_query(
            "INSERT INTO users (user_id, first_name, username, referred_by, referral_count, can_upload, is_banned, is_vip, unlimited_uploads, joined_at) VALUES (?, ?, ?, 0, 0, 1, 0, 0, 0, ?)",
            (user_id, html.escape(message.from_user.first_name or ""), html.escape(message.from_user.username or ""), datetime.now().isoformat()),
            commit=True
        )
        existing_user = db_query("SELECT * FROM users WHERE user_id = ?", (user_id,), fetch_one=True)

    if existing_user["is_banned"] == 1:
        bot.reply_to(message, "🚫 <b>عذراً، حسابك محظور من استخدام المنصة.</b>")
        return

    if not check_user_force_subscribe(user_id):
        channels = db_query("SELECT * FROM force_channels", fetch_all=True)
        markup = InlineKeyboardMarkup()
        for ch in channels:
            ch_url = f"https://t.me/{ch['channel_username']}" if ch['channel_username'] else "https://t.me/"
            markup.row(InlineKeyboardButton(f"📢 ⦗ {ch['channel_title']} ⦘", url=ch_url))
        markup.row(InlineKeyboardButton("♻️ ⦗ تحقق من الاشتراك ⦘", callback_data="check_sub"))
        
        text = """
<b>╭━━━ 🛡️ تنبيه الاشتراك الإجباري 🛡️ ━━━╮</b>
┃
┃ ıllıllı عذراً عزيزي المستخدم، يجب عليك الاشتراك 
┃ في قنوات المنصة أولاً لكي تتمكن من استخدام البوت.
┃
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
◂ اشترك في القنوات أدناه ثم اضغط على زر التحقق:
"""
        bot.send_message(message.chat.id, text, reply_markup=markup)
        return

    send_main_menu(message.chat.id)


def send_main_menu(chat_id: int, message_id: int = None):
    text = """
<b>╭━━━ 🌟 منصة الاستضافة السحابية للـ VPS 🌟 ━━━╮</b>
┃
┃ ıllıllı أهلاً بك في أقوى منصة لاستضافة بوتات 
┃ تليجرام أوتوماتيكياً مع تشغيل فعلي عبر الـ VPS.
┃
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
◂ <b>اختر إحدى الخدمات من القائمة أدناه:</b>
"""
    is_admin = chat_id in ADMIN_IDS
    markup = get_main_menu_markup(is_admin)
    
    if message_id:
        try:
            bot.edit_message_text(text, chat_id, message_id, reply_markup=markup)
            return
        except Exception:
            pass
    bot.send_message(chat_id, text, reply_markup=markup)


# =====================================================================
# 9. CALLBACK ROUTER
# =====================================================================

@bot.callback_query_handler(func=lambda call: True)
def callback_router(call: CallbackQuery):
    user_id = call.from_user.id
    data = call.data
    is_admin = user_id in ADMIN_IDS

    if not check_user_force_subscribe(user_id) and data != "check_sub":
        bot.answer_callback_query(call.id, "⚠️ يجب الاشتراك في القنوات الإجبارية أولاً!", show_alert=True)
        return

    try:
        if data == "check_sub":
            if check_user_force_subscribe(user_id):
                bot.answer_callback_query(call.id, "✅ تم التحقق من اشتراكك بنجاح!")
                try:
                    bot.delete_message(call.message.chat.id, call.message.message_id)
                except Exception:
                    pass
                send_main_menu(call.message.chat.id)
            else:
                bot.answer_callback_query(call.id, "❌ لم تقم بالاشتراك في جميع القنوات المطلوبة بعد!", show_alert=True)

        elif data == "nav_home":
            send_main_menu(call.message.chat.id, call.message.message_id)
            bot.answer_callback_query(call.id)

        elif data == "menu_profile":
            user = db_query("SELECT * FROM users WHERE user_id = ?", (user_id,), fetch_one=True)
            bots_count = db_query("SELECT COUNT(*) as c FROM hosted_bots WHERE user_id = ?", (user_id,), fetch_one=True)["c"]
            vip_status = "نعم ⭐" if user["is_vip"] == 1 else "لا 👤"
            
            text = f"""
<b>╭━━━ 👤 ملف المستخدم الشخصي 👤 ━━━╮</b>
┃
┃ ◂ <b>المعرف الرقمي:</b> <code>{user_id}</code>
┃ ◂ <b>الاسم:</b> {user['first_name']}
┃ ◂ <b>حالة الـ VIP:</b> {vip_status}
┃ ◂ <b>رصيد الإحالات:</b> {user['referral_count']} 👤
┃ ◂ <b>صلاحيات الرفع المتاحة:</b> {"غير محدود ♾️" if user["unlimited_uploads"] == 1 else user['can_upload']} 🚀
┃ ◂ <b>عدد بوتاتك المرفوعة:</b> {bots_count} 🤖
┃
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
"""
            bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=get_back_markup())
            bot.answer_callback_query(call.id)

        elif data == "menu_referrals":
            user = db_query("SELECT * FROM users WHERE user_id = ?", (user_id,), fetch_one=True)
            bot_info = bot.get_me()
            ref_link = f"https://t.me/{bot_info.username}?start={user_id}"
            
            text = f"""
<b>╭━━━ 👥 نظام الإحالات والأرباح 👥 ━━━╮</b>
┃
┃ ıllıllı كل 1 شخص يقوم بالدخول عبر رابط إحالتك 
┃ سيحصل حسابك فوراً على (+1) صلاحية رفع بوت جديد!
┃
┃ ◂ <b>عدد الأشخاص الذين دعيتهم:</b> {user['referral_count']}
┃ ◂ <b>صلاحيات الرفع المتاحة لديك:</b> {"غير محدود ♾️" if user["unlimited_uploads"] == 1 else user['can_upload']}
┃
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
◂ <b>رابط الإحالة الخاص بك:</b>
<code>{ref_link}</code>
"""
            bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=get_back_markup())
            bot.answer_callback_query(call.id)

        elif data == "menu_hosting":
            user = db_query("SELECT * FROM users WHERE user_id = ?", (user_id,), fetch_one=True)
            if user["unlimited_uploads"] == 0 and user["can_upload"] <= 0:
                text = """
<b>⚠️ ⦗ تنبيه: عذراً لا تمتلك صلاحية رفع ⦘</b>
┃
┃ ıllıllı يشترط لجلب صلاحية رفع بوت جديد دعوة شخص واحد 
┃ على الأقل عبر 'نظام الإحالات' الخاص بك أو ترقية حسابك لـ VIP!
┃
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
◂ توجه إلى قسم <b>'نظام الإحالات'</b> أو تواصل مع المالك لشراء VIP.
"""
                bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=get_back_markup())
                bot.answer_callback_query(call.id)
                return

            text = """
<b>🚀 ⦗ رفع واستضافة بوت جديد ⦘</b>
┃
┃ ıllıllı أرسل الآن ملف البوت الخاص بك بصيغة <b>.py</b> 
┃ وسيتم معالجته ومنحه 24 ساعة مجانية وتثبيت مكتباته وتشغيله آلياً على الـ VPS.
┃
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
"""
            bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=get_back_markup())
            bot.answer_callback_query(call.id)

        elif data == "menu_my_bots":
            bots = db_query("SELECT * FROM hosted_bots WHERE user_id = ?", (user_id,), fetch_all=True)
            if not bots:
                text = "<b>🤖 ⦗ لم تقم برفع أي بوتات استضافة حتى الآن! ⦘</b>"
                bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=get_back_markup())
                bot.answer_callback_query(call.id)
                return

            markup = InlineKeyboardMarkup()
            for b in bots:
                status_icon = "🟢" if b["status"] == "running" else "🔴"
                time_display = "غير محدود ♾️" if b["unlimited_time"] == 1 else f"{b['runtime_hours']:.1f}h"
                markup.row(InlineKeyboardButton(f"{status_icon} ⦗ {b['bot_name']} ({time_display}) ⦘", callback_data=f"manage_bot:{b['bot_id']}"))
            markup.row(InlineKeyboardButton("🔙 ⦗ عودة للقائمة الرئيسية ⦘", callback_data="nav_home"))

            text = "<b>🤖 ⦗ قائمة بوتاتك النشطة والمرفوعة ⦘</b>\n\n◂ اضغط على البوت لعرض لوحة التحكم وإدارته:"
            bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=markup)
            bot.answer_callback_query(call.id)

        elif data.startswith("manage_bot:"):
            bot_id = data.split(":")[1]
            b = db_query("SELECT * FROM hosted_bots WHERE bot_id = ? AND user_id = ?", (bot_id, user_id), fetch_one=True)
            if not b:
                bot.answer_callback_query(call.id, "❌ البوت غير موجود أو لا تملكه!", show_alert=True)
                return

            has_time = (b["runtime_hours"] > 0) or (b["unlimited_time"] == 1)
            status_text = "يعمل حالياً 🟢" if b["status"] == "running" else ("نفد الوقت ⏳" if b["status"] == "out_of_time" else "متوقف 🔴")
            time_display = "غير محدود ♾️" if b["unlimited_time"] == 1 else f"{b['runtime_hours']:.2f} ساعة"
            
            text = f"""
<b>╭━━━ 🤖 لوحة تحكم البوت 🤖 ━━━╮</b>
┃
┃ ◂ <b>اسم البوت:</b> <code>{b['bot_name']}</code>
┃ ◂ <b>الحالة الحالية:</b> {status_text}
┃ ◂ <b>الوقت المتبقي:</b> <code>{time_display}</code>
┃ ◂ <b>معرف العمليات PID:</b> {b['pid']}
┃
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
"""
            markup = get_bot_control_markup(bot_id, b["status"], has_time, b["unlimited_time"])
            bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=markup)
            bot.answer_callback_query(call.id)

        elif data.startswith("bot_start:"):
            bot_id = data.split(":")[1]
            b = db_query("SELECT * FROM hosted_bots WHERE bot_id = ? AND user_id = ?", (bot_id, user_id), fetch_one=True)
            if not b:
                return

            if b["unlimited_time"] == 0 and b["runtime_hours"] <= 0:
                bot.answer_callback_query(call.id, "⏳ نفد وقت تشغيل هذا البوت! يرجى شحن الوقت.", show_alert=True)
                return

            success = start_bot_process(bot_id)
            if success:
                bot.answer_callback_query(call.id, "✅ تم تشغيل البوت بنجاح على الـ VPS!")
            else:
                bot.answer_callback_query(call.id, "❌ فشل تشغيل البوت، راجع السجلات.", show_alert=True)
            
            call.data = f"manage_bot:{bot_id}"
            callback_router(call)

        elif data.startswith("bot_stop:"):
            bot_id = data.split(":")[1]
            stop_bot_process(bot_id)
            bot.answer_callback_query(call.id, "⏸️ تم إيقاف البوت مؤقتاً.")
            
            call.data = f"manage_bot:{bot_id}"
            callback_router(call)

        elif data.startswith("bot_restart:"):
            bot_id = data.split(":")[1]
            stop_bot_process(bot_id)
            time.sleep(1)
            start_bot_process(bot_id)
            bot.answer_callback_query(call.id, "🔄 تمت إعادة تشغيل البوت بنجاح.")
            
            call.data = f"manage_bot:{bot_id}"
            callback_router(call)

        elif data.startswith("bot_logs:"):
            bot_id = data.split(":")[1]
            b = db_query("SELECT * FROM hosted_bots WHERE bot_id = ? AND user_id = ?", (bot_id, user_id), fetch_one=True)
            if not b:
                return

            log_path = b["log_path"]
            logs_content = "لا توجد سجلات مسجلة حتى الآن."
            if os.path.exists(log_path):
                with open(log_path, "r", encoding="utf-8", errors="ignore") as lf:
                    lines = lf.readlines()
                    last_20 = lines[-20:]
                    if last_20:
                        logs_content = "".join(last_20)

            text = f"""
<b>📝 ⦗ آخر 20 سطر من سجلات البوت ⦘</b>
━━━━━━━━━━━━━━━━━━
<pre>{html.escape(logs_content[-3500:])}</pre>
━━━━━━━━━━━━━━━━━━
"""
            markup = InlineKeyboardMarkup()
            markup.row(InlineKeyboardButton("🔄 ⦗ تحديث السجلات ⦘", callback_data=f"bot_logs:{bot_id}"))
            markup.row(InlineKeyboardButton("🔙 ⦗ عودة لوحة التحكم ⦘", callback_data=f"manage_bot:{bot_id}"))
            
            bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=markup)
            bot.answer_callback_query(call.id)

        elif data.startswith("bot_delete:"):
            bot_id = data.split(":")[1]
            b = db_query("SELECT * FROM hosted_bots WHERE bot_id = ? AND user_id = ?", (bot_id, user_id), fetch_one=True)
            if not b:
                return

            stop_bot_process(bot_id)
            try:
                folder_to_delete = os.path.dirname(b["file_path"])
                if os.path.exists(folder_to_delete):
                    shutil.rmtree(folder_to_delete)
                if os.path.exists(b["log_path"]):
                    os.remove(b["log_path"])
            except Exception:
                pass

            db_query("DELETE FROM hosted_bots WHERE bot_id = ?", (bot_id,), commit=True)
            bot.answer_callback_query(call.id, "🗑️ تم حذف البوت نهائياً من الـ VPS.")
            
            call.data = "menu_my_bots"
            callback_router(call)

        elif data == "menu_tasks":
            tasks = db_query("SELECT * FROM time_tasks WHERE is_active = 1", fetch_all=True)
            if not tasks:
                text = "<b>⏳ ⦗ مهام زيادة الوقت ⦘</b>\n\n◂ عذراً، لا توجد مهام نشطة حالياً. يرجى العودة لاحقاً."
                bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=get_back_markup())
                bot.answer_callback_query(call.id)
                return

            markup = InlineKeyboardMarkup()
            for t in tasks:
                used = db_query("SELECT * FROM used_tokens WHERE token_id = ? AND user_id = ?", (t["task_id"], user_id), fetch_one=True)
                if not used:
                    markup.row(InlineKeyboardButton(f"🔗 ⦗ مهمة: {t['task_name']} (+24h) ⦘", callback_data=f"claim_task:{t['task_id']}"))

            markup.row(InlineKeyboardButton("🔙 ⦗ عودة للقائمة الرئيسية ⦘", callback_data="nav_home"))
            text = "<b>⏳ ⦗ مهام زيادة وقت التشغيل ⦘</b>\n\n◂ اختر إحدى المهام أدناه لتنفيذها والحصول على 24 ساعة إضافية لبوتاتك:"
            bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=markup)
            bot.answer_callback_query(call.id)

        elif data.startswith("claim_task:"):
            task_id = data.split(":")[1]
            task = db_query("SELECT * FROM time_tasks WHERE task_id = ? AND is_active = 1", (task_id,), fetch_one=True)
            if not task:
                bot.answer_callback_query(call.id, "⚠️ المهمة غير صالحة أو انتهت.", show_alert=True)
                return

            used = db_query("SELECT * FROM used_tokens WHERE token_id = ? AND user_id = ?", (task_id, user_id), fetch_one=True)
            if used:
                bot.answer_callback_query(call.id, "⚠️ لقد قمت بتنفيذ هذه المهمة مسبقاً!", show_alert=True)
                return

            text = f"""
<b>🔗 ⦗ تنفيذ مهمة كسب الوقت ⦘</b>
┃
┃ ıllıllı للحصول على 24 ساعة وقت تشغيل، يرجى التوجه 
┃ إلى الرابط المختصر أدناه وتخطيه للوصول للرابط الفريد:
┃
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
◂ <b>الرابط المختصر:</b>
{task['token_url']}

◂ بعد تجاوز الرابط المختصر والوصول للرمز الفريد، اضغط على الزر أدناه لتأكيد الكود وإضافة الساعات:
"""
            markup = InlineKeyboardMarkup()
            markup.row(InlineKeyboardButton("✅ ⦗ تأكيد إدخال الكود الفريد ⦘", callback_data=f"verify_task:{task_id}"))
            markup.row(InlineKeyboardButton("🔙 ⦗ عودة للمهام ⦘", callback_data="menu_tasks"))
            
            bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=markup)
            bot.answer_callback_query(call.id)

        elif data.startswith("verify_task:"):
            task_id = data.split(":")[1]
            bots = db_query("SELECT * FROM hosted_bots WHERE user_id = ?", (user_id,), fetch_all=True)
            if not bots:
                bot.answer_callback_query(call.id, "⚠️ ليس لديك أي بوتات لتضيف لها الوقت!", show_alert=True)
                return

            markup = InlineKeyboardMarkup()
            for b in bots:
                markup.row(InlineKeyboardButton(f"🤖 ⦗ {b['bot_name']} ⦘", callback_data=f"apply_time:{task_id}:{b['bot_id']}"))
            markup.row(InlineKeyboardButton("🔙 ⦗ عودة ⦘", callback_data="menu_tasks"))

            text = "<b>🤖 ⦗ اختر البوت الذي تريد إضافة الـ 24 ساعة له: ⦘</b>"
            bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=markup)
            bot.answer_callback_query(call.id)

        elif data.startswith("apply_time:"):
            parts = data.split(":")
            task_id, bot_id = parts[1], parts[2]
            
            used = db_query("SELECT * FROM used_tokens WHERE token_id = ? AND user_id = ?", (task_id, user_id), fetch_one=True)
            if used:
                bot.answer_callback_query(call.id, "⚠️ تم استخدام هذا الرابط مسبقاً!", show_alert=True)
                return

            db_query("INSERT INTO used_tokens (token_id, user_id) VALUES (?, ?)", (task_id, user_id), commit=True)
            db_query("UPDATE hosted_bots SET runtime_hours = runtime_hours + 24.0 WHERE bot_id = ?", (bot_id,), commit=True)

            bot.answer_callback_query(call.id, "🎉 بنجاح! تم إضافة 24 ساعة وقت تشغيل للبوت.", show_alert=True)
            call.data = f"manage_bot:{bot_id}"
            callback_router(call)

        # ==================== لوحة الأدمن المحدثة لإدارة VIP ====================
        elif data == "admin_main":
            if not is_admin:
                return
            text = """
<b>🔐 ⦗ لوحة تحكم المشرف المركزية ⦘</b>
┃
┃ ıllıllı مرحباً بك يا مشرف النظام. يمكنك منที่นี่ 
┃ إدارة حسابات الـ VIP، الرفع، والوقوت للبوتات.
┃
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
"""
            markup = InlineKeyboardMarkup()
            markup.row(InlineKeyboardButton("⭐ ⦗ ترقية مستخدم إلى VIP (بالآيدي) ⦘", callback_data="adm_make_vip"))
            markup.row(
                InlineKeyboardButton("🚀 ⦗ إضافة رصيد رفع للمستخدمين ⦘", callback_data="adm_add_uploads"),
                InlineKeyboardButton("⏳ ⦗ زيادة وقت للبوتات ⦘", callback_data="adm_add_time")
            )
            markup.row(
                InlineKeyboardButton("♾️ ⦗ تفعيل رفع/وقت غير محدود ⦘", callback_data="adm_unlimited_mode"),
                InlineKeyboardButton("📢 ⦗ إدارة قنوات الاشتراك ⦘", callback_data="adm_channels")
            )
            markup.row(
                InlineKeyboardButton("➕ ⦗ إنشاء مهمة وقت (CPA) ⦘", callback_data="adm_create_task"),
                InlineKeyboardButton("📊 ⦗ إحصائيات الخادم ⦘", callback_data="adm_stats")
            )
            markup.row(InlineKeyboardButton("🔙 ⦗ عودة للقائمة الرئيسية ⦘", callback_data="nav_home"))
            bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=markup)
            bot.answer_callback_query(call.id)

        elif data == "adm_make_vip":
            if not is_admin:
                return
            msg = bot.send_message(call.message.chat.id, "✍️ <b>أرسل آيدي المستخدم لجعله VIP فوراً:</b>\n\n<code>123456789</code>")
            bot.register_next_step_handler(msg, process_admin_make_vip)
            bot.answer_callback_query(call.id)

        elif data == "adm_add_uploads":
            if not is_admin:
                return
            msg = bot.send_message(call.message.chat.id, "✍️ <b>أرسل آيدي المستخدم وعدد صلاحيات الرفع بهذا الشكل:</b>\n\n<code>123456789 | 5</code>")
            bot.register_next_step_handler(msg, process_admin_add_uploads)
            bot.answer_callback_query(call.id)

        elif data == "adm_add_time":
            if not is_admin:
                return
            msg = bot.send_message(call.message.chat.id, "✍️ <b>أرسل (آيدي المستخدم) و(عدد الساعات الإضافية) بهذا الشكل:</b>\n\n<code>123456789 | 48</code>")
            bot.register_next_step_handler(msg, process_admin_add_time)
            bot.answer_callback_query(call.id)

        elif data == "adm_unlimited_mode":
            if not is_admin:
                return
            msg = bot.send_message(call.message.chat.id, "✍️ <b>اختر نوع التفعيل غير المحدود وأرسله بهذا الشكل:</b>\n\n• لجعل رفع المستخدم غير محدود:\n<code>uploads | 123456789</code>\n\n• لجعل جميع بوتات المستخدم بوقت غير محدود:\n<code>time | 123456789</code>")
            bot.register_next_step_handler(msg, process_admin_unlimited_mode)
            bot.answer_callback_query(call.id)

        elif data == "adm_create_task":
            if not is_admin:
                return
            msg = bot.send_message(call.message.chat.id, "✍️ <b>أرسل الآن اسم المهمة والرابط المختصر بهذا الشكل تماماً في رسالة واحدة:</b>\n\n<code>اسم المهمة | https://shortlink.com/xxxxx</code>")
            bot.register_next_step_handler(msg, process_admin_create_task)
            bot.answer_callback_query(call.id)

        elif data == "adm_channels":
            if not is_admin:
                return
            channels = db_query("SELECT * FROM force_channels", fetch_all=True)
            text = "<b>📢 ⦗ قنوات الاشتراك الإجباري الحالية ⦘</b>\n\n"
            markup = InlineKeyboardMarkup()
            for ch in channels:
                text += f"• <b>{ch['channel_title']}</b> (@{ch['channel_username']})\n"
                markup.row(InlineKeyboardButton(f"🗑️ حذف: {ch['channel_title']}", callback_data=f"adm_del_ch:{ch['channel_id']}"))
            
            markup.row(InlineKeyboardButton("➕ ⦗ إضافة قناة إجبارية جديدة ⦘", callback_data="adm_add_ch"))
            markup.row(InlineKeyboardButton("🔙 ⦗ عودة للوحة الأدمن ⦘", callback_data="admin_main"))
            bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=markup)
            bot.answer_callback_query(call.id)

        elif data == "adm_add_ch":
            if not is_admin:
                return
            msg = bot.send_message(call.message.chat.id, "✍️ <b>أرسل آيدي القناة ومعرفها بالعنوان بهذا الشكل في رسالة واحدة:</b>\n\n<code>-100xxxxxxxxxx | channel_username | عنوان القناة</code>")
            bot.register_next_step_handler(msg, process_admin_add_channel)
            bot.answer_callback_query(call.id)

        elif data.startswith("adm_del_ch:"):
            if not is_admin:
                return
            ch_id = data.split(":")[1]
            db_query("DELETE FROM force_channels WHERE channel_id = ?", (ch_id,), commit=True)
            bot.answer_callback_query(call.id, "🗑️ تم حذف القناة بنجاح.")
            
            call.data = "adm_channels"
            callback_router(call)

        elif data == "adm_stats":
            if not is_admin:
                return
            users_c = db_query("SELECT COUNT(*) as c FROM users", fetch_one=True)["c"]
            bots_c = db_query("SELECT COUNT(*) as c FROM hosted_bots", fetch_one=True)["c"]
            running_c = db_query("SELECT COUNT(*) as c FROM hosted_bots WHERE status = 'running'", fetch_one=True)["c"]
            vip_c = db_query("SELECT COUNT(*) as c FROM users WHERE is_vip = 1", fetch_one=True)["c"]
            
            text = f"""
<b>📊 ⦗ إحصائيات منصة الـ VPS الشاملة ⦘</b>
┃
┃ ◂ <b>إجمالي المستخدمين:</b> {users_c}
┃ ◂ <b>مشتركي الـ VIP ⭐:</b> {vip_c}
┃ ◂ <b>إجمالي البوتات المرفوعة:</b> {bots_c}
┃ ◂ <b>البوتات الشغالة حالياً:</b> {running_c} 🟢
┃
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
"""
            markup = InlineKeyboardMarkup()
            markup.row(InlineKeyboardButton("🔙 ⦗ عودة لوحة الأدمن ⦘", callback_data="admin_main"))
            bot.edit_message_text(text, call.message.chat.id, call.message.message_id, reply_markup=markup)
            bot.answer_callback_query(call.id)

    except Exception as err:
        logger.error(f"Error in callback router: {err}", exc_info=True)


# =====================================================================
# 10. ADMIN STEP HANDLERS (VIP, UPLOADS, TIME, UNLIMITED)
# =====================================================================

def process_admin_make_vip(message: Message):
    if message.from_user.id not in ADMIN_IDS:
        return
    try:
        target_id = int(message.text.strip())
        db_query("UPDATE users SET is_vip = 1, unlimited_uploads = 1 WHERE user_id = ?", (target_id,), commit=True)
        bot.reply_to(message, f"⭐ <b>تمت ترقية المستخدم {target_id} إلى VIP بنجاح!</b>\n◂ تم منحه صلاحيات رفع غير محدودة.")
        try:
            bot.send_message(target_id, "<b>💎 مبارك! تمت ترقية حسابك إلى رتبة (VIP ⭐) وأصبحت صلاحيات الرفع لديك غير محدودة!</b>")
        except Exception:
            pass
    except Exception as e:
        bot.reply_to(message, f"❌ حدث خطأ، تأكد من صحة الآيدي: {e}")


def process_admin_add_uploads(message: Message):
    if message.from_user.id not in ADMIN_IDS:
        return
    try:
        parts = message.text.split("|")
        target_id = int(parts[0].strip())
        amount = int(parts[1].strip())
        db_query("UPDATE users SET can_upload = can_upload + ? WHERE user_id = ?", (amount, target_id), commit=True)
        bot.reply_to(message, f"✅ <b>تمت إضافة {amount} صلاحية رفع للمستخدم {target_id} بنجاح.</b>")
    except Exception as e:
        bot.reply_to(message, f"❌ الصيغة خطأ. استخدم: <code>ID | Count</code>\nخطأ: {e}")


def process_admin_add_time(message: Message):
    if message.from_user.id not in ADMIN_IDS:
        return
    try:
        parts = message.text.split("|")
        target_id = int(parts[0].strip())
        hours = float(parts[1].strip())
        db_query("UPDATE hosted_bots SET runtime_hours = runtime_hours + ? WHERE user_id = ?", (hours, target_id), commit=True)
        bot.reply_to(message, f"✅ <b>تمت إضافة {hours} ساعة لجميع بوتات المستخدم {target_id} بنجاح.</b>")
    except Exception as e:
        bot.reply_to(message, f"❌ الصيغة خطأ. استخدم: <code>ID | Hours</code>\nخطأ: {e}")


def process_admin_unlimited_mode(message: Message):
    if message.from_user.id not in ADMIN_IDS:
        return
    try:
        parts = message.text.split("|")
        mode = parts[0].strip().lower()
        target_id = int(parts[1].strip())
        
        if mode == "uploads":
            db_query("UPDATE users SET unlimited_uploads = 1 WHERE user_id = ?", (target_id,), commit=True)
            bot.reply_to(message, f"♾️ <b>تم تفعيل الرفع غير المحدود للمستخدم {target_id}.</b>")
        elif mode == "time":
            db_query("UPDATE hosted_bots SET unlimited_time = 1 WHERE user_id = ?", (target_id,), commit=True)
            bot.reply_to(message, f"♾️ <b>تم تفعيل الوقت غير المحدود لجميع بوتات المستخدم {target_id}.</b>")
        else:
            bot.reply_to(message, "❌ وضع غير معروف. استخدم uploads أو time.")
    except Exception as e:
        bot.reply_to(message, f"❌ حدث خطأ: {e}")


def process_admin_create_task(message: Message):
    if message.from_user.id not in ADMIN_IDS:
        return
    try:
        parts = message.text.split("|")
        if len(parts) < 2:
            bot.reply_to(message, "❌ الصيغة غير صحيحة.")
            return
        
        task_name = parts[0].strip()
        short_url = parts[1].strip()
        task_id = uuid.uuid4().hex[:10]

        db_query(
            "INSERT INTO time_tasks (task_id, task_name, token_url, is_active, created_at) VALUES (?, ?, ?, 1, ?)",
            (task_id, task_name, short_url, datetime.now().isoformat()),
            commit=True
        )
        bot.reply_to(message, f"✅ <b>تم إنشاء المهمة بنجاح!</b>\n\n- الاسم: {task_name}\n- المعرف: <code>{task_id}</code>")
    except Exception as e:
        bot.reply_to(message, f"❌ حدث خطأ: {e}")


def process_admin_add_channel(message: Message):
    if message.from_user.id not in ADMIN_IDS:
        return
    try:
        parts = message.text.split("|")
        if len(parts) < 3:
            bot.reply_to(message, "❌ الصيغة غير صحيحة.")
            return
        
        ch_id = parts[0].strip()
        ch_username = parts[1].strip().replace("@", "")
        ch_title = parts[2].strip()

        db_query(
            "INSERT OR REPLACE INTO force_channels (channel_id, channel_username, channel_title) VALUES (?, ?, ?)",
            (ch_id, ch_username, ch_title),
            commit=True
        )
        bot.reply_to(message, f"✅ <b>تمت إضافة القناة الإجبارية بنجاح:</b> {ch_title}")
    except Exception as e:
        bot.reply_to(message, f"❌ حدث خطأ: {e}")


# =====================================================================
# 11. FILE UPLOAD & REAL PROCESS EXECUTION HANDLER
# =====================================================================

@bot.message_handler(content_types=['document'])
def handle_document_upload(message: Message):
    user_id = message.from_user.id
    
    if fetch_system_setting("maintenance_mode") == "on" and user_id not in ADMIN_IDS:
        bot.reply_to(message, "🛠️ المنصة في وضع الصيانة حالياً.")
        return

    if not check_user_force_subscribe(user_id):
        bot.reply_to(message, "⚠️ يجب الاشتراك في القنوات الإجبارية أولاً لاستخدام ميزة الاستضافة.")
        return

    user = db_query("SELECT * FROM users WHERE user_id = ?", (user_id,), fetch_one=True)
    
    # التحقق من صلاحيات الرفع (إن لم يكن محدوداً أو لديه رصيد رفع > 0)
    if user["unlimited_uploads"] == 0 and user["can_upload"] <= 0:
        bot.reply_to(message, "❌ <b>عذراً، لا تمتلك صلاحية رفع بوت جديد.</b>\n\n◂ قم بدعوة شخص واحد عبر <b>'نظام الإحالات'</b> لتحصل على صلاحية فورية أو تواصل لشراء VIP!")
        return

    doc = message.document
    if not doc:
        return

    raw_name = doc.file_name or "bot.py"
    filename = os.path.basename(raw_name)

    if doc.file_size and doc.file_size > MAX_FILE_SIZE:
        bot.reply_to(message, "❌ عذراً، حجم الملف أكبر من الحد المسموح (20MB).")
        return

    if not (filename.endswith(".py") or filename.endswith(".zip")):
        bot.reply_to(message, "❌ يُسمح فقط برفع ملفات بايثون <code>.py</code> أو ملفات مضغوطة <code>.zip</code>")
        return

    bot_id = uuid.uuid4().hex[:12]
    bot_folder = os.path.join(HOSTING_DIR, str(user_id), bot_id)
    os.makedirs(bot_folder, exist_ok=True)
    
    file_path = os.path.join(bot_folder, filename)
    log_path = os.path.join(LOGS_DIR, f"{bot_id}.log")

    try:
        file_info = bot.get_file(doc.file_id)
        downloaded = bot.download_file(file_info.file_path)
        with open(file_path, 'wb') as f:
            f.write(downloaded)
    except Exception as e:
        logger.error(f"Error downloading file: {e}", exc_info=True)
        bot.reply_to(message, "❌ حدث خطأ أثناء تحميل الملف من تيليجرام.")
        return

    # خصم 1 من صلاحيات الرفع إذا لم يكن محدود الرفع
    if user["unlimited_uploads"] == 0:
        db_query("UPDATE users SET can_upload = can_upload - 1 WHERE user_id = ?", (user_id,), commit=True)

    # حفظ البوت ومنحه 24 ساعة مجانية افتراضياً
    db_query(
        """
        INSERT INTO hosted_bots (bot_id, user_id, bot_name, file_path, log_path, pid, status, runtime_hours, unlimited_time, created_at)
        VALUES (?, ?, ?, ?, ?, 0, 'stopped', 24.0, 0, ?)
        """,
        (bot_id, user_id, filename, file_path, log_path, datetime.now().isoformat()),
        commit=True
    )

    success = start_bot_process(bot_id)

    if success:
        text = f"""
<b>🎉 ⦗ تم رفع واستضافة البوت بنجاح تام! ⦘</b>
┃
┃ ◂ <b>اسم البوت:</b> <code>{filename}</code>
┃ ◂ <b>وقت التشغيل المبدئي:</b> 24.0 ساعة مجانية ⏳
┃ ◂ <b>حالة الـ VPS:</b> يعمل في الخلفية بنجاح 🟢
┃
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
◂ يمكنك التحكم الكامل ببوتك وإدارته عبر قسم <b>"بوتاتي النشطة"</b>.
"""
    else:
        text = f"""
<b>⚠️ ⦗ تم رفع الملف ولكن واجهنا مشكلة في التشغيل ⦘</b>
┃
┃ ◂ تم حفظ البوت في قسم <b>"بوتاتي النشطة"</b>، يرجى مراجعة السجلات أو فحص الأخطاء.
┃
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
"""

    bot.reply_to(message, text, reply_markup=get_main_menu_markup(user_id in ADMIN_IDS))


# =====================================================================
# 12. ENTERPRISE POLLING STARTUP
# =====================================================================

def main():
    logger.info("🤖 Starting VPS Hosting Platform Engine...")
    backoff = 3
    while True:
        try:
            bot.remove_webhook()
            logger.info("Polling started successfully.")
            bot.infinity_polling(skip_pending=True, timeout=30, long_polling_timeout=20)
        except telebot.apihelper.ApiTelegramException as api_err:
            if api_err.error_code == 401:
                logger.critical("CRITICAL: Invalid Bot Token (401 Unauthorized). Please check BOT_TOKEN!")
                time.sleep(20)
            else:
                logger.error(f"Telegram API Error: {api_err}")
        except Exception as e:
            logger.error(f"Unexpected error in polling loop: {e}", exc_info=True)
        
        time.sleep(backoff)
        backoff = min(backoff * 2, 60)


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        logger.info("🛑 Platform stopped gracefully by administrator.")
        sys.exit(0)
