# -*- coding: utf-8 -*-
"""
نقطه‌ی شروع ربات ممبرگیر
=============================
اجرا با:
    python main.py
"""

import glob
import os
import sqlite3
import sys
import threading
import time

import telebot

import config
import database as db
from handlers import user as user_handlers
from handlers import payment as payment_handlers
from handlers import campaign as campaign_handlers
from handlers import admin as admin_handlers


def _backup_database_loop():
    """
    هر چند ساعت یه‌بار، یه نسخه‌ی پشتیبان امن (سازگار حتی اگه دیتابیس در
    حال استفاده باشه) از دیتابیس اصلی میگیره و توی یه پوشه‌ی جدا نگه
    میداره. فقط ۱۰ تای آخر رو نگه میداره تا فضای دیسک پر نشه. این کاملا
    جدا از فایل اصلیه، پس حتی اگه دیتابیس اصلی خراب بشه، این بکاپ‌ها
    سالم می‌مونن.
    """
    backup_dir = os.path.join(os.path.dirname(config.DB_PATH), "backups")
    os.makedirs(backup_dir, exist_ok=True)
    while True:
        try:
            ts = time.strftime("%Y%m%d_%H%M%S")
            dest_path = os.path.join(backup_dir, f"backup_{ts}.db")
            src_conn = sqlite3.connect(config.DB_PATH)
            dest_conn = sqlite3.connect(dest_path)
            src_conn.backup(dest_conn)
            dest_conn.close()
            src_conn.close()

            backups = sorted(glob.glob(os.path.join(backup_dir, "backup_*.db")))
            for old_backup in backups[:-10]:
                try:
                    os.remove(old_backup)
                except Exception:
                    pass
        except Exception as e:
            print(f"⚠️ خطا در گرفتن بکاپ خودکار: {e}")
        time.sleep(6 * 60 * 60)  # هر ۶ ساعت


def main():
    if config.BOT_TOKEN == "PUT_YOUR_BOT_TOKEN_HERE":
        print("❌ اول توکن ربات رو توی فایل config.py وارد کن!")
        sys.exit(1)

    db.init_db()

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

    bot = telebot.TeleBot(
        config.BOT_TOKEN,
        parse_mode=None,
        threaded=True,
        num_threads=30,  # پیش‌فرض فقط ۲ه - برای هزاران کاربر همزمان خیلی کمه
    )

    # این دو تا باید قبل از همه‌ی هندلرهای دیگه ثبت بشن - وگرنه کاربر
    # مسدودشده‌ای که منوی ربات از قبل براش باز مونده، همچنان می‌تونه از
    # همه‌ی امکانات (خرید، کسب کوین، تبلیغ کانال و ...) استفاده کنه، چون
    # قبلاً فقط دستور /start وضعیت مسدودی رو چک می‌کرد نه بقیه‌ی دکمه‌ها.
    @bot.message_handler(func=lambda m: db.is_banned(m.from_user.id))
    def _banned_message_guard(message):
        bot.send_message(message.chat.id, "⛔️ شما از استفاده از ربات مسدود شدید.")

    @bot.callback_query_handler(func=lambda c: db.is_banned(c.from_user.id))
    def _banned_callback_guard(call):
        bot.answer_callback_query(call.id, "⛔️ شما از استفاده از ربات مسدود شدید.", show_alert=True)

    user_handlers.register(bot)
    payment_handlers.register(bot)
    campaign_handlers.register(bot)
    admin_handlers.register(bot)
    # این باید بعد از همه‌ی هندلرهای بالا ثبت بشه - وگرنه ممکنه برچسب یه
    # دکمه‌ی سفارشی با ورودی متنیِ وسط یه مرحله‌ی دیگه (مثل مبلغ خرید) تداخل کنه
    user_handlers.register_custom_buttons(bot)

    # هندلر fallback برای پیام‌های ناشناخته که وسط هیچ مرحله‌ای نیستن
    @bot.message_handler(func=lambda m: True, content_types=["text"])
    def fallback(message):
        import keyboards as kb

        bot.send_message(
            message.chat.id,
            "متوجه نشدم 🤔 از دکمه‌های پایین استفاده کن.",
            reply_markup=kb.main_menu(message.from_user.id),
        )

    print("✅ ربات با موفقیت اجرا شد و در حال گوش دادن به پیام‌هاست...")

    while True:
        try:
            bot.infinity_polling(
                timeout=30,
                long_polling_timeout=30,
                allowed_updates=["message", "callback_query", "chat_member"],
            )
        except Exception as e:
            print(f"⚠️ خطا در polling: {e} — تلاش مجدد در ۵ ثانیه...")
            time.sleep(5)


if __name__ == "__main__":
    main()
