# Telegram Bot Fly-Fly для детей 9-12 лет
# Игра "Ловец" - сбор бабочек и рейтинги

import telebot
from telebot import apihelper
from requests.exceptions import RequestException
from telebot import types
from datetime import datetime
import sys
import os

# Добавляем родительскую папку в path для импортов
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))

# Ensure stdout/stderr use UTF-8 on Windows consoles to avoid UnicodeEncodeError
try:
    # Python 3.7+: reconfigure allows changing encoding for interactive consoles
    sys.stdout.reconfigure(encoding='utf-8')
    sys.stderr.reconfigure(encoding='utf-8')
except Exception:
    # ignore if reconfigure not available or fails
    pass

from config.config import (
    TELEGRAM_BOT_TOKEN,
    TELEGRAM_PROXY_URL,
    TELEGRAM_CONNECT_TIMEOUT,
    TELEGRAM_READ_TIMEOUT,
    POINTS_SCHOOL_COMPLETE,
    POINTS_REFERRAL_BONUS,
    ADMIN_ID,
    REQUIRED_GROUP_CHAT_ID,
    REQUIRED_GROUP_LINK,
)
try:
    from .database import Database
except Exception:
    # allow running file directly (not as package)
    from database import Database

try:
    from .school import SCHOOL_CURRICULUM, validate_answer, get_question
except Exception:
    from school import SCHOOL_CURRICULUM, validate_answer, get_question

# ============= ИНИЦИАЛИЗАЦИЯ =============
# Настройки сети/прокси для Telegram API (полезно на серверах с блокировкой)
if TELEGRAM_PROXY_URL:
    apihelper.proxy = {'https': TELEGRAM_PROXY_URL}
apihelper.REQUESTS_TIMEOUT = (TELEGRAM_CONNECT_TIMEOUT, TELEGRAM_READ_TIMEOUT)

bot = telebot.TeleBot(TELEGRAM_BOT_TOKEN)

# Безопасные обёртки, чтобы сетевые ошибки не останавливали polling
_orig_send_message = bot.send_message
_orig_send_video = bot.send_video


def _safe_call(fn, *args, **kwargs):
    try:
        return fn(*args, **kwargs)
    except RequestException as e:
        print(f"telegram request error: {e}")
        return None
    except Exception as e:
        print(f"telegram send error: {e}")
        return None


def safe_send_message(*args, **kwargs):
    return _safe_call(_orig_send_message, *args, **kwargs)


def safe_send_video(*args, **kwargs):
    return _safe_call(_orig_send_video, *args, **kwargs)


bot.send_message = safe_send_message
bot.send_video = safe_send_video
db = Database()
user_states = {}  # {user_id: {'state': 'school', 'question': 1}}


def attempt_award_referral(new_user_id: int):
    """Проверить и начислить реферальный бонус пригласившему.
    Условия:
    - Новый пользователь имеет поле `referred_by` (telegram_id пригласителя)
    - Пригласитель существует
    - Приглашённый ещё не учтён в `invited_friends` пригласителя
    - Если в конфиге указан REQUIRED_GROUP_CHAT_ID — приглашённый является членом этой группы
    """
    user = db.get_user(new_user_id)
    if not user:
        return

    referred_by = user.get('referred_by')
    if not referred_by:
        return

    inviter = db.get_user(referred_by)
    if not inviter:
        return

    invited = inviter.get('invited_friends', []) or []
    if new_user_id in invited:
        return

    # Проверяем членство в группе, если задана
    if REQUIRED_GROUP_CHAT_ID:
        chat_id = REQUIRED_GROUP_CHAT_ID
        # попробуем привести к int если это строка из цифр
        try:
            if isinstance(chat_id, str) and chat_id.lstrip('-').isdigit():
                chat_id = int(chat_id)
        except Exception:
            pass

        try:
            member = bot.get_chat_member(chat_id, new_user_id)
            if member.status not in ['member', 'creator', 'administrator']:
                return
        except Exception:
            # Не можем проверить — не начисляем
            return

    # Все условия выполнены — начисляем и помечаем
    db.add_points(referred_by, POINTS_REFERRAL_BONUS)
    invited.append(new_user_id)
    db.update_user(referred_by, invited_friends=invited)

    # Уведомляем пригласителя
    try:
        bot.send_message(referred_by, f"✨ {user.get('first_name', 'Друг')} присоединился! +{POINTS_REFERRAL_BONUS} очков.")
    except Exception:
        pass


# ============= КЛАВИАТУРЫ =============

def get_main_keyboard(user: dict):
    """Главное меню в зависимости от статуса пользователя"""
    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True, row_width=2)
    team_id = user.get('team_id')
    telegram_id = user['telegram_id']

    added_photo = False
    # Школа теперь необязательна — показываем кнопку, если не пройдено, но не блокируем меню
    if not user.get('school_completed'):
        keyboard.add(types.KeyboardButton("📚 Школа бабочковода флай-флай"))

    if team_id:
        # В стае
        keyboard.add(
            types.KeyboardButton("🦋 Поймать друга"),
            types.KeyboardButton("📊 Мои очки")
        )
        keyboard.add(
            types.KeyboardButton("🏆 Рейтинг"),
            types.KeyboardButton("📌 Стая")
        )
        if team_id == telegram_id:
            # Капитан
            keyboard.add(types.KeyboardButton("⚙️ Управлять стаей"))
            added_photo = True
        else:
            # Обычный участник
            added_photo = True
    else:
        # Не в стае
        keyboard.add(
            types.KeyboardButton("🦋 Поймать друга"),
            types.KeyboardButton("📊 Мои очки")
        )

    keyboard.add(types.KeyboardButton("🛒 Купить Бабочкарий"))
    keyboard.add(types.KeyboardButton("❓ Справка"))
    return keyboard


@bot.message_handler(func=lambda msg: msg.text == "🦋 Поймать друга")
def handle_catch_friend(message: types.Message):
    """Отправляет GIF при нажатии кнопки 'Поймать друга'"""
    chat_id = message.chat.id
    telegram_id = message.from_user.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        return

    # Путь к GIF в корне проекта
    gif_path = os.path.join(os.path.dirname(__file__), '..', 'bot-cat.mp4')

    if not os.path.exists(gif_path):
        bot.send_message(chat_id, "❌ GIF не найден на сервере.")
        return

    try:
        # Отправляем первое сообщение с инструкцией
        telegram_id = message.from_user.id
        referral_link = f"https://t.me/fly_fly_team_bot?start={telegram_id}"

        invite_text = (
            "🦋 Поймай друга в стаю бабочек Флай-Флай\n"
            "\n"
            "✨ и получи +5 баллов в рейтинге бабочководов Флай-Флай!\n"
            "\n"
            "📩 Для этого просто перешли следующее сообщение своим друзьям 👇\n\n"
            f"{referral_link}"
        )
        bot.send_message(chat_id, invite_text)

        # Отправляем второе сообщение с GIF и текстом приглашения
        replay_text = (
            "Привет! Приглашаю тебя в стаю бабочек 'Флай-Флай'\n"
            "Для этого перейди по ссылке: "
            f"{referral_link}"
        )

        # Отправляем GIF с увеличенным таймаутом
        gif_file = open(gif_path, 'rb')
        bot.send_animation(chat_id, gif_file, caption=replay_text, timeout=180)
        gif_file.close()

    except Exception as e:
        print(f"send_animation error: {e}")
        bot.send_message(chat_id, f"❌ Не удалось отправить GIF. Попробуй позже. Ошибка: {e}")


def get_school_keyboard(question_num: int):
    """Клавиатура для школы с вариантами ответов"""
    keyboard = types.InlineKeyboardMarkup()
    question = get_question(question_num)
    
    for idx, option in enumerate(question.options):
        keyboard.add(types.InlineKeyboardButton(
            option,
            callback_data=f"answer_{question_num}_{idx}"
        ))
    
    return keyboard


def get_team_menu_keyboard():
    """Меню информации о стае"""
    keyboard = types.InlineKeyboardMarkup()
    keyboard.add(types.InlineKeyboardButton("👥 Состав", callback_data="team_members"))
    keyboard.add(types.InlineKeyboardButton("📊 Статистика", callback_data="team_stats"))
    keyboard.add(types.InlineKeyboardButton("🔗 Ссылка приглашения", callback_data="team_link"))
    keyboard.add(types.InlineKeyboardButton("⬅️ Назад", callback_data="back_to_main"))
    return keyboard


# ============= СТАРТОВАЯ РЕГИСТРАЦИЯ =============

@bot.message_handler(commands=['start'])
def handle_start(message: types.Message):
    """Обработка команды /start с параметрами.
    Работает только в личных сообщениях.
    """
    chat_id = message.chat.id
    telegram_id = message.from_user.id
    
    # Игнорируем сообщения из групп
    if not is_private_chat(chat_id):
        return
    
    first_name = message.from_user.first_name or "Ловец"

    # Парсим параметры: /start 0 (владелец) или /start <id> (по реферальной ссылке)
    args = message.text.split()
    referred_by = None
    is_owner = False
    
    if len(args) > 1:
        param = args[1]
        if param == "0":
            is_owner = True
        else:
            try:
                referred_by = int(param)
            except ValueError:
                pass
    
    # Проверяем, есть ли пользователь
    user = db.get_user(telegram_id)
    
    if user:
        # Пользователь уже зарегистрирован
        keyboard = get_main_keyboard(user)
        bot.send_message(
            chat_id,
            f"👋 С возвращением, {user.get('first_name', 'Ловец')}!\n\n"
            f"⭐ Твои очки: {user.get('total_points', 0)}",
            reply_markup=keyboard
        )
    else:
        # Новый пользователь
        db.create_user(telegram_id, first_name, is_butterfly_owner=is_owner, referred_by=referred_by)
        # Попробуем начислить реферальный бонус приглашавшему (если выполнены условия)
        try:
            attempt_award_referral(telegram_id)
        except Exception:
            pass
        
        # Отправляем единое приветственное сообщение для первого запуска
        welcome = (
            "Привет! Добро пожаловать в стаю бабочек Флай-Флай 🦋\n"
            "Рады видеть тебя среди участников нашего конкурса ✨\n"
            "Чтобы начать участие, выполни первое условие:\n\n"
            "1️⃣ Подпишись на нашу группу\n"
            "👉 https://t.me/+2RjGyDueqqAyM2Ey\n\n"
            "2️⃣ После подписки отправь в ответ слово «Готово»\n\n"
            "🎁 И выиграй классные призы:\n\n"
            "🥇 Умную колонку Алису + настоящий «Бабочкарий Флай-Флай»\n"
            "🥈 Фитнес-браслет Xiaomi Smart Band 10 + настоящий «Бабочкарий Флай-Флай»\n"
            "🥉 Наушники JBL Tune 520 + настоящий «Бабочкарий Флай-Флай»\n\n"
            "Как только получим «Готово» и увидим подписку — подтвердим твоё участие 🏆\n\n"
            "Летим к победе вместе! 🦋✨"
        )

        user = db.get_user(telegram_id)
        keyboard = get_main_keyboard(user)
        bot.send_message(chat_id, welcome, reply_markup=keyboard)


# ============= ШКОЛА БАБОЧКОВОДА =============

@bot.message_handler(func=lambda msg: msg.text == "📚 Школа бабочковода флай-флай")
def start_school(message: types.Message):
    """Начало школы"""
    chat_id = message.chat.id
    telegram_id = message.from_user.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        return

    user = db.get_user(telegram_id)
    if not user:
        bot.send_message(chat_id, "❌ Сначала зарегистрируйся с /start")
        return
    
    if user.get('school_completed'):
        bot.send_message(chat_id, "✅ Ты уже прошёл Школу! 🎓")
        return
    
    user_states[telegram_id] = {'state': 'school', 'question': 1, 'correct': 0}
    question = get_question(1)
    
    learning_text = f"📖 Урок 1: {question.title}\n\n{question.learning_text}"
    bot.send_message(chat_id, learning_text)
    
    question_text = f"\n\n❓ {question.question_text}"
    bot.send_message(
        chat_id,
        question_text,
        reply_markup=get_school_keyboard(1)
    )


@bot.callback_query_handler(func=lambda call: call.data.startswith('answer_'))
def handle_school_answer(call: types.CallbackQuery):
    """Обработка ответа на вопрос"""
    telegram_id = call.from_user.id
    chat_id = call.message.chat.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        bot.answer_callback_query(call.id, "❌ Нужно подписаться на группу!", show_alert=True)
        return

    try:
        _, question_num, answer_idx = call.data.split('_')
        question_num = int(question_num)
        answer_idx = int(answer_idx)
        
        question = get_question(question_num)
        is_correct = (answer_idx == question.correct_answer)
        
        state = user_states.get(telegram_id, {})
        if is_correct:
            state['correct'] = state.get('correct', 0) + 1
        
        # Показываем объяснение
        if is_correct:
            feedback = f"✅ Правильно!\n\n{question.explanation}"
        else:
            feedback = f"❌ Неправильно!\n\n{question.explanation}"
        
        bot.send_message(call.message.chat.id, feedback)
        
        # Переходим к следующему вопросу
        if question_num < 5:
            next_question = get_question(question_num + 1)
            state['question'] = question_num + 1
            user_states[telegram_id] = state
            
            learning = f"📖 Урок {question_num + 1}: {next_question.title}\n\n{next_question.learning_text}"
            bot.send_message(call.message.chat.id, learning)
            
            question_text = f"\n\n❓ {next_question.question_text}"
            bot.send_message(
                call.message.chat.id,
                question_text,
                reply_markup=get_school_keyboard(question_num + 1)
            )
        else:
            # Школа завершена!
            db.mark_school_completed(telegram_id)
            user = db.get_user(telegram_id)
            db.add_points(telegram_id, POINTS_SCHOOL_COMPLETE)
            # Реферальный бонус теперь начисляется при условии присоединения к группе при старте,
            # поэтому снято автоматическое начисление здесь.
            
            completion = (
                f"🎓 **Поздравляем!** Ты прошёл Школу бабочковода!\n\n"
                f"⭐ +{POINTS_SCHOOL_COMPLETE} очков за школу\n"
                f"📊 Всего очков: {user.get('total_points', 0) + POINTS_SCHOOL_COMPLETE}"
            )
            
            keyboard = get_main_keyboard(db.get_user(telegram_id))
            bot.send_message(call.message.chat.id, completion, reply_markup=keyboard)
            
            user_states.pop(telegram_id, None)
        
        bot.answer_callback_query(call.id)
    
    except Exception as e:
        bot.answer_callback_query(call.id, "❌ Ошибка!", show_alert=True)


# ============= СТАИ =============

# Возможность создания стаи удалена — соответствующие команды отключены


@bot.message_handler(func=lambda msg: msg.text == "📌 Стая")
def show_team_menu(message: types.Message):
    """Меню информации о стае"""
    chat_id = message.chat.id
    telegram_id = message.from_user.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        return

    user = db.get_user(telegram_id)
    if not user or not user.get('team_id'):
        bot.send_message(chat_id, "❌ Ты не в стае!")
        return
    
    team_id = user['team_id']
    team = db.get_team(team_id)
    
    if not team:
        bot.send_message(chat_id, "❌ Стая не найдена!")
        return
    
    members = db.get_team_members(team_id)
    total_points = sum(m.get('total_points', 0) for m in members)
    position = db.get_team_ranking_position(team_id)
    position_text = f"#{position}" if position else "—"
    
    team_info = (
        f"🦋 **Стая '{team.get('team_name', 'Без названия')}'**\n\n"
        f"👨‍💼 Капитан: {team.get('captain_name', '?')}\n"
        f"👥 Участников: {team.get('members_count', 0)}\n"
        f"⭐ Очков: {team.get('total_points', 0)}\n"
        f"🏅 Место в рейтинге: {position_text}\n\n"
        f"🤖 Бот: @fly_fly_team_bot"
    )
    
    keyboard = get_team_menu_keyboard()
    # Кнопка выхода из стаи (только для участников)
    keyboard.add(types.InlineKeyboardButton("🚪 Выйти из стаи", callback_data="leave_team"))

    bot.send_message(chat_id, team_info, reply_markup=keyboard)


@bot.callback_query_handler(func=lambda call: call.data.startswith('team_'))
def handle_team_menu(call: types.CallbackQuery):
    """Обработка меню стаи"""
    telegram_id = call.from_user.id
    chat_id = call.message.chat.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        bot.answer_callback_query(call.id, "❌ Нужно подписаться на группу!", show_alert=True)
        return

    user = db.get_user(telegram_id)

    if not user or not user.get('team_id'):
        bot.answer_callback_query(call.id, "❌ Ты не в стае!", show_alert=True)
        return
    
    if call.data == "team_members":
        team_id = user['team_id']
        members = db.get_team_members(team_id)
        
        members_list = "\n".join([
            f"👤 {m.get('first_name', '?')} — {m.get('total_points', 0)} ⭐"
            for m in members
        ])
        
        text = f"👥 **Участники стаи:**\n\n{members_list}"
        bot.send_message(call.message.chat.id, text, reply_markup=get_team_menu_keyboard())
    
    elif call.data == "team_stats":
        team_id = user['team_id']
        team = db.get_team(team_id)
        
        if not team:
            bot.answer_callback_query(call.id, "❌ Ошибка стаи!", show_alert=True)
            return

        team_pos = db.get_team_ranking_position(team_id)
        team_pos_text = f"#{team_pos}" if team_pos else "—"

        text = (
            f"📊 **Статистика стаи '{team.get('team_name')}'**\n\n"
            f"👥 Участников: {team.get('members_count', 0)}\n"
            f"⭐ Очков: {team.get('total_points', 0)}\n"
            f"🏅 Место: {team_pos_text}\n\n"
            f"🤖 Бот: @fly_fly_team_bot"
        )
        bot.send_message(call.message.chat.id, text, reply_markup=get_team_menu_keyboard())
    
    elif call.data == "team_link":
        team_id = user['team_id']
        referral_link = f"https://t.me/fly_fly_team_bot?start={team_id}"
        text = f"🔗 Ссылка приглашения:\n\n{referral_link}\n\n🤖 Бот: @fly_fly_team_bot"
        bot.send_message(call.message.chat.id, text, reply_markup=get_team_menu_keyboard())
    
    elif call.data == "back_to_main":
        user = db.get_user(telegram_id)
        keyboard = get_main_keyboard(user)
        bot.send_message(call.message.chat.id, "⬅️ Вернулись в меню", reply_markup=keyboard)
    
    bot.answer_callback_query(call.id)


@bot.callback_query_handler(func=lambda call: call.data in ['leave_team', 'leave_confirm', 'leave_cancel'])
def handle_leave_team(call: types.CallbackQuery):
    """Обработка выхода из стаи"""
    telegram_id = call.from_user.id
    chat_id = call.message.chat.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        bot.answer_callback_query(call.id, "❌ Нужно подписаться на группу!", show_alert=True)
        return

    user = db.get_user(telegram_id)

    if not user or not user.get('team_id'):
        bot.answer_callback_query(call.id, "❌ Ты не в стае!", show_alert=True)
        return

    team_id = user['team_id']
    team = db.get_team(team_id)
    team_name = team.get('team_name') if team else (db.get_user(team_id) or {}).get('team_name') or 'Без названия'

    if call.data == 'leave_team':
        # Капитан не может просто покинуть стаю
        if user.get('team_id') == telegram_id:
            bot.answer_callback_query(call.id, "❌ Капитан не может покинуть стаю. Используй 'Разойти стаю'", show_alert=True)
            return

        keyboard = types.InlineKeyboardMarkup()
        keyboard.add(types.InlineKeyboardButton("✅ Да, хочу выйти", callback_data='leave_confirm'))
        keyboard.add(types.InlineKeyboardButton("❌ Отмена", callback_data='leave_cancel'))

        bot.send_message(call.message.chat.id, f"Ты хочешь покинуть стаю {team_name}", reply_markup=keyboard)

    elif call.data == 'leave_cancel':
        keyboard = get_team_menu_keyboard()
        bot.send_message(call.message.chat.id, "⬅️ Вернулись в меню стаи", reply_markup=keyboard)

    elif call.data == 'leave_confirm':
        # Выполняем выход
        success = db.remove_member_from_team(team_id, telegram_id)
        if success:
            user = db.get_user(telegram_id)
            keyboard = get_main_keyboard(user)
            bot.send_message(call.message.chat.id, f"✅ Ты покинул стаю {team_name}", reply_markup=keyboard)
        else:
            bot.send_message(call.message.chat.id, "❌ Не удалось выйти из стаи. Попробуй позже.")

    bot.answer_callback_query(call.id)


@bot.callback_query_handler(func=lambda call: call.data.startswith('award_'))
def handle_award_callbacks(call: types.CallbackQuery):
    """Обработка кнопок начисления очков модератором"""
    admin_id = ADMIN_ID
    caller_id = call.from_user.id
    chat_id = call.message.chat.id
    telegram_id = call.from_user.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        bot.answer_callback_query(call.id, "❌ Нужно подписаться на группу!", show_alert=True)
        return

    if caller_id != admin_id:
        bot.answer_callback_query(call.id, "❌ Нет доступа", show_alert=True)
        return

    # parse callback
    try:
        parts = call.data.split('_')  # e.g. award_15_12345
        action = parts[1]
        target_id = int(parts[2])
    except Exception:
        bot.answer_callback_query(call.id, "❌ Неправильные данные", show_alert=True)
        return

    if action == 'reject':
        # Просто уведомляем и убираем кнопки
        bot.edit_message_caption(chat_id=call.message.chat.id, message_id=call.message.message_id, caption=(call.message.caption + "\n\n❌ Отклонено"))
        bot.send_message(target_id, "❌ Ваше фото не прошло модерацию.")
        bot.answer_callback_query(call.id, "Отклонено")
        return

    points = 15 if action == '15' else 5 if action == '5' else 0
    if points <= 0:
        bot.answer_callback_query(call.id, "❌ Неправильное количество очков", show_alert=True)
        return

    # Начисляем очки
    db.add_points(target_id, points)

    # Обновляем подписанный пост у модератора
    try:
        bot.edit_message_caption(chat_id=call.message.chat.id, message_id=call.message.message_id, caption=(call.message.caption + f"\n\n✅ Начислено {points} очков пользователю {target_id}"))
    except:
        pass

    # Уведомления
    bot.send_message(target_id, f"✨ Модератор начислил тебе +{points} очков за фото!")
    bot.send_message(call.message.chat.id, f"✅ Пользователю {target_id} начислено +{points} очков.")
    bot.answer_callback_query(call.id)


@bot.message_handler(func=lambda msg: msg.text == "⚙️ Управлять стаей")
def manage_team(message: types.Message):
    """Управление стаей (для капитана)"""
    chat_id = message.chat.id
    telegram_id = message.from_user.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        return

    user = db.get_user(telegram_id)
    if not user or user.get('team_id') != telegram_id:
        bot.send_message(chat_id, "❌ Ты не капитан стаи!")
        return
    
    team = db.get_team(user['team_id'])
    text = f"⚙️ **Управление стаей '{team.get('team_name')}'**\n\nВыбери действие:"
    
    keyboard = types.InlineKeyboardMarkup()
    keyboard.add(types.InlineKeyboardButton("✏️ Изменить название", callback_data="manage_rename"))
    keyboard.add(types.InlineKeyboardButton("👥 Исключить участника", callback_data="manage_remove"))
    keyboard.add(types.InlineKeyboardButton("📊 Рейтинг участников", callback_data="manage_rating"))
    keyboard.add(types.InlineKeyboardButton("🚫 Разойти стаю", callback_data="manage_disband"))
    keyboard.add(types.InlineKeyboardButton("⬅️ Назад", callback_data="back_menu"))
    
    bot.send_message(chat_id, text, reply_markup=keyboard)


@bot.callback_query_handler(func=lambda call: call.data.startswith('manage_') or call.data.startswith('remove_') or call.data == 'disband_confirm' or call.data == 'back_menu')
def handle_manage_team(call: types.CallbackQuery):
    """Обработка управления стаей"""
    telegram_id = call.from_user.id
    chat_id = call.message.chat.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        bot.answer_callback_query(call.id, "❌ Нужно подписаться на группу!", show_alert=True)
        return

    user = db.get_user(telegram_id)

    # Для back_menu не нужна проверка капитана
    if call.data == "back_menu":
        user = db.get_user(telegram_id)
        keyboard = get_main_keyboard(user)
        bot.send_message(call.message.chat.id, "⬅️ Вернулись в меню", reply_markup=keyboard)
        bot.answer_callback_query(call.id)
        return
    
    if not user or user.get('team_id') != telegram_id:
        bot.answer_callback_query(call.id, "❌ Ты не капитан!", show_alert=True)
        return
    
    team_id = user['team_id']
    
    if call.data == "manage_rename":
        msg = bot.send_message(call.message.chat.id, "📝 Введи новое название стаи (максимум 30 символов):")
        bot.register_next_step_handler(msg, process_rename_team)
    
    elif call.data == "manage_remove":
        team = db.get_team(team_id)
        members = db.get_team_members(team_id)
        
        if len(members) <= 1:
            bot.answer_callback_query(call.id, "❌ В стае только ты!", show_alert=True)
            return
        
        keyboard = types.InlineKeyboardMarkup()
        for member in members:
            if member['telegram_id'] != telegram_id:
                keyboard.add(types.InlineKeyboardButton(
                    f"{member.get('first_name', '?')} ({member.get('total_points', 0)} ⭐)",
                    callback_data=f"remove_{member['telegram_id']}"
                ))
        keyboard.add(types.InlineKeyboardButton("⬅️ Назад", callback_data="back_menu"))
        
        bot.send_message(call.message.chat.id, "👥 Выбери участника для исключения:", reply_markup=keyboard)
    
    elif call.data == "manage_rating":
        team = db.get_team(team_id)
        members = db.get_team_members(team_id)
        members_sorted = sorted(members, key=lambda x: x.get('total_points', 0), reverse=True)
        
        rating_text = f"📊 **Рейтинг участников стаи '{team.get('team_name')}'**\n\n"
        for idx, member in enumerate(members_sorted, 1):
            is_captain = "👑" if member['telegram_id'] == team_id else ""
            rating_text += f"{idx}. {member.get('first_name', '?')} — {member.get('total_points', 0)} ⭐ {is_captain}\n"
        
        keyboard = types.InlineKeyboardMarkup()
        keyboard.add(types.InlineKeyboardButton("⬅️ Назад", callback_data="back_menu"))
        
        bot.send_message(call.message.chat.id, rating_text, reply_markup=keyboard)
    
    elif call.data == "manage_disband":
        keyboard = types.InlineKeyboardMarkup()
        keyboard.add(types.InlineKeyboardButton("✅ Да, разойти", callback_data="disband_confirm"))
        keyboard.add(types.InlineKeyboardButton("❌ Отмена", callback_data="back_menu"))
        
        bot.send_message(
            call.message.chat.id,
            "⚠️ Ты уверен? Все участники выйдут из стаи!",
            reply_markup=keyboard
        )
    
    elif call.data == "disband_confirm":
        db.disband_team(team_id)
        user = db.get_user(telegram_id)
        keyboard = get_main_keyboard(user)
        
        bot.send_message(
            call.message.chat.id,
            "🚫 Стая разойдена! Все участники выведены.",
            reply_markup=keyboard
        )
    
    elif call.data.startswith("remove_"):
        try:
            member_id = int(call.data.split("_")[1])
            db.remove_member_from_team(team_id, member_id)
            
            member = db.get_user(member_id)
            bot.send_message(
                call.message.chat.id,
                f"✅ {member.get('first_name', '?')} исключён из стаи!"
            )
            
            # Показываем меню управления заново
            team = db.get_team(team_id)
            text = f"⚙️ **Управление стаей '{team.get('team_name')}'**\n\nВыбери действие:"
            
            keyboard = types.InlineKeyboardMarkup()
            keyboard.add(types.InlineKeyboardButton("✏️ Изменить название", callback_data="manage_rename"))
            keyboard.add(types.InlineKeyboardButton("👥 Исключить участника", callback_data="manage_remove"))
            keyboard.add(types.InlineKeyboardButton("📊 Рейтинг участников", callback_data="manage_rating"))
            keyboard.add(types.InlineKeyboardButton("🚫 Разойти стаю", callback_data="manage_disband"))
            keyboard.add(types.InlineKeyboardButton("⬅️ В главное меню", callback_data="back_to_main_menu"))
            
            bot.send_message(call.message.chat.id, text, reply_markup=keyboard)
        except (ValueError, IndexError) as e:
            bot.answer_callback_query(call.id, "❌ Ошибка при исключении!", show_alert=True)
    
    bot.answer_callback_query(call.id)


@bot.callback_query_handler(func=lambda call: call.data == "back_menu")
def handle_back_menu(call: types.CallbackQuery):
    """Обработка кнопки 'Назад' в меню управления стаей"""
    telegram_id = call.from_user.id
    chat_id = call.message.chat.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        bot.answer_callback_query(call.id, "❌ Нужно подписаться на группу!", show_alert=True)
        return

    user = db.get_user(telegram_id)

    if user and user.get('team_id') == telegram_id:
        # Капитан - показываем управление стаей
        team = db.get_team(user['team_id'])
        text = f"⚙️ **Управление стаей '{team.get('team_name')}'**\n\nВыбери действие:"
        
        keyboard = types.InlineKeyboardMarkup()
        keyboard.add(types.InlineKeyboardButton("✏️ Изменить название", callback_data="manage_rename"))
        keyboard.add(types.InlineKeyboardButton("👥 Исключить участника", callback_data="manage_remove"))
        keyboard.add(types.InlineKeyboardButton("📊 Рейтинг участников", callback_data="manage_rating"))
        keyboard.add(types.InlineKeyboardButton("🚫 Разойти стаю", callback_data="manage_disband"))
        keyboard.add(types.InlineKeyboardButton("⬅️ В главное меню", callback_data="back_to_main_menu"))
        
        bot.send_message(call.message.chat.id, text, reply_markup=keyboard)
    else:
        # Обычный пользователь - вернись в главное меню
        user = db.get_user(telegram_id)
        keyboard = get_main_keyboard(user)
        bot.send_message(call.message.chat.id, "⬅️ Вернулись в меню", reply_markup=keyboard)
    
    bot.answer_callback_query(call.id)


@bot.callback_query_handler(func=lambda call: call.data == "back_to_main_menu")
def handle_back_to_main(call: types.CallbackQuery):
    """Обработка кнопки 'В главное меню'"""
    telegram_id = call.from_user.id
    chat_id = call.message.chat.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        bot.answer_callback_query(call.id, "❌ Нужно подписаться на группу!", show_alert=True)
        return

    user = db.get_user(telegram_id)
    keyboard = get_main_keyboard(user)
    bot.send_message(call.message.chat.id, "⬅️ Вернулись в меню", reply_markup=keyboard)
    bot.answer_callback_query(call.id)


def process_rename_team(message: types.Message):
    """Обработка переименования стаи"""
    chat_id = message.chat.id
    telegram_id = message.from_user.id
    new_name = message.text.strip()
    
    if len(new_name) > 30:
        msg = bot.send_message(chat_id, "❌ Слишком длинное имя! Попробуй снова:")
        bot.register_next_step_handler(msg, process_rename_team)
        return
    
    if len(new_name) < 2:
        msg = bot.send_message(chat_id, "❌ Имя слишком короткое! Попробуй снова:")
        bot.register_next_step_handler(msg, process_rename_team)
        return
    
    db.update_team_name(telegram_id, new_name)
    
    user = db.get_user(telegram_id)
    keyboard = get_main_keyboard(user)
    
    bot.send_message(
        chat_id,
        f"✅ Стая переименована на '{new_name}'!",
        reply_markup=keyboard
    )



# ============= ОЧКИ И РЕЙТИНГ =============

@bot.message_handler(func=lambda msg: msg.text == "📊 Мои очки")
def show_my_stats(message: types.Message):
    """Показать мои очки"""
    chat_id = message.chat.id
    telegram_id = message.from_user.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        return

    user = db.get_user(telegram_id)
    if not user:
        bot.send_message(chat_id, "❌ Сначала зарегистрируйся!")
        return
    position = db.get_user_ranking_position(telegram_id)

    text = (
        f"📊 **Твои очки**\n\n"
        f"👤 Имя: {user.get('first_name')}\n"
        f"⭐ Твои очки: {user.get('total_points', 0)}\n"
        f"🏅 Место в рейтинге: #{position}\n\n"
        f"🤖 Бот: @fly_fly_team_bot"
    )

    keyboard = get_main_keyboard(user)
    # Также показываем Топ-10 ловцов под личной статистикой
    top_users = db.get_users_ranking()
    ranking_text = "\n🏆 Топ-10 ловцов:\n"
    for idx, u in enumerate(top_users[:10], 1):
        ranking_text += f"{idx}. {u.get('first_name', '?')} — {u.get('total_points', 0)} ⭐\n"

    bot.send_message(chat_id, text + ranking_text, reply_markup=keyboard)


@bot.message_handler(func=lambda msg: msg.text == "🏆 Рейтинг")
def show_ranking(message: types.Message):
    """Показать рейтинг"""
    chat_id = message.chat.id
    telegram_id = message.from_user.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        return

    users = db.get_users_ranking()
    ranking_text = "🏆 **Топ-10 ловцов**\n\n"
    
    for idx, user in enumerate(users[:10], 1):
        ranking_text += f"{idx}. {user.get('first_name', '?')} — {user.get('total_points', 0)} ⭐\n"
    
    user = db.get_user(telegram_id)
    position = db.get_user_ranking_position(telegram_id)
    
    ranking_text += f"\n👤 Твоё место: #{position}\n\n🤖 Бот: @fly_fly_team_bot"
    
    keyboard = get_main_keyboard(user)
    bot.send_message(chat_id, ranking_text, reply_markup=keyboard)


@bot.message_handler(content_types=['photo'])
def handle_photo(message: types.Message):
    """Обработка присланного фото — пересылка модератору с кнопками для начисления очков"""
    telegram_id = message.from_user.id
    chat_id = message.chat.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        return

    state = user_states.get(telegram_id, {})

    # Принимаем фото только если ждём его от пользователя
    if not state.get('awaiting_photo'):
        return

    # Сохраняем file_id и очищаем состояние
    file_id = message.photo[-1].file_id
    user_states.pop(telegram_id, None)

    # Кому отправлять — берем ADMIN_ID из конфига или дефолт
    admin_id = ADMIN_ID

    caption = f"📸 Фото от {message.from_user.first_name} (ID {telegram_id})\n\nНажми кнопку, чтобы начислить очки."
    keyboard = types.InlineKeyboardMarkup()
    keyboard.add(types.InlineKeyboardButton("Дать 15 баллов", callback_data=f"award_15_{telegram_id}"))
    keyboard.add(types.InlineKeyboardButton("Дать 5 баллов", callback_data=f"award_5_{telegram_id}"))
    keyboard.add(types.InlineKeyboardButton("Отклонить", callback_data=f"award_reject_{telegram_id}"))

    try:
        bot.send_photo(admin_id, file_id, caption=caption, reply_markup=keyboard)
        bot.send_message(telegram_id, "✅ Фото отправлено на проверку модератору.")
    except Exception as e:
        bot.send_message(telegram_id, "❌ Не удалось отправить фото на проверку. Попробуй позже.")


@bot.message_handler(func=lambda msg: msg.text == "🛒 Купить Бабочкарий")
def buy_butterfly_farm(message: types.Message):
    """Показать ссылку на покупку Бабочкария"""
    chat_id = message.chat.id
    telegram_id = message.from_user.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        return

    url = "https://fly-fly.ru/butterctary?utm_source=tg_team_bot"

    keyboard = types.InlineKeyboardMarkup()
    keyboard.add(types.InlineKeyboardButton("Купить Бабочкарий", url=url))

    bot.send_message(chat_id, "Перейди по ссылке, чтобы приобрести Бабочкарий:", reply_markup=keyboard)


# ============= СПРАВКА =============

@bot.message_handler(func=lambda msg: msg.text == "❓ Справка")
def show_help(message: types.Message):
    """Справка по игре"""
    chat_id = message.chat.id
    telegram_id = message.from_user.id

    # Проверяем подписку
    if not is_user_subscribed(telegram_id, chat_id):
        return

    help_text = (
        "❓ **Справка - Fly-Fly**\n\n"
        "🦋 Ловец бабочек — ты!\n\n"
        "📚 Школа: Пройди 5 уроков → +10 ⭐\n"
        "🎪 Стая: Создай команду или присоединись\n"
        "🤝 Друзья: Приглашай друзей → +5 ⭐ за каждого\n"
        "🏆 Рейтинг: Соревнуйся с другими!\n\n"
        "🤖 Бот: @fly_fly_team_bot"
    )
    
    user = db.get_user(telegram_id)
    keyboard = get_main_keyboard(user)
    bot.send_message(chat_id, help_text, reply_markup=keyboard)


# ============= ПРОВЕРКА ПОДПИСКИ НА ГРУППУ =============

def is_private_chat(chat_id: int) -> bool:
    """Проверяет, что сообщение пришло из личного чата (не из группы)"""
    return chat_id > 0


def check_user_in_group(telegram_id: int) -> bool:
    """Проверяет, состоит ли пользователь в требуемой группе"""
    if not REQUIRED_GROUP_CHAT_ID:
        return True  # Если ID группы не настроен — пропускаем проверку

    try:
        member = bot.get_chat_member(REQUIRED_GROUP_CHAT_ID, telegram_id)
        return member.status in ['member', 'administrator', 'creator']
    except Exception:
        # Если ошибка проверки — считаем что не подписан
        return False


def send_subscription_required(chat_id: int):
    """Отправляет сообщение о необходимости подписки"""
    bot.send_message(
        chat_id,
        "🦋 **Доступ только для подписчиков!** 🦋\n\n"
        "Чтобы использовать все функции бота, нужно быть подписанным на нашу группу:\n\n"
        "👉 " + REQUIRED_GROUP_LINK + "\n\n"
        "Подпишись и попробуй снова! ✨",
        parse_mode='Markdown'
    )


def is_user_subscribed(telegram_id: int, chat_id: int) -> bool:
    """Проверяет подписку и отправляет уведомление, если не подписан.
    Работает только в личных сообщениях.
    """
    # Игнорируем сообщения из групп
    if not is_private_chat(chat_id):
        return False
    
    if not check_user_in_group(telegram_id):
        send_subscription_required(chat_id)
        return False
    return True


@bot.message_handler(func=lambda msg: msg.text.lower() in ['готово', 'готово!'])
def handle_gotovo(message: types.Message):
    """Обработка сообщения «Готово» — проверка подписки на группу.
    Работает только в личных сообщениях.
    """
    chat_id = message.chat.id
    telegram_id = message.from_user.id

    # Игнорируем сообщения из групп
    if not is_private_chat(chat_id):
        return

    user = db.get_user(telegram_id)
    if not user:
        bot.send_message(chat_id, "❌ Сначала зарегистрируйся с /start")
        return

    # Проверяем подписку
    if check_user_in_group(telegram_id):
        # Пользователь подписан — подтверждаем участие
        keyboard = get_main_keyboard(user)
        bot.send_message(
            chat_id,
            "✨ **Отлично! Мы видели твою подписку!** 🦋\n\n"
            "Твоё участие в конкурсе подтверждено! 🏆\n\n"
            "Теперь ты можешь:\n"
            "• Ловить друзей и приглашать в стаю\n"
            "• Выполнять задания и получать очки\n"
            "• Соревноваться за классные призы!\n\n"
            "Летим к победе вместе! 🦋✨",
            reply_markup=keyboard,
            parse_mode='Markdown'
        )
    else:
        # Пользователь не подписан
        bot.send_message(
            chat_id,
            "🦋 **Кажется, мы тебя потеряли** 🦋\n\n"
            "Мы получили сообщение «Готово», но пока не видим подписку на нашу группу 🤍\n\n"
            "Чтобы участие засчиталось, нужно:\n"
            "1️⃣ Подписаться на группу\n"
            "👉 " + REQUIRED_GROUP_LINK + "\n"
            "2️⃣ И после этого снова отправить слово «Готово»\n\n"
            "Как только увидим подписку — сразу подтвердим участие ✨\n\n"
            "Ждём тебя в стае Флай-Флай 🦋",
            parse_mode='Markdown'
        )


# ============= ОБРАБОТЧИК НЕИЗВЕСТНЫХ КОМАНД =============

@bot.message_handler(func=lambda msg: True)
def handle_unknown(message: types.Message):
    """Обработка неизвестных команд.
    Работает только в личных сообщениях.
    """
    chat_id = message.chat.id
    telegram_id = message.from_user.id

    # Игнорируем сообщения из групп
    if not is_private_chat(chat_id):
        return

    user = db.get_user(telegram_id)
    if user:
        keyboard = get_main_keyboard(user)
        bot.send_message(
            chat_id,
            "🤔 Не понимаю. Используй меню 👇",
            reply_markup=keyboard
        )


# ============= ЗАПУСК БОТА =============

if __name__ == "__main__":
    print("🦋 Бот Fly-Fly запущен!")
    print("🤖 @fly_fly_team_bot")
    print("Ожидаю сообщений...\n")
    
    try:
        bot.infinity_polling()
    except Exception as e:
        print(f"❌ Ошибка: {e}")
