"""
Telegram бот для уведомлений и интеграции.
"""
import logging
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, ReplyKeyboardMarkup, KeyboardButton
from telegram.ext import (
    Application,
    CommandHandler,
    CallbackQueryHandler,
    MessageHandler,
    filters,
    ContextTypes,
)
from django.conf import settings
from django.utils import timezone
from asgiref.sync import sync_to_async

logger = logging.getLogger(__name__)


def get_main_keyboard(role=None):
    """
    Получить основную клавиатуру в зависимости от роли.
    
    Args:
        role: Роль пользователя ('mentor', 'client', 'parent', None)
    
    Returns:
        ReplyKeyboardMarkup: Клавиатура с кнопками
    """
    if role == 'mentor':
        keyboard = [
            [KeyboardButton("📅 Расписание"), KeyboardButton("📚 Следующее занятие")],
            [KeyboardButton("📝 Домашние задания"), KeyboardButton("👥 Клиенты")],
            [KeyboardButton("📊 Статистика"), KeyboardButton("⚙️ Настройки")],
            [KeyboardButton("ℹ️ Статус"), KeyboardButton("❓ Помощь")]
        ]
    elif role == 'client':
        keyboard = [
            [KeyboardButton("📅 Моё расписание"), KeyboardButton("📚 Следующее занятие")],
            [KeyboardButton("📝 Мои задания"), KeyboardButton("📊 Мой прогресс")],
            [KeyboardButton("⚙️ Настройки"), KeyboardButton("❓ Помощь")]
        ]
    elif role == 'parent':
        keyboard = [
            [KeyboardButton("📅 Расписание детей"), KeyboardButton("📚 Следующее занятие")],
            [KeyboardButton("📝 Задания детей"), KeyboardButton("⚙️ Настройки")],
            [KeyboardButton("ℹ️ Статус"), KeyboardButton("❓ Помощь")]
        ]
    else:
        # Для не связанных пользователей
        keyboard = [
            [KeyboardButton("🔗 Связать аккаунт"), KeyboardButton("❓ Помощь")]
        ]
    
    return ReplyKeyboardMarkup(keyboard, resize_keyboard=True, one_time_keyboard=False)


async def get_user_keyboard(telegram_id):
    """
    Получить клавиатуру для пользователя по его telegram_id.
    
    Args:
        telegram_id: ID пользователя в Telegram
    
    Returns:
        ReplyKeyboardMarkup: Клавиатура с кнопками
    """
    from apps.users.models import User
    db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
    role = db_user.role if db_user else None
    return get_main_keyboard(role)


# Текст кнопки «Назад» в панели списка заданий
HOMEWORK_LIST_BACK_BUTTON = "◀️ Назад в меню"

# Кнопки для «Мой прогресс»
PROGRESS_BACK_TO_MENU = "◀️ В меню"
PROGRESS_PERIOD_WEEK = "📅 За текущую неделю"
PROGRESS_PERIOD_30 = "📅 За последние 30 дней"
PROGRESS_PERIOD_ALL = "📅 За всё время"
PROGRESS_BACK_SUBJECT = "◀️ К выбору предмета"


def make_homework_list_keyboard(homeworks):
    """
    Собрать клавиатуру панели со списком заданий (кнопки в панели Telegram).
    
    Args:
        homeworks: список объектов Homework
    
    Returns:
        (ReplyKeyboardMarkup, dict): клавиатура и маппинг текст_кнопки -> homework_id
    """
    mapping = {}
    rows = []
    for idx, hw in enumerate(homeworks, 1):
        btn_text = f"📝 Задание {idx}"
        mapping[btn_text] = hw.id
        rows.append([KeyboardButton(btn_text)])
    rows.append([KeyboardButton(HOMEWORK_LIST_BACK_BUTTON)])
    keyboard = ReplyKeyboardMarkup(rows, resize_keyboard=True, one_time_keyboard=False)
    return keyboard, mapping


class TelegramBot:
    """Класс для управления Telegram ботом."""
    
    def __init__(self):
        """Инициализация бота."""
        self.token = settings.TELEGRAM_BOT_TOKEN
        self.application = None
        self.use_webhook = getattr(settings, 'TELEGRAM_USE_WEBHOOK', False)
        self.webhook_url = getattr(settings, 'TELEGRAM_WEBHOOK_URL', None)
        self.webhook_secret_token = getattr(settings, 'TELEGRAM_WEBHOOK_SECRET_TOKEN', None)
    
    async def start_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """
        Обработчик команды /start.
        Приветствие и инструкции по связыванию аккаунта.
        """
        user = update.effective_user
        telegram_id = user.id
        
        from apps.users.models import User
        
        # Проверяем связан ли аккаунт
        db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
        
        if not db_user:
            # Если аккаунт не связан, показываем общее приветствие
            welcome_message = f"""
👋 Привет, {user.first_name}!

Я бот образовательной платформы. Я буду присылать вам уведомления о:
• Новых занятиях
• Домашних заданиях
• Сообщениях от ментора/ученика
• Напоминаниях о занятиях

📱 Чтобы связать ваш аккаунт:
1. Войдите на платформу
2. Перейдите в Профиль → Настройки → Telegram
3. Нажмите "Связать Telegram"
4. Введите код связывания

Или используйте команду:
/link <ваш_код_связывания>

После связывания вы увидите команды, доступные для вашей роли.
"""
        else:
            # Если аккаунт связан, показываем приветствие в зависимости от роли
            role = db_user.role
            user_name = db_user.get_full_name() or db_user.email
            
            if role == 'mentor':
                welcome_message = f"""
👋 Привет, {user_name}!

Я бот образовательной платформы для менторов.

Я буду присылать вам уведомления о:
• Новых запросах на занятия
• Отменах занятий
• Сданных домашних заданиях
• Сообщениях от учеников
• Напоминаниях о занятиях

📚 Доступные команды:
/help - Полный список команд
/schedule - Расписание занятий
/nextlesson - Следующее занятие
/homework - Домашние задания на проверку
/clients - Список клиентов
/stats - Статистика
/settings - Настройки уведомлений
/status - Статус аккаунта
"""
                keyboard = get_main_keyboard('mentor')
                await update.message.reply_text(
                    welcome_message,
                    reply_markup=keyboard
                )
                return
            elif role == 'client':
                welcome_message = f"""
👋 Привет, {user_name}!

Я бот образовательной платформы для учеников.

Я буду присылать вам уведомления о:
• Новых занятиях
• Отменах занятий
• Новых домашних заданиях
• Проверенных домашних заданиях
• Сообщениях от ментора
• Напоминаниях о занятиях

📚 Доступные команды:
/help - Полный список команд
/schedule - Моё расписание
/nextlesson - Следующее занятие
/homework - Мои домашние задания
/progress - Мой прогресс обучения
/settings - Настройки уведомлений
/status - Статус аккаунта
"""
                keyboard = get_main_keyboard('client')
                await update.message.reply_text(
                    welcome_message,
                    reply_markup=keyboard
                )
                return
            elif role == 'parent':
                welcome_message = f"""
👋 Привет, {user_name}!

Я бот образовательной платформы для родителей.

Я буду присылать вам уведомления о:
• Занятиях ваших детей
• Домашних заданиях детей
• Прогрессе обучения
• Отчётах от менторов

📚 Доступные команды:
/help - Полный список команд
/schedule - Расписание детей
/nextlesson - Следующее занятие ребёнка
/homework - Домашние задания детей
/settings - Настройки уведомлений
/status - Статус аккаунта
"""
                keyboard = get_main_keyboard('parent')
                await update.message.reply_text(
                    welcome_message,
                    reply_markup=keyboard
                )
                return
            else:
                # Для других ролей (admin и т.д.)
                welcome_message = f"""
👋 Привет, {user_name}!

Я бот образовательной платформы.

Я буду присылать вам уведомления о событиях на платформе.

📚 Доступные команды:
/help - Полный список команд
/settings - Настройки уведомлений
/status - Статус аккаунта
"""
                keyboard = get_main_keyboard(None)
                await update.message.reply_text(
                    welcome_message,
                    reply_markup=keyboard
                )
                return
        
        # Если дошли сюда, отправляем без клавиатуры
        await update.message.reply_text(welcome_message)
    
    async def help_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Обработчик команды /help."""
        user = update.effective_user
        telegram_id = user.id
        
        from apps.users.models import User
        
        # Проверяем связан ли аккаунт
        db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
        
        if not db_user:
            # Если аккаунт не связан, показываем общую справку
            help_text = """
🔔 Доступные команды:

/start - Начать работу с ботом
/link <код> - Связать аккаунт с платформой
/help - Эта справка

💡 Как связать аккаунт:
1. Получите код связывания на платформе (Профиль → Telegram)
2. Отправьте команду: /link ВАШ_КОД

После связывания вы увидите команды, доступные для вашей роли.
"""
        else:
            # Если аккаунт связан, показываем справку в зависимости от роли
            role = db_user.role
            
            if role == 'mentor':
                help_text = """
👨‍🏫 Справка для менторов:

🔔 Основные команды:
/start - Главное меню
/help - Эта справка
/status - Статус аккаунта
/settings - Настройки уведомлений

📚 Расписание:
/schedule - Ближайшие занятия (до 5 занятий)
/nextlesson - Следующее занятие

📝 Домашние задания:
/homework - Задания, требующие проверки

👥 Клиенты:
/clients - Список ваших клиентов со статистикой
/stats - Ваша статистика (занятия, ДЗ, клиенты)

🔗 Управление аккаунтом:
/unlink - Отвязать Telegram аккаунт

💡 Вы будете получать уведомления о:
• Новых запросах на занятия
• Отменах занятий
• Сданных домашних заданиях
• Сообщениях от учеников
"""
            elif role == 'client':
                help_text = """
👨‍🎓 Справка для учеников:

🔔 Основные команды:
/start - Главное меню
/help - Эта справка
/status - Статус аккаунта
/settings - Настройки уведомлений

📚 Расписание:
/schedule - Моё расписание (до 5 ближайших занятий)
/nextlesson - Следующее занятие

📝 Домашние задания:
/homework - Мои активные домашние задания

📊 Прогресс:
/progress - Мой прогресс обучения

🔗 Управление аккаунтом:
/unlink - Отвязать Telegram аккаунт

💡 Вы будете получать уведомления о:
• Новых занятиях
• Отменах занятий
• Новых домашних заданиях
• Проверенных домашних заданиях
• Сообщениях от ментора
"""
            elif role == 'parent':
                help_text = """
👨‍👩‍👧 Справка для родителей:

🔔 Основные команды:
/start - Главное меню
/help - Эта справка
/status - Статус аккаунта
/settings - Настройки уведомлений

📚 Расписание детей:
/schedule - Расписание всех детей (до 5 ближайших занятий)
/nextlesson - Следующее занятие ребёнка

📝 Домашние задания:
/homework - Домашние задания детей

🔗 Управление аккаунтом:
/unlink - Отвязать Telegram аккаунт

💡 Вы будете получать уведомления о:
• Занятиях ваших детей
• Домашних заданиях детей
• Прогрессе обучения
• Отчётах от менторов
"""
            else:
                # Для других ролей (admin и т.д.)
                help_text = """
🔔 Доступные команды:

/start - Начать работу с ботом
/help - Эта справка
/settings - Настройки уведомлений
/status - Статус связывания
/unlink - Отвязать аккаунт

💡 Вы будете получать уведомления о событиях на платформе.
"""
        
        # Добавляем клавиатуру если аккаунт связан
        if db_user:
            keyboard = get_main_keyboard(db_user.role)
            await update.message.reply_text(help_text, reply_markup=keyboard)
        else:
            await update.message.reply_text(help_text)
    
    async def link_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """
        Обработчик команды /link.
        Связывание Telegram аккаунта с аккаунтом на платформе.
        """
        user = update.effective_user
        telegram_id = user.id
        telegram_username = user.username or ''
        
        # Проверяем наличие кода
        if not context.args:
            await update.message.reply_text(
                "❌ Укажите код связывания.\n\n"
                "Использование: /link <код>\n\n"
                "Получите код на платформе: Профиль → Настройки → Telegram"
            )
            return
        
        link_code = context.args[0]
        
        # Проверяем код и связываем аккаунт
        from .services import TelegramLinkService
        
        try:
            result = await sync_to_async(TelegramLinkService.link_account)(
                link_code=link_code,
                telegram_id=telegram_id,
                telegram_username=telegram_username
            )
            
            if result['success']:
                user_name = result.get('user_name', 'Пользователь')
                # Получаем роль пользователя для клавиатуры
                from apps.users.models import User
                linked_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
                keyboard = get_main_keyboard(linked_user.role if linked_user else None)
                await update.message.reply_text(
                    f"✅ Аккаунт успешно связан!\n\n"
                    f"👤 {user_name}\n\n"
                    f"Теперь вы будете получать уведомления в Telegram.",
                    reply_markup=keyboard
                )
            else:
                keyboard = get_main_keyboard(None)
                await update.message.reply_text(
                    f"❌ Ошибка связывания: {result.get('error', 'Неизвестная ошибка')}",
                    reply_markup=keyboard
                )
        
        except Exception as e:
            logger.error(f"Error linking Telegram account: {e}")
            await update.message.reply_text(
                "❌ Произошла ошибка при связывании аккаунта.\n"
                "Попробуйте позже или обратитесь в поддержку."
            )
    
    async def unlink_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """
        Обработчик команды /unlink.
        Отвязка Telegram аккаунта.
        """
        user = update.effective_user
        telegram_id = user.id
        
        from .services import TelegramLinkService
        
        try:
            result = await sync_to_async(TelegramLinkService.unlink_account)(telegram_id)
            
            if result['success']:
                await update.message.reply_text(
                    "✅ Аккаунт успешно отвязан.\n\n"
                    "Вы больше не будете получать уведомления в Telegram.\n\n"
                    "Чтобы снова связать аккаунт, используйте /link"
                )
            else:
                await update.message.reply_text(
                    f"❌ {result.get('error', 'Аккаунт не найден')}"
                )
        
        except Exception as e:
            logger.error(f"Error unlinking Telegram account: {e}")
            await update.message.reply_text(
                "❌ Произошла ошибка при отвязке аккаунта."
            )
    
    async def status_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Обработчик команды /status."""
        user = update.effective_user
        telegram_id = user.id
        
        from apps.users.models import User
        
        try:
            db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
            
            if db_user:
                role_display = db_user.get_role_display()
                role_emoji = {
                    'mentor': '👨‍🏫',
                    'client': '👨‍🎓',
                    'parent': '👨‍👩‍👧',
                    'admin': '👤'
                }.get(db_user.role, '👤')
                
                status_message = (
                    f"✅ <b>Аккаунт связан</b>\n\n"
                    f"{role_emoji} {db_user.get_full_name() or db_user.email}\n"
                    f"📧 {db_user.email}\n"
                    f"🎭 Роль: {role_display}\n\n"
                )
                
                # Дополнительная информация в зависимости от роли
                if db_user.role == 'parent':
                    from apps.users.models import Parent
                    try:
                        parent_profile = await sync_to_async(lambda: db_user.parent_profile)()
                        children = await sync_to_async(list)(parent_profile.children.all())
                        children_count = len(children)
                        status_message += f"👶 Привязано детей: {children_count}\n\n"
                    except:
                        pass
                
                # Проверяем настройки уведомлений
                try:
                    preferences = await sync_to_async(lambda: db_user.notification_preferences)()
                    notifications_status = "✅ Включены" if preferences.telegram_enabled else "❌ Выключены"
                    status_message += f"🔔 Уведомления: {notifications_status}"
                except:
                    status_message += "🔔 Уведомления: ⚙️ Настройте на платформе"
                
                keyboard = await get_user_keyboard(telegram_id)
                await update.message.reply_text(status_message, parse_mode='HTML', reply_markup=keyboard)
            else:
                keyboard = get_main_keyboard(None)
                await update.message.reply_text(
                    "❌ Аккаунт не связан\n\n"
                    "Используйте /link <код> для связывания аккаунта.",
                    reply_markup=keyboard
                )
        
        except Exception as e:
            logger.error(f"Error checking status: {e}")
            await update.message.reply_text(
                "❌ Ошибка проверки статуса."
            )
    
    async def settings_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Обработчик команды /settings."""
        user = update.effective_user
        telegram_id = user.id
        
        from apps.users.models import User
        
        try:
            db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
            
            if not db_user:
                keyboard = get_main_keyboard(None)
                await update.message.reply_text(
                    "❌ Аккаунт не связан.\n\n"
                    "Используйте /link <код> для связывания.",
                    reply_markup=keyboard
                )
                return
            
            # Получаем настройки уведомлений
            try:
                preferences = await sync_to_async(lambda: db_user.notification_preferences)()
            except:
                keyboard = await get_user_keyboard(telegram_id)
                await update.message.reply_text(
                    "⚙️ Настройки уведомлений не найдены.\n\n"
                    "Настройте уведомления на платформе: Профиль → Настройки",
                    reply_markup=keyboard
                )
                return
            
            # Формируем расширенное меню настроек
            message_text = "⚙️ <b>Настройки</b>\n\n"
            
            # Статус уведомлений
            all_status = "✅ Включены" if preferences.enabled else "❌ Выключены"
            telegram_status = "✅ Вкл" if preferences.telegram_enabled else "❌ Выкл"
            email_status = "✅ Вкл" if preferences.email_enabled else "❌ Выкл"
            in_app_status = "✅ Вкл" if preferences.in_app_enabled else "❌ Выкл"
            
            message_text += f"🔔 Все уведомления: {all_status}\n"
            message_text += f"📱 Telegram: {telegram_status}\n"
            message_text += f"📧 Email: {email_status}\n"
            message_text += f"💬 В приложении: {in_app_status}\n\n"
            
            # Режим тишины
            if preferences.quiet_hours_enabled and preferences.quiet_hours_start and preferences.quiet_hours_end:
                quiet_start = preferences.quiet_hours_start.strftime('%H:%M')
                quiet_end = preferences.quiet_hours_end.strftime('%H:%M')
                message_text += f"🔇 Режим тишины: {quiet_start} - {quiet_end}\n\n"
            else:
                message_text += "🔇 Режим тишины: ❌ Выключен\n\n"
            
            # Язык
            user_lang = db_user.language or 'ru'
            lang_display = 'Русский' if user_lang == 'ru' else 'English'
            message_text += f"🌐 Язык: {lang_display}\n"
            
            # Создаем inline клавиатуру
            keyboard = []
            
            # Основные настройки уведомлений
            keyboard.append([
                InlineKeyboardButton(
                    "🔔 " + ("Выключить все" if preferences.enabled else "Включить все"),
                    callback_data="settings_toggle_all"
                )
            ])
            
            keyboard.append([
                InlineKeyboardButton(
                    "📱 Telegram: " + ("Выкл" if preferences.telegram_enabled else "Вкл"),
                    callback_data="settings_toggle_telegram"
                ),
                InlineKeyboardButton(
                    "📧 Email: " + ("Выкл" if preferences.email_enabled else "Вкл"),
                    callback_data="settings_toggle_email"
                )
            ])
            
            keyboard.append([
                InlineKeyboardButton(
                    "🔇 Режим тишины",
                    callback_data="settings_quiet_hours"
                ),
                InlineKeyboardButton(
                    "📋 Типы уведомлений",
                    callback_data="settings_notification_types"
                )
            ])
            
            keyboard.append([
                InlineKeyboardButton("🌐 Язык", callback_data="settings_language")
            ])
            
            # Добавляем кнопку с URL только если это не localhost
            frontend_url = settings.FRONTEND_URL
            if frontend_url and 'localhost' not in frontend_url and '127.0.0.1' not in frontend_url:
                keyboard.append([
                    InlineKeyboardButton("🌐 Открыть на сайте", url=f"{frontend_url}/profile")
                ])
            
            reply_markup = InlineKeyboardMarkup(keyboard)
            
            # Добавляем основную клавиатуру вместе с inline кнопками
            main_keyboard = await get_user_keyboard(telegram_id)
            await update.message.reply_text(
                message_text,
                parse_mode='HTML',
                reply_markup=reply_markup
            )
            # Отправляем отдельное сообщение с основной клавиатурой
            await update.message.reply_text(
                "Используйте кнопки ниже для навигации:",
                reply_markup=main_keyboard
            )
        
        except Exception as e:
            logger.error(f"Error getting settings: {e}")
            await update.message.reply_text(
                "❌ Ошибка получения настроек."
            )
    
    async def button_callback(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Обработчик нажатий на кнопки."""
        query = update.callback_query
        await query.answer()
        
        # Сначала обрабатываем настройки (они имеют приоритет)
        if (query.data.startswith('settings_') or query.data.startswith('toggle_type_')
                or query.data.startswith('set_timezone_') or query.data.startswith('set_language_')
                or query.data.startswith('quiet_hours_') or query.data == "noop"):
            user = update.effective_user
            telegram_id = user.id
            
            from apps.users.models import User
            
            try:
                db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
                
                if not db_user:
                    await query.edit_message_text("❌ Аккаунт не связан.")
                    return
                
                preferences = await sync_to_async(lambda: db_user.notification_preferences)()
                
                # Переключение всех уведомлений
                if query.data == "settings_toggle_all":
                    preferences.enabled = not preferences.enabled
                    await sync_to_async(preferences.save)()
                    await self._refresh_settings_message(query, db_user, preferences)
                    return
                
                # Переключение Telegram уведомлений
                elif query.data == "settings_toggle_telegram":
                    preferences.telegram_enabled = not preferences.telegram_enabled
                    await sync_to_async(preferences.save)()
                    await self._refresh_settings_message(query, db_user, preferences)
                    return
                
                # Переключение Email уведомлений
                elif query.data == "settings_toggle_email":
                    preferences.email_enabled = not preferences.email_enabled
                    await sync_to_async(preferences.save)()
                    await self._refresh_settings_message(query, db_user, preferences)
                    return
                
                # Режим тишины
                elif query.data == "settings_quiet_hours":
                    await self._handle_quiet_hours(query, db_user, preferences)
                    return
                
                # Обработка режима тишины
                elif query.data.startswith("quiet_hours_"):
                    from datetime import time
                    
                    if query.data == "quiet_hours_disable":
                        preferences.quiet_hours_enabled = False
                        await sync_to_async(preferences.save)()
                        await query.answer("Режим тишины выключен")
                        await self._handle_quiet_hours(query, db_user, preferences)
                        return
                    elif query.data == "quiet_hours_enable_22_8":
                        preferences.quiet_hours_enabled = True
                        preferences.quiet_hours_start = time(22, 0)
                        preferences.quiet_hours_end = time(8, 0)
                        await sync_to_async(preferences.save)()
                        await query.answer("Режим тишины: 22:00 - 08:00")
                        await self._refresh_settings_message(query, db_user, preferences)
                        return
                    elif query.data == "quiet_hours_enable_23_7":
                        preferences.quiet_hours_enabled = True
                        preferences.quiet_hours_start = time(23, 0)
                        preferences.quiet_hours_end = time(7, 0)
                        await sync_to_async(preferences.save)()
                        await query.answer("Режим тишины: 23:00 - 07:00")
                        await self._refresh_settings_message(query, db_user, preferences)
                        return
                    elif query.data == "quiet_hours_custom":
                        await query.answer("Настройка времени через сайт", show_alert=True)
                        await self._handle_quiet_hours(query, db_user, preferences)
                        return
                
                # Типы уведомлений
                elif query.data == "settings_notification_types":
                    await self._handle_notification_types(query, db_user, preferences)
                    return
                
                # Часовой пояс — кнопка убрана; при нажатии старой кнопки просто возврат в настройки
                elif query.data == "settings_timezone":
                    await query.answer()
                    await self._refresh_settings_message(query, db_user, preferences)
                    return
                
                # Язык
                elif query.data == "settings_language":
                    await self._handle_language(query, db_user)
                    return
                
                # Обработка типов уведомлений
                elif query.data.startswith("toggle_type_"):
                    ntype = query.data.replace("toggle_type_", "")
                    type_prefs = preferences.type_preferences.get(ntype, {})
                    if not isinstance(type_prefs, dict):
                        type_prefs = {}
                    
                    current = type_prefs.get('telegram', True)
                    type_prefs['telegram'] = not current
                    preferences.type_preferences[ntype] = type_prefs
                    await sync_to_async(preferences.save)()
                    
                    # Получаем название типа для ответа
                    from .models import Notification
                    type_display = dict(Notification.TYPE_CHOICES).get(ntype, ntype)
                    status = "включены" if not current else "выключены"
                    await query.answer(f"{type_display} {status}")
                    await self._handle_notification_types(query, db_user, preferences)
                    return
                
                # Игнорируем заголовки (noop)
                elif query.data == "noop":
                    await query.answer()
                    return
                
                # Установка часового пояса (меню убрано; при нажатии старой кнопки — возврат в настройки)
                elif query.data.startswith("set_timezone_"):
                    await query.answer()
                    preferences = await sync_to_async(lambda: db_user.notification_preferences)()
                    await self._refresh_settings_message(query, db_user, preferences)
                    return
                
                # Установка языка
                elif query.data.startswith("set_language_"):
                    language = query.data.replace("set_language_", "")
                    db_user.language = language
                    await sync_to_async(db_user.save)(update_fields=['language'])
                    await query.answer(f"Язык установлен: {language}")
                    await self._handle_language(query, db_user)
                    return
                
                # Возврат к настройкам
                elif query.data == "settings_back":
                    preferences = await sync_to_async(lambda: db_user.notification_preferences)()
                    await self._refresh_settings_message(query, db_user, preferences)
                    return
            
            except Exception as e:
                logger.error(f"Error handling settings callback: {e}", exc_info=True)
                await query.edit_message_text("❌ Ошибка обновления настроек.")
                return
        
        # Обработка домашних заданий и кнопок ментора (список заданий → выбор задания)
        if (query.data.startswith('homework_') or query.data.startswith('mentor_submission_')
                or query.data.startswith('submission_') or query.data == 'mentor_homework_back'):
            user = update.effective_user
            telegram_id = user.id
            
            from apps.users.models import User
            db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
            
            if not db_user:
                await query.answer("❌ Аккаунт не связан", show_alert=True)
                return
            
            try:
                if query.data.startswith('homework_upload_'):
                    # Загрузка решения ДЗ
                    homework_id = int(query.data.replace('homework_upload_', ''))
                    
                    from apps.homework.models import Homework
                    homework = await sync_to_async(Homework.objects.get)(id=homework_id)
                    
                    # Проверяем доступ
                    if db_user.role != 'client' or db_user not in await sync_to_async(list)(homework.assigned_to.all()):
                        await query.answer("❌ У вас нет доступа к этому заданию", show_alert=True)
                        return
                    
                    # Сохраняем ID задания в контексте
                    context.user_data['waiting_for_homework_file'] = homework_id
                    
                    await query.answer("📎 Отправьте файл или фото для решения")
                    await query.edit_message_text(
                        f"📎 <b>Загрузка решения</b>\n\n"
                        f"📝 Задание: {homework.title}\n\n"
                        f"Отправьте:\n"
                        f"• Текст решения\n"
                        f"• Файл (документ)\n"
                        f"• Фото с решением\n\n"
                        f"Или отправьте 'отмена' для отмены.",
                        parse_mode='HTML'
                    )
                    return
                
                elif query.data.startswith('homework_detail_'):
                    # Детали задания
                    homework_id = int(query.data.replace('homework_detail_', ''))
                    
                    from apps.homework.models import Homework, HomeworkSubmission
                    homework = await sync_to_async(Homework.objects.get)(id=homework_id)
                    
                    deadline_str = homework.deadline.strftime('%d.%m.%Y в %H:%M') if homework.deadline else 'Без дедлайна'
                    
                    submission = await sync_to_async(
                        HomeworkSubmission.objects.filter(
                            homework=homework,
                            student=db_user
                        ).first
                    )()
                    
                    message = f"📝 <b>{homework.title}</b>\n\n"
                    message += f"📅 Дедлайн: {deadline_str}\n"
                    if homework.description:
                        desc = homework.description[:200] + "..." if len(homework.description) > 200 else homework.description
                        message += f"\n📄 {desc}\n"
                    
                    if submission:
                        message += f"\n✅ <b>Статус: Сдано</b>\n"
                        if submission.status == 'graded' and submission.score is not None:
                            message += f"🎯 Оценка: {submission.score}/{homework.max_score}\n"
                        elif submission.status == 'returned':
                            message += f"🔄 Возвращено на доработку\n"
                        else:
                            message += f"⏳ Ожидает проверки\n"
                    else:
                        message += f"\n⏳ <b>Статус: Не сдано</b>\n"
                    
                    inline_keyboard = []
                    if not submission or submission.status == 'returned':
                        inline_keyboard.append([
                            InlineKeyboardButton(
                                "📎 Загрузить решение",
                                callback_data=f"homework_upload_{homework.id}"
                            )
                        ])
                    
                    if submission:
                        inline_keyboard.append([
                            InlineKeyboardButton(
                                "👁️ Просмотреть решение",
                                callback_data=f"homework_view_{submission.id}"
                            )
                        ])
                    
                    inline_keyboard.append([
                        InlineKeyboardButton(
                            "◀️ Назад к списку",
                            callback_data="homework_back"
                        )
                    ])
                    
                    reply_markup = InlineKeyboardMarkup(inline_keyboard)
                    await query.edit_message_text(message, parse_mode='HTML', reply_markup=reply_markup)
                    return
                
                elif query.data.startswith('homework_view_'):
                    # Просмотр решения
                    submission_id = int(query.data.replace('homework_view_', ''))
                    
                    from apps.homework.models import HomeworkSubmission
                    submission = await sync_to_async(HomeworkSubmission.objects.select_related('homework', 'student').get)(id=submission_id)
                    if submission.student_id != db_user.id and db_user.role != 'mentor':
                        await query.answer("❌ У вас нет доступа", show_alert=True)
                        return
                    view_data = await sync_to_async(lambda s: (
                        s.homework.title,
                        s.student.get_full_name(),
                        s.homework.max_score,
                        s.submitted_at.strftime('%d.%m.%Y в %H:%M') if s.submitted_at else 'Неизвестно',
                        s.get_status_display(),
                    ))(submission)
                    hw_title_v, student_name_v, hw_max_v, submitted_at_v, status_v = view_data
                    message = f"👁️ <b>Решение ДЗ</b>\n\n"
                    message += f"📝 Задание: {hw_title_v}\n"
                    message += f"👤 Студент: {student_name_v}\n"
                    message += f"📅 Сдано: {submitted_at_v}\n"
                    message += f"📊 Статус: {status_v}\n"
                    if submission.score is not None:
                        message += f"🎯 Оценка: {submission.score}/{hw_max_v}\n"
                    
                    # Комментарии (экранируем HTML, чтобы не сломать сообщение в Telegram)
                    import html as _html
                    if submission.feedback and submission.feedback.strip():
                        feedback = submission.feedback[:500] + "..." if len(submission.feedback) > 500 else submission.feedback
                        message += f"\n💬 <b>Комментарий ментора:</b>\n<i>{_html.escape(feedback)}</i>\n"
                    if submission.ai_checked_at and submission.ai_feedback and submission.ai_feedback.strip():
                        ai_feedback = submission.ai_feedback[:500] + "..." if len(submission.ai_feedback) > 500 else submission.ai_feedback
                        message += f"\n🤖 <b>Комментарий ИИ:</b>\n<i>{_html.escape(ai_feedback)}</i>\n"
                    
                    if submission.attachment:
                        message += f"\n📎 Файл прикреплен"
                    
                    inline_keyboard = [[
                        InlineKeyboardButton(
                            "🌐 Открыть на сайте",
                            url=f"{settings.FRONTEND_URL}/homework"
                        )
                    ]]
                    
                    reply_markup = InlineKeyboardMarkup(inline_keyboard)
                    await query.edit_message_text(message, parse_mode='HTML', reply_markup=reply_markup)
                    return
                
                elif query.data.startswith('mentor_submission_'):
                    # Просмотр submission ментором: все обращения к БД/связям — только внутри sync_to_async
                    submission_id = int(query.data.replace('mentor_submission_', ''))
                    import html
                    
                    def _load_mentor_submission(sid, mentor_user_id):
                        from apps.homework.models import HomeworkSubmission, HomeworkFile
                        sub = HomeworkSubmission.objects.select_related('homework', 'student').prefetch_related(
                            'files'
                        ).get(id=sid)
                        if sub.homework.mentor_id != mentor_user_id:
                            return None
                        # Основной файл
                        att_name = None
                        has_att = bool(getattr(sub, 'attachment', None))
                        if has_att:
                            att_name = getattr(sub.attachment, 'name', None) or 'Файл'
                            if att_name and '/' in att_name:
                                att_name = att_name.split('/')[-1]
                        # Список всех файлов: основной + доп. файлы решения (используем prefetch)
                        file_names = []
                        if att_name:
                            file_names.append(att_name)
                        for hf in sub.files.all():
                            if getattr(hf, 'file_type', None) == 'submission' and hf.file:
                                name = getattr(hf.file, 'name', None) or 'Файл'
                                if '/' in name:
                                    name = name.split('/')[-1]
                                if name and name not in file_names:
                                    file_names.append(name)
                        return {
                            'id': sub.id,
                            'student_name': sub.student.get_full_name(),
                            'hw_title': sub.homework.title,
                            'hw_id': sub.homework_id,
                            'max_score': sub.homework.max_score,
                            'submitted_at': sub.submitted_at,
                            'status_display': sub.get_status_display(),
                            'content': (sub.content or '').strip(),
                            'attachment_url': (sub.attachment_url or '').strip(),
                            'score': sub.score,
                            'status': sub.status,
                            'ai_checked_at': sub.ai_checked_at,
                            'ai_score': sub.ai_score,
                            'ai_feedback': (sub.ai_feedback or '').strip(),
                            'feedback': (sub.feedback or '').strip(),
                            'has_attachment': has_att,
                            'attachment_name': att_name,
                            'file_names': file_names,
                            'sub': sub,
                        }
                    
                    data = await sync_to_async(_load_mentor_submission)(submission_id, db_user.id)
                    if data is None or db_user.role != 'mentor':
                        await query.answer("❌ У вас нет доступа", show_alert=True)
                        return
                    
                    submitted_at = data['submitted_at'].strftime('%d.%m.%Y в %H:%M') if data['submitted_at'] else 'Неизвестно'
                    message = f"📝 <b>{data['hw_title']}</b>\n\n"
                    message += f"👤 <b>Студент:</b> {data['student_name']}\n"
                    message += f"📅 <b>Сдано:</b> {submitted_at}\n"
                    message += f"📊 <b>Статус:</b> {data['status_display']}\n\n"
                    
                    # Текст, который отправил студент
                    message += "📄 <b>Текст от студента:</b>\n"
                    if data['content']:
                        content_preview = data['content'][:1500] + "…" if len(data['content']) > 1500 else data['content']
                        message += "<i>" + html.escape(content_preview) + "</i>\n\n"
                    else:
                        message += "<i>Студент текста не написал.</i>\n\n"
                    
                    # Все прикреплённые файлы (основной + доп. из HomeworkFile)
                    message += "📎 <b>Прикреплённые файлы:</b>\n"
                    file_names = data.get('file_names') or []
                    if file_names:
                        for i, name in enumerate(file_names[:15], 1):
                            message += f"  {i}. {html.escape(name)}\n"
                        if len(file_names) > 15:
                            message += f"  … и ещё {len(file_names) - 15}\n"
                    else:
                        message += "  <i>Файлов нет</i>\n"
                    if data['attachment_url']:
                        message += f"🔗 <b>Ссылка студента:</b> {data['attachment_url'][:100]}{'…' if len(data['attachment_url']) > 100 else ''}\n"
                    message += "\n<i>Скачать/открыть файлы — кнопка «Открыть на сайте» ниже.</i>\n\n"
                    
                    if data['status'] == 'graded' and data['score'] is not None:
                        message += f"🎯 <b>Оценка:</b> {data['score']}/{data['max_score']}\n\n"
                    
                    message += "💬 <b>Комментарии к решению:</b>\n"
                    has_comment = False
                    if data['ai_checked_at'] and data['ai_feedback']:
                        ai_score_text = f"{data['ai_score']}/5" if data['ai_score'] is not None else "—"
                        message += f"🤖 <b>ИИ</b> (оценка: {ai_score_text}):\n"
                        ai_fb = data['ai_feedback'][:800] + "..." if len(data['ai_feedback']) > 800 else data['ai_feedback']
                        message += f"<i>{html.escape(ai_fb)}</i>\n\n"
                        has_comment = True
                    if data['feedback']:
                        message += "✏️ <b>Ваш комментарий:</b>\n"
                        fb = data['feedback'][:800] + "..." if len(data['feedback']) > 800 else data['feedback']
                        message += f"<i>{html.escape(fb)}</i>\n"
                        has_comment = True
                    if not has_comment:
                        message += "<i>Пока нет комментариев.</i>\n"
                    
                    inline_keyboard = [
                        [InlineKeyboardButton("✏️ Редактировать ответ", callback_data=f"submission_edit_feedback_{data['id']}")],
                    ]
                    if data['status'] == 'pending' or (data['ai_checked_at'] and data['status'] != 'graded'):
                        if data['ai_score'] and data['ai_feedback']:
                            inline_keyboard.append([InlineKeyboardButton("💾 Сохранить ответ", callback_data=f"submission_publish_ai_{data['id']}")])
                        inline_keyboard.append([InlineKeyboardButton("⭐ Выставить оценку", callback_data=f"submission_grade_{data['id']}")])
                    elif data['status'] == 'graded':
                        inline_keyboard.append([InlineKeyboardButton("⭐ Изменить оценку", callback_data=f"submission_grade_{data['id']}")])
                    # Вернуть на пересдачу — студент получит уведомление
                    inline_keyboard.append([InlineKeyboardButton("🔄 Вернуть на доработку", callback_data=f"submission_return_revision_{data['id']}")])
                    inline_keyboard.append([InlineKeyboardButton("🌐 Открыть на сайте", url=f"{settings.FRONTEND_URL}/homework/{data['hw_id']}/submissions/{data['id']}/")])
                    inline_keyboard.append([InlineKeyboardButton("◀️ Назад к списку", callback_data="mentor_homework_back")])
                    
                    reply_markup = InlineKeyboardMarkup(inline_keyboard)
                    await query.edit_message_text(message, parse_mode='HTML', reply_markup=reply_markup)
                    
                    # Картинка вложения — только в sync_to_async, submission в data['sub']
                    def _get_attachment_photo_data(s):
                        if not s:
                            return None, None, False
                        att = getattr(s, 'attachment', None)
                        if not att:
                            return None, None, False
                        name = (getattr(att, 'name', None) or '').lower()
                        if not any(name.endswith(ext) for ext in ('.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp')):
                            return None, None, False
                        path, url = None, None
                        try:
                            path = getattr(att, 'path', None)
                            path = str(path) if path else None
                        except Exception:
                            pass
                        try:
                            url = getattr(att, 'url', None)
                        except Exception:
                            pass
                        return path, url, True
                    
                    _path, _url, _is_image = await sync_to_async(_get_attachment_photo_data)(data['sub'])
                    if _is_image:
                        try:
                            import os
                            sent = False
                            if _path and os.path.exists(_path):
                                await context.bot.send_photo(
                                    chat_id=query.message.chat_id,
                                    photo=_path,
                                    caption="📎 Файл решения (прикреплён учеником)"
                                )
                                sent = True
                            if not sent and _url:
                                base = getattr(settings, 'BASE_URL', None) or getattr(settings, 'API_URL', None) or ''
                                if base:
                                    photo_url = base.rstrip('/') + _url
                                    await context.bot.send_photo(
                                        chat_id=query.message.chat_id,
                                        photo=photo_url,
                                        caption="📎 Файл решения (прикреплён учеником)"
                                    )
                        except Exception as img_err:
                            logger.warning("Could not send submission image to Telegram: %s", img_err)
                    
                    return
                
                elif query.data.startswith('submission_publish_ai_'):
                    # Публикация черновика ИИ как есть
                    submission_id = int(query.data.replace('submission_publish_ai_', ''))
                    
                    from apps.homework.models import HomeworkSubmission, Homework
                    submission = await sync_to_async(
                        HomeworkSubmission.objects.select_related('homework', 'student').get
                    )(id=submission_id)
                    homework_mentor_id = await sync_to_async(
                        lambda hw_id: Homework.objects.values_list('mentor_id', flat=True).get(id=hw_id)
                    )(submission.homework_id)
                    if db_user.role != 'mentor' or homework_mentor_id != db_user.id:
                        await query.answer("❌ У вас нет доступа", show_alert=True)
                        return
                    
                    if not submission.ai_score or not submission.ai_feedback:
                        await query.answer("❌ Нет данных от ИИ для публикации", show_alert=True)
                        return
                    
                    # Публикуем оценку и комментарий ИИ
                    await sync_to_async(submission.grade)(
                        submission.ai_score,
                        submission.ai_feedback,
                        checked_by=db_user
                    )
                    submission.graded_by_ai = True
                    await sync_to_async(submission.save)(update_fields=['graded_by_ai'])
                    
                    # Обновляем статистику и уведомление — всё в sync (доступ к homework/student)
                    def _publish_ai_and_notify(sub):
                        sub.homework.update_statistics()
                        from apps.notifications.services import NotificationService
                        msg = f'Проверено ДЗ "{sub.homework.title}". Оценка: {sub.ai_score}/{sub.homework.max_score}'
                        if sub.ai_feedback and str(sub.ai_feedback).strip():
                            comment = (sub.ai_feedback[:500] + '…') if len(sub.ai_feedback) > 500 else sub.ai_feedback
                            msg += f'\n\n💬 Комментарий:\n{comment}'
                        NotificationService.create_notification_with_telegram(
                            recipient=sub.student,
                            notification_type='homework_reviewed',
                            title='✅ ДЗ проверено',
                            message=msg,
                            priority='normal',
                            action_url=f'/homework/{sub.homework.id}/submissions/{sub.id}/',
                            content_object=sub
                        )
                        return (sub.homework.title, sub.student.get_full_name(), sub.homework.max_score)
                    hw_title, student_name, hw_max = await sync_to_async(_publish_ai_and_notify)(submission)
                    
                    await query.answer("✅ Оценка опубликована!")
                    await query.edit_message_text(
                        f"✅ <b>Оценка опубликована!</b>\n\n"
                        f"📝 Задание: {hw_title}\n"
                        f"👤 Студент: {student_name}\n"
                        f"⭐ Оценка: {submission.ai_score}/{hw_max}\n"
                        f"💬 Комментарий: {submission.ai_feedback[:200]}{'...' if len(submission.ai_feedback) > 200 else ''}\n\n"
                        f"📤 Студент получил уведомление.",
                        parse_mode='HTML'
                    )
                    return
                
                elif query.data.startswith('submission_grade_'):
                    # Начало редактирования оценки
                    submission_id = int(query.data.replace('submission_grade_', ''))
                    
                    from apps.homework.models import HomeworkSubmission, Homework
                    submission = await sync_to_async(HomeworkSubmission.objects.select_related('homework', 'student').get)(id=submission_id)
                    homework_mentor_id = await sync_to_async(
                        lambda hw_id: Homework.objects.values_list('mentor_id', flat=True).get(id=hw_id)
                    )(submission.homework_id)
                    if db_user.role != 'mentor' or homework_mentor_id != db_user.id:
                        await query.answer("❌ У вас нет доступа", show_alert=True)
                        return
                    
                    grade_display = await sync_to_async(lambda s: (
                        s.score if s.score is not None else (s.ai_score if s.ai_score else None),
                        s.homework.max_score,
                        s.homework.title,
                        s.student.get_full_name()
                    ))(submission)
                    current_score, hw_max, hw_title, student_name = grade_display
                    current_score_text = f" (текущая: {current_score}/{hw_max})" if current_score else ""
                    
                    context.user_data['waiting_for_submission_score'] = submission_id
                    await query.answer()
                    await query.message.reply_text(
                        f"⭐ <b>Выставление оценки</b>\n\n"
                        f"📝 Задание: {hw_title}\n"
                        f"👤 Студент: {student_name}\n\n"
                        f"Введите оценку от 1 до {hw_max}{current_score_text}.\n\n"
                        f"Или отправьте оценку и комментарий в формате:\n"
                        f"<code>5\nОтличная работа!</code>",
                        parse_mode='HTML'
                    )
                    return
                
                elif query.data.startswith('submission_edit_feedback_'):
                    # Начало редактирования ответа
                    import html as _html_mod
                    submission_id = int(query.data.replace('submission_edit_feedback_', ''))
                    
                    from apps.homework.models import HomeworkSubmission, Homework
                    submission = await sync_to_async(HomeworkSubmission.objects.select_related('homework', 'student').get)(id=submission_id)
                    homework_mentor_id = await sync_to_async(
                        lambda hw_id: Homework.objects.values_list('mentor_id', flat=True).get(id=hw_id)
                    )(submission.homework_id)
                    if db_user.role != 'mentor' or homework_mentor_id != db_user.id:
                        await query.answer("❌ У вас нет доступа", show_alert=True)
                        return
                    
                    current_feedback = (submission.feedback or submission.ai_feedback or "").strip()
                    cf_preview = current_feedback[:200] + "..." if len(current_feedback) > 200 else current_feedback
                    current_feedback_text = f"\n\nТекущий ответ:\n<i>{_html_mod.escape(cf_preview)}</i>" if current_feedback else ""
                    hw_title_fb, student_name_fb = await sync_to_async(
                        lambda s: (s.homework.title, s.student.get_full_name())
                    )(submission)
                    context.user_data['waiting_for_submission_feedback'] = submission_id
                    await query.answer()
                    await query.message.reply_text(
                        f"✏️ <b>Редактировать ответ</b>\n\n"
                        f"📝 Задание: {hw_title_fb}\n"
                        f"👤 Студент: {student_name_fb}\n\n"
                        f"Введите ваш ответ. Отправка сообщения сохранит ответ.{current_feedback_text}",
                        parse_mode='HTML'
                    )
                    return
                
                elif query.data.startswith('submission_return_revision_'):
                    # Вернуть ДЗ на доработку — студент получит уведомление
                    submission_id = int(query.data.replace('submission_return_revision_', ''))
                    from apps.homework.models import HomeworkSubmission, Homework
                    submission = await sync_to_async(
                        HomeworkSubmission.objects.select_related('homework', 'student').get
                    )(id=submission_id)
                    homework_mentor_id = await sync_to_async(
                        lambda hw_id: Homework.objects.values_list('mentor_id', flat=True).get(id=hw_id)
                    )(submission.homework_id)
                    if db_user.role != 'mentor' or homework_mentor_id != db_user.id:
                        await query.answer("❌ У вас нет доступа", show_alert=True)
                        return
                    hw_title_rr, student_name_rr = await sync_to_async(
                        lambda s: (s.homework.title, s.student.get_full_name())
                    )(submission)
                    context.user_data['waiting_for_return_revision'] = submission_id
                    await query.answer()
                    await query.message.reply_text(
                        f"🔄 <b>Вернуть на доработку</b>\n\n"
                        f"📝 Задание: {hw_title_rr}\n"
                        f"👤 Студент: {student_name_rr}\n\n"
                        f"Введите комментарий для студента (почему нужно доработать). "
                        f"Студент получит уведомление и сможет отправить решение заново.\n\n"
                        f"Или отправьте «отмена» для отмены.",
                        parse_mode='HTML'
                    )
                    return
                
                elif query.data == 'mentor_homework_back':
                    # Возврат к списку заданий для ментора
                    from apps.homework.models import HomeworkSubmission
                    from django.utils import timezone
                    
                    def _mentor_submissions_list(mentor_user):
                        qs = HomeworkSubmission.objects.filter(
                            homework__mentor=mentor_user,
                            status='pending'
                        ).select_related('homework', 'student').order_by('-submitted_at')[:5]
                        return [
                            {
                                'id': s.id,
                                'student_name': s.student.get_full_name() if s.student else 'Студент',
                                'hw_title': s.homework.title or 'Без названия',
                                'submitted_at': s.submitted_at.strftime('%d.%m.%Y') if s.submitted_at else 'Неизвестно',
                                'ai_checked_at': getattr(s, 'ai_checked_at', None),
                            }
                            for s in qs
                        ]
                    submissions_data = await sync_to_async(_mentor_submissions_list)(db_user)
                    if not submissions_data:
                        message = "📝 Нет домашних заданий, требующих проверки."
                        keyboard = await get_user_keyboard(update.effective_user.id)
                        await query.edit_message_text(message, parse_mode='HTML')
                        await query.message.reply_text("Используйте кнопки для навигации:", reply_markup=keyboard)
                        return
                    message = "📝 <b>Домашние задания на проверку:</b>\n\n"
                    inline_keyboard = []
                    for item in submissions_data:
                        ai_status = " 🤖 ИИ проверил" if item['ai_checked_at'] else ""
                        message += f"<b>{item['hw_title']}</b>{ai_status}\n"
                        message += f"👤 {item['student_name']}\n"
                        message += f"📅 Сдано: {item['submitted_at']}\n\n"
                        inline_keyboard.append([
                            InlineKeyboardButton(
                                f"👁️ {item['hw_title'][:30]} — {item['student_name']}",
                                callback_data=f"mentor_submission_{item['id']}"
                            )
                        ])
                    reply_markup = InlineKeyboardMarkup(inline_keyboard)
                    await query.edit_message_text(message, parse_mode='HTML', reply_markup=reply_markup)
                    return
                
                elif query.data == 'homework_back':
                    # Возврат к списку заданий в виде кнопок в панели
                    from apps.homework.models import Homework
                    from django.utils import timezone
                    
                    # Используем правильный sync_to_async
                    def get_homeworks():
                        return list(Homework.objects.filter(
                            assigned_to=db_user,
                            deadline__gte=timezone.now()
                        ).order_by('deadline')[:5])
                    
                    homeworks = await sync_to_async(get_homeworks)()
                    
                    if not homeworks:
                        keyboard = await get_user_keyboard(query.from_user.id)
                        await query.edit_message_text("📝 У вас нет активных домашних заданий.")
                        await context.bot.send_message(
                            chat_id=query.message.chat_id,
                            text="Возврат в главное меню.",
                            reply_markup=keyboard
                        )
                        return
                    
                    # Возврат к списку в виде кнопок в панели
                    homework_keyboard, homework_buttons = make_homework_list_keyboard(homeworks)
                    context.user_data['homework_buttons'] = homework_buttons
                    context.user_data['homework_list_active'] = True
                    context.user_data.pop('current_homework_id', None)
                    
                    await query.edit_message_text(
                        "📝 <b>Домашние задания</b>\n\nВыберите задание кнопкой в панели ниже:",
                        parse_mode='HTML'
                    )
                    await context.bot.send_message(
                        chat_id=query.message.chat_id,
                        text="👇",
                        reply_markup=homework_keyboard
                    )
                    return
                    
            except Exception as e:
                logger.error(f"Error handling homework callback: {e}", exc_info=True)
                await query.answer("❌ Ошибка обработки запроса", show_alert=True)
                return
        
        # Обработка деталей занятия
        if query.data.startswith('lesson_detail_'):
            try:
                lesson_id = int(query.data.replace('lesson_detail_', ''))
                
                from apps.schedule.models import Lesson
                from django.utils import timezone
                import pytz
                
                lesson = await sync_to_async(
                    Lesson.objects.select_related('mentor', 'client', 'client__user', 'subject').get
                )(id=lesson_id)
                
                user = update.effective_user
                telegram_id = user.id
                db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
                
                if not db_user:
                    await query.answer("❌ Аккаунт не связан", show_alert=True)
                    return
                
                # Проверяем доступ
                has_access = False
                if db_user.role == 'mentor' and lesson.mentor == db_user:
                    has_access = True
                elif db_user.role == 'client' and lesson.client and lesson.client.user == db_user:
                    has_access = True
                elif db_user.role == 'parent' and lesson.client and lesson.client.user.parent_profile and lesson.client.user.parent_profile.user == db_user:
                    has_access = True
                
                if not has_access:
                    await query.answer("❌ У вас нет доступа к этому занятию", show_alert=True)
                    return
                
                # Формируем сообщение
                from apps.users.utils import get_user_timezone
                user_tz = get_user_timezone(db_user.timezone or 'UTC')
                if timezone.is_aware(lesson.start_time):
                    local_start = lesson.start_time.astimezone(user_tz)
                    local_end = lesson.end_time.astimezone(user_tz) if lesson.end_time else None
                else:
                    utc_start = timezone.make_aware(lesson.start_time, pytz.UTC)
                    local_start = utc_start.astimezone(user_tz)
                    local_end = lesson.end_time.astimezone(user_tz) if lesson.end_time and timezone.is_aware(lesson.end_time) else None
                
                message = f"📚 <b>{lesson.title}</b>\n\n"
                
                if lesson.subject:
                    message += f"📖 Предмет: {lesson.subject.name}\n"
                
                message += f"🕐 Начало: {local_start.strftime('%d.%m.%Y в %H:%M')}\n"
                if local_end:
                    message += f"🕐 Окончание: {local_end.strftime('%d.%m.%Y в %H:%M')}\n"
                message += f"⏱ Длительность: {lesson.duration} минут\n"
                message += f"📊 Статус: {lesson.get_status_display()}\n\n"
                
                if db_user.role == 'mentor':
                    if lesson.client:
                        message += f"👤 Студент: {lesson.client.user.get_full_name()}\n"
                else:
                    message += f"👨‍🏫 Ментор: {lesson.mentor.get_full_name()}\n"
                
                if lesson.description:
                    desc = lesson.description[:200] + "..." if len(lesson.description) > 200 else lesson.description
                    message += f"\n📄 {desc}\n"
                
                if lesson.meeting_url:
                    message += f"\n🔗 <a href='{lesson.meeting_url}'>Ссылка на видеоконференцию</a>\n"
                
                if lesson.mentor_grade is not None:
                    message += f"\n🎯 Оценка: {lesson.mentor_grade}/100\n"
                
                inline_keyboard = [[
                    InlineKeyboardButton(
                        "🌐 Открыть на сайте",
                        url=f"{settings.FRONTEND_URL}/schedule"
                    )
                ]]
                
                reply_markup = InlineKeyboardMarkup(inline_keyboard)
                await query.edit_message_text(message, parse_mode='HTML', reply_markup=reply_markup)
                
            except Lesson.DoesNotExist:
                await query.answer("❌ Занятие не найдено", show_alert=True)
            except Exception as e:
                logger.error(f"Error handling lesson detail: {e}", exc_info=True)
                await query.answer("❌ Ошибка обработки запроса", show_alert=True)
            return
        
        # Обработка деталей клиента (для менторов)
        if query.data.startswith('client_detail_'):
            try:
                client_id = int(query.data.replace('client_detail_', ''))
                
                from apps.users.models import Client, User
                from apps.schedule.models import Lesson
                from apps.homework.models import HomeworkSubmission
                from django.utils import timezone
                from datetime import timedelta
                
                client = await sync_to_async(
                    Client.objects.select_related('user').get
                )(id=client_id)
                
                user = update.effective_user
                telegram_id = user.id
                db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
                
                if not db_user or db_user.role != 'mentor' or db_user not in await sync_to_async(list)(client.mentors.all()):
                    await query.answer("❌ У вас нет доступа", show_alert=True)
                    return
                
                client_name = client.user.get_full_name() or client.user.email
                message = f"👤 <b>{client_name}</b>\n\n"
                
                # Статистика занятий
                all_lessons = await sync_to_async(list)(
                    Lesson.objects.filter(mentor=db_user, client=client)
                )
                total_lessons = len(all_lessons)
                completed_lessons = len([l for l in all_lessons if l.status == 'completed'])
                upcoming_lessons = len([
                    l for l in all_lessons 
                    if l.start_time >= timezone.now() and l.status == 'scheduled'
                ])
                
                # Занятия за месяц
                month_ago = timezone.now() - timedelta(days=30)
                lessons_this_month = len([
                    l for l in all_lessons 
                    if l.start_time >= month_ago
                ])
                
                message += f"📚 <b>Занятия:</b>\n"
                message += f"• Всего: {total_lessons}\n"
                message += f"• Завершено: {completed_lessons}\n"
                message += f"• Предстоящих: {upcoming_lessons}\n"
                message += f"• За месяц: {lessons_this_month}\n\n"
                
                # Статистика ДЗ
                all_submissions = await sync_to_async(list)(
                    HomeworkSubmission.objects.filter(
                        homework__mentor=db_user,
                        student=client.user
                    )
                )
                total_homeworks = len(all_submissions)
                pending_homeworks = len([s for s in all_submissions if s.status == 'pending'])
                graded_homeworks = len([s for s in all_submissions if s.status == 'graded'])
                
                message += f"📝 <b>Домашние задания:</b>\n"
                message += f"• Всего решений: {total_homeworks}\n"
                message += f"• На проверке: {pending_homeworks}\n"
                message += f"• Проверено: {graded_homeworks}\n"
                
                if graded_homeworks > 0:
                    scores = [s.score for s in all_submissions if s.score is not None]
                    avg_score = sum(scores) / len(scores) if scores else 0
                    message += f"• Средний балл: {avg_score:.1f}\n"
                
                # Доходы от клиента
                lessons_with_price = [l for l in all_lessons if l.price and l.status == 'completed']
                if lessons_with_price:
                    total_revenue = sum([float(l.price) for l in lessons_with_price])
                    message += f"\n💰 <b>Доходы:</b>\n"
                    message += f"• Всего: {total_revenue:.2f} ₽\n"
                
                inline_keyboard = [[
                    InlineKeyboardButton(
                        "🌐 Открыть на сайте",
                        url=f"{settings.FRONTEND_URL}/students"
                    ),
                    InlineKeyboardButton(
                        "◀️ Назад к списку",
                        callback_data="clients_back"
                    )
                ]]
                
                reply_markup = InlineKeyboardMarkup(inline_keyboard)
                await query.edit_message_text(message, parse_mode='HTML', reply_markup=reply_markup)
                
            except Client.DoesNotExist:
                await query.answer("❌ Клиент не найден", show_alert=True)
            except Exception as e:
                logger.error(f"Error handling client detail: {e}", exc_info=True)
                await query.answer("❌ Ошибка обработки запроса", show_alert=True)
            return
        
        # Обработка возврата к списку клиентов
        if query.data == 'clients_back':
            try:
                user = update.effective_user
                telegram_id = user.id
                db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
                
                if not db_user or db_user.role != 'mentor':
                    await query.answer("❌ Ошибка", show_alert=True)
                    return
                
                from apps.users.models import Client
                clients = await sync_to_async(list)(
                    Client.objects.filter(mentors=db_user).select_related('user')[:10]
                )
                
                if not clients:
                    await query.edit_message_text("👥 У вас пока нет клиентов.")
                    return
                
                message = "👥 <b>Ваши клиенты:</b>\n\n"
                inline_keyboard = []
                
                for client in clients:
                    client_name = client.user.get_full_name() or client.user.email
                    message += f"👤 <b>{client_name}</b>\n\n"
                    inline_keyboard.append([
                        InlineKeyboardButton(
                            f"👤 {client_name[:30]}",
                            callback_data=f"client_detail_{client.id}"
                        )
                    ])
                
                reply_markup = InlineKeyboardMarkup(inline_keyboard)
                await query.edit_message_text(message, parse_mode='HTML', reply_markup=reply_markup)
                
            except Exception as e:
                logger.error(f"Error handling clients back: {e}", exc_info=True)
                await query.answer("❌ Ошибка", show_alert=True)
            return
        
        # Обработка подтверждения занятия (Занятие состоялось / Занятие отменилось)
        if query.data.startswith('lesson_confirm_') or query.data.startswith('lesson_cancel_'):
            try:
                lesson_id = int(query.data.split('_')[-1])
                is_confirmed = query.data.startswith('lesson_confirm_')

                from apps.schedule.models import Lesson
                from django.utils import timezone

                lesson = await sync_to_async(
                    Lesson.objects.select_related('client', 'client__user', 'mentor').get
                )(id=lesson_id)
                user = update.effective_user
                telegram_id = user.id

                # Только ментор может подтверждать
                if not lesson.mentor or lesson.mentor.telegram_id != telegram_id:
                    await query.answer("❌ Только ментор занятия может подтвердить.", show_alert=True)
                    return

                if is_confirmed:
                    # Занятие состоялось — оставляем completed
                    await query.edit_message_text(
                        f"✅ <b>Подтверждено</b>\n\n"
                        f"Занятие «{lesson.title}» состоялось."
                    )
                else:
                    # Занятие отменилось — меняем статус
                    lesson.status = 'cancelled'
                    lesson.cancelled_at = timezone.now()
                    await sync_to_async(lesson.save)(update_fields=['status', 'cancelled_at'])
                    await query.edit_message_text(
                        f"❌ <b>Отменено</b>\n\n"
                        f"Занятие «{lesson.title}» отмечено как отменённое."
                    )

                await query.answer()
            except Lesson.DoesNotExist:
                await query.answer("❌ Занятие не найдено", show_alert=True)
            except Exception as e:
                logger.error(f"Error handling lesson confirmation: {e}", exc_info=True)
                await query.answer("❌ Ошибка обработки", show_alert=True)
            return

        # Обработка подтверждения присутствия
        if query.data.startswith('attendance_yes_') or query.data.startswith('attendance_no_'):
            try:
                lesson_id = int(query.data.split('_')[-1])
                response_bool = query.data.startswith('attendance_yes_')
                
                from apps.schedule.models import Lesson
                from django.utils import timezone
                
                lesson = await sync_to_async(Lesson.objects.select_related('client', 'client__user', 'mentor').get)(id=lesson_id)
                user = update.effective_user
                telegram_id = user.id
                
                # Проверяем, что пользователь - студент этого занятия
                if not lesson.client or lesson.client.user.telegram_id != telegram_id:
                    await query.edit_message_text(
                        "❌ Ошибка: вы не являетесь студентом этого занятия"
                    )
                    return
                
                # Сохраняем ответ
                lesson.attendance_confirmed = response_bool
                lesson.attendance_response_at = timezone.now()
                await sync_to_async(lesson.save)(update_fields=['attendance_confirmed', 'attendance_response_at'])
                
                # Отправляем уведомление ментору
                from apps.notifications.services import NotificationService
                await sync_to_async(NotificationService.send_attendance_response_to_mentor)(lesson, response_bool)
                
                response_text = "будете присутствовать" if response_bool else "не сможете присутствовать"
                
                await query.edit_message_text(
                    f"✅ <b>Ответ сохранен</b>\n\n"
                    f"Вы подтвердили, что {response_text} на занятии:\n"
                    f"<b>{lesson.title}</b>\n\n"
                    f"Преподаватель получил уведомление."
                )
                
            except Lesson.DoesNotExist:
                await query.edit_message_text("❌ Занятие не найдено")
            except Exception as e:
                logger.error(f"Error processing attendance confirmation: {e}")
                await query.edit_message_text("❌ Ошибка обработки ответа")
            return
        
        # Обработка настроек уведомлений
        user = update.effective_user
        telegram_id = user.id
        
        from apps.users.models import User
        
        try:
            db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
            
            if not db_user:
                await query.edit_message_text("❌ Аккаунт не связан.")
                return
            
            preferences = await sync_to_async(lambda: db_user.notification_preferences)()
            
            # Переключение всех уведомлений
            if query.data == "settings_toggle_all":
                preferences.enabled = not preferences.enabled
                await sync_to_async(preferences.save)()
                await self._refresh_settings_message(query, db_user, preferences)
                return
            
            # Переключение Telegram уведомлений
            elif query.data == "settings_toggle_telegram":
                preferences.telegram_enabled = not preferences.telegram_enabled
                await sync_to_async(preferences.save)()
                await self._refresh_settings_message(query, db_user, preferences)
                return
            
            # Переключение Email уведомлений
            elif query.data == "settings_toggle_email":
                preferences.email_enabled = not preferences.email_enabled
                await sync_to_async(preferences.save)()
                await self._refresh_settings_message(query, db_user, preferences)
                return
            
            # Режим тишины
            elif query.data == "settings_quiet_hours":
                await self._handle_quiet_hours(query, db_user, preferences)
                return
            
            # Типы уведомлений
            elif query.data == "settings_notification_types":
                await self._handle_notification_types(query, db_user, preferences)
                return
            
            # Часовой пояс — кнопка убрана
            elif query.data == "settings_timezone":
                await query.answer()
                await self._refresh_settings_message(query, db_user, preferences)
                return
            
            # Язык
            elif query.data == "settings_language":
                await self._handle_language(query, db_user)
                return
            
            # Обработка типов уведомлений
            elif query.data.startswith("toggle_type_"):
                ntype = query.data.replace("toggle_type_", "")
                type_prefs = preferences.type_preferences.get(ntype, {})
                if not isinstance(type_prefs, dict):
                    type_prefs = {}
                
                current = type_prefs.get('telegram', True)
                type_prefs['telegram'] = not current
                preferences.type_preferences[ntype] = type_prefs
                await sync_to_async(preferences.save)()
                
                await query.answer("Настройка обновлена")
                await self._handle_notification_types(query, db_user, preferences)
                return
            
            # Установка часового пояса (меню убрано)
            elif query.data.startswith("set_timezone_"):
                await query.answer()
                await self._refresh_settings_message(query, db_user, preferences)
                return
            
            # Установка языка
            elif query.data.startswith("set_language_"):
                language = query.data.replace("set_language_", "")
                db_user.language = language
                await sync_to_async(db_user.save)(update_fields=['language'])
                await query.answer(f"Язык установлен: {language}")
                await self._handle_language(query, db_user)
                return
            
            # Возврат к настройкам
            elif query.data == "settings_back":
                preferences = await sync_to_async(lambda: db_user.notification_preferences)()
                await self._refresh_settings_message(query, db_user, preferences)
                return
            
            # Старый обработчик для обратной совместимости
            elif query.data == "toggle_notifications":
                preferences.telegram_enabled = not preferences.telegram_enabled
                await sync_to_async(preferences.save)()
                await self._refresh_settings_message(query, db_user, preferences)
                return
        
        except Exception as e:
            logger.error(f"Error handling settings callback: {e}", exc_info=True)
            await query.edit_message_text(
                "❌ Ошибка обновления настроек."
            )
    
    async def schedule_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Обработчик команды /schedule - показать расписание."""
        user = update.effective_user
        telegram_id = user.id
        
        from apps.users.models import User
        
        try:
            db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
            
            if not db_user:
                await update.message.reply_text(
                    "❌ Аккаунт не связан.\n\n"
                    "Используйте /link <код> для связывания аккаунта."
                )
                return
            
            # Получаем ближайшие занятия
            from apps.schedule.models import Lesson
            from django.utils import timezone
            
            now = timezone.now()
            
            # Для ментора - все занятия
            if db_user.role == 'mentor':
                lessons = await sync_to_async(list)(
                    Lesson.objects.filter(
                        mentor=db_user,
                        start_time__gte=now
                    ).select_related('mentor', 'client', 'client__user').order_by('start_time')[:5]
                )
            # Для клиента - только его занятия
            elif db_user.role == 'client':
                # Проверяем наличие Client профиля
                try:
                    from apps.users.models import Client
                    client_profile = await sync_to_async(
                        Client.objects.filter(user=db_user).first
                    )()
                    
                    if not client_profile:
                        await update.message.reply_text(
                            "❌ Профиль клиента не найден.\n\n"
                            "Обратитесь к администратору для настройки профиля."
                        )
                        return
                except Exception as e:
                    logger.error(f"Error getting client profile: {e}")
                    await update.message.reply_text(
                        "❌ Ошибка получения профиля клиента."
                    )
                    return
                
                lessons = await sync_to_async(list)(
                    Lesson.objects.filter(
                        client=client_profile,
                        start_time__gte=now
                    ).select_related('mentor', 'client', 'client__user').order_by('start_time')[:5]
                )
            # Для родителя - занятия всех детей
            elif db_user.role == 'parent':
                from apps.users.models import Parent
                try:
                    parent_profile = await sync_to_async(lambda: db_user.parent_profile)()
                    children = await sync_to_async(list)(parent_profile.children.all())
                    
                    if not children:
                        keyboard = await get_user_keyboard(telegram_id)
                        await update.message.reply_text(
                            "❌ У вас нет привязанных детей.\n\n"
                            "Обратитесь к администратору для привязки детей к вашему аккаунту.",
                            reply_markup=keyboard
                        )
                        return
                    
                    # Получаем занятия всех детей
                    child_clients = list(children)  # children уже список Client объектов
                    lessons = await sync_to_async(list)(
                        Lesson.objects.filter(
                            client__in=child_clients,
                            start_time__gte=now
                        ).select_related('mentor', 'client', 'client__user').order_by('start_time')[:5]
                    )
                except:
                    await update.message.reply_text(
                        "❌ Ошибка получения данных родителя."
                    )
                    return
            else:
                await update.message.reply_text(
                    "❌ Эта команда доступна только для менторов, клиентов и родителей."
                )
                return
            
            if not lessons:
                await update.message.reply_text(
                    "📅 У вас нет предстоящих занятий."
                )
                return
            
            message = "📅 <b>Ближайшие занятия:</b>\n\n"
            
            for lesson in lessons:
                import pytz
                from apps.users.utils import get_user_timezone
                user_tz = get_user_timezone(db_user.timezone or 'UTC')
                if timezone.is_aware(lesson.start_time):
                    local_time = lesson.start_time.astimezone(user_tz)
                else:
                    utc_time = timezone.make_aware(lesson.start_time, pytz.UTC)
                    local_time = utc_time.astimezone(user_tz)
                
                time_str = local_time.strftime('%d.%m.%Y в %H:%M')
                
                if db_user.role == 'mentor':
                    student_name = lesson.client.user.get_full_name() if lesson.client and lesson.client.user else 'Студент'
                    message += f"📚 <b>{lesson.title}</b>\n"
                    message += f"👤 {student_name}\n"
                elif db_user.role == 'parent':
                    child_name = lesson.client.user.get_full_name() if lesson.client and lesson.client.user else 'Ребёнок'
                    message += f"📚 <b>{lesson.title}</b>\n"
                    message += f"👨‍🏫 {lesson.mentor.get_full_name()}\n"
                    message += f"👶 {child_name}\n"
                else:
                    message += f"📚 <b>{lesson.title}</b>\n"
                    message += f"👨‍🏫 {lesson.mentor.get_full_name()}\n"
                
                message += f"🕐 {time_str}\n\n"
            
            await update.message.reply_text(message, parse_mode='HTML')
        
        except Exception as e:
            logger.error(f"Error in schedule_command: {e}", exc_info=True)
            keyboard = await get_user_keyboard(telegram_id)
            await update.message.reply_text(
                "❌ Ошибка получения расписания.\n\n"
                "Попробуйте позже или обратитесь в поддержку.",
                reply_markup=keyboard
            )
    
    async def nextlesson_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Обработчик команды /nextlesson - показать следующее занятие."""
        user = update.effective_user
        telegram_id = user.id
        
        from apps.users.models import User
        
        try:
            db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
            
            if not db_user:
                keyboard = get_main_keyboard(None)
                await update.message.reply_text(
                    "❌ Аккаунт не связан.\n\n"
                    "Используйте /link <код> для связывания аккаунта.",
                    reply_markup=keyboard
                )
                return
            
            from apps.schedule.models import Lesson
            from django.utils import timezone
            
            now = timezone.now()
            
            # Находим ближайшее занятие
            if db_user.role == 'mentor':
                lesson = await sync_to_async(
                    Lesson.objects.filter(
                        mentor=db_user,
                        start_time__gte=now
                    ).select_related('mentor', 'client', 'client__user').order_by('start_time').first
                )()
            elif db_user.role == 'client':
                # Проверяем наличие Client профиля
                try:
                    from apps.users.models import Client
                    client_profile = await sync_to_async(
                        Client.objects.filter(user=db_user).first
                    )()
                    
                    if not client_profile:
                        keyboard = await get_user_keyboard(telegram_id)
                        await update.message.reply_text(
                            "❌ Профиль клиента не найден.\n\n"
                            "Обратитесь к администратору для настройки профиля.",
                            reply_markup=keyboard
                        )
                        return
                except Exception as e:
                    logger.error(f"Error getting client profile: {e}")
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text(
                        "❌ Ошибка получения профиля клиента.",
                        reply_markup=keyboard
                    )
                    return
                
                lesson = await sync_to_async(
                    Lesson.objects.filter(
                        client=client_profile,
                        start_time__gte=now
                    ).select_related('mentor', 'client', 'client__user').order_by('start_time').first
                )()
            elif db_user.role == 'parent':
                from apps.users.models import Parent
                try:
                    parent_profile = await sync_to_async(lambda: db_user.parent_profile)()
                    children = await sync_to_async(list)(parent_profile.children.all())
                    
                    if not children:
                        keyboard = await get_user_keyboard(telegram_id)
                        await update.message.reply_text(
                            "❌ У вас нет привязанных детей.",
                            reply_markup=keyboard
                        )
                        return
                    
                    child_clients = list(children)  # children уже список Client объектов
                    lesson = await sync_to_async(
                        Lesson.objects.filter(
                            client__in=child_clients,
                            start_time__gte=now
                        ).select_related('mentor', 'client', 'client__user').order_by('start_time').first
                    )()
                except:
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text(
                        "❌ Ошибка получения данных родителя.",
                        reply_markup=keyboard
                    )
                    return
            else:
                keyboard = await get_user_keyboard(telegram_id)
                await update.message.reply_text(
                    "❌ Эта команда доступна только для менторов, клиентов и родителей.",
                    reply_markup=keyboard
                )
                return
            
            if not lesson:
                keyboard = await get_user_keyboard(telegram_id)
                await update.message.reply_text(
                    "📅 У вас нет предстоящих занятий.",
                    reply_markup=keyboard
                )
                return
            
            import pytz
            from apps.users.utils import get_user_timezone
            user_tz = get_user_timezone(db_user.timezone or 'UTC')
            if timezone.is_aware(lesson.start_time):
                local_time = lesson.start_time.astimezone(user_tz)
            else:
                utc_time = timezone.make_aware(lesson.start_time, pytz.UTC)
                local_time = utc_time.astimezone(user_tz)
            
            time_str = local_time.strftime('%d.%m.%Y в %H:%M')
            
            message = "📚 <b>Следующее занятие:</b>\n\n"
            message += f"<b>{lesson.title}</b>\n"
            
            if db_user.role == 'mentor':
                student_name = lesson.client.user.get_full_name() if lesson.client and lesson.client.user else 'Студент'
                message += f"👤 {student_name}\n"
            elif db_user.role == 'parent':
                child_name = lesson.client.user.get_full_name() if lesson.client and lesson.client.user else 'Ребёнок'
                message += f"👨‍🏫 {lesson.mentor.get_full_name()}\n"
                message += f"👶 {child_name}\n"
            else:
                message += f"👨‍🏫 {lesson.mentor.get_full_name()}\n"
            
            message += f"🕐 {time_str}\n"
            
            if lesson.description:
                message += f"\n📝 {lesson.description[:200]}"
            
            keyboard = await get_user_keyboard(telegram_id)
            await update.message.reply_text(message, parse_mode='HTML', reply_markup=keyboard)
        
        except Exception as e:
            logger.error(f"Error in nextlesson_command: {e}", exc_info=True)
            keyboard = await get_user_keyboard(telegram_id)
            await update.message.reply_text(
                "❌ Ошибка получения следующего занятия.\n\n"
                "Попробуйте позже или обратитесь в поддержку.",
                reply_markup=keyboard
            )
    
    async def _get_client_homework_detail(self, homework_id: int, db_user):
        """Вернуть (текст сообщения, ReplyKeyboardMarkup) для деталей задания клиента."""
        from apps.homework.models import Homework, HomeworkSubmission
        
        # Используем sync_to_async правильно для всех DB операций
        try:
            # Получаем homework с prefetch для оптимизации
            homework = await sync_to_async(
                lambda: Homework.objects.select_related('mentor').prefetch_related('assigned_to').get(id=homework_id)
            )()
        except Homework.DoesNotExist:
            return None, None
        
        # Проверяем доступ (используем sync_to_async для проверки M2M)
        assigned_users = await sync_to_async(list)(homework.assigned_to.all())
        if db_user.role != 'client' or db_user not in assigned_users:
            return None, None
        
        deadline_str = homework.deadline.strftime('%d.%m.%Y в %H:%M') if homework.deadline else 'Без дедлайна'
        
        # Получаем submission через sync_to_async
        submission = await sync_to_async(
            lambda: HomeworkSubmission.objects.filter(homework=homework, student=db_user).first()
        )()
        
        message = f"📝 <b>{homework.title}</b>\n\n"
        message += f"📅 Дедлайн: {deadline_str}\n"
        message += f"🎯 Макс. баллов: {homework.max_score}\n"
        if homework.description:
            desc = homework.description[:300] + "..." if len(homework.description) > 300 else homework.description
            message += f"\n📄 {desc}\n"
        
        if submission:
            message += f"\n✅ <b>Статус: Сдано</b>\n"
            if submission.status == 'graded' and submission.score is not None:
                message += f"🎯 Оценка: {submission.score}/{homework.max_score}\n"
                # Краткий комментарий к оценке — студент видит, что есть отзыв
                comment = (submission.feedback or submission.ai_feedback or "").strip()
                if comment:
                    preview = comment[:120] + "…" if len(comment) > 120 else comment
                    import html as _html
                    message += f"💬 <i>{_html.escape(preview)}</i>\n"
            elif submission.status == 'returned':
                message += f"🔄 Возвращено на доработку\n"
            else:
                message += f"⏳ Ожидает проверки\n"
        else:
            message += f"\n⏳ <b>Статус: Не сдано</b>\n"
        
        # Создаём Reply клавиатуру для управления ДЗ
        keyboard_buttons = []
        if not submission or submission.status == 'returned':
            keyboard_buttons.append([KeyboardButton("📎 Загрузить решение")])
        if submission:
            keyboard_buttons.append([KeyboardButton("👁️ Просмотреть решение")])
        keyboard_buttons.append([KeyboardButton("◀️ Назад к списку"), KeyboardButton("🏠 В главное меню")])
        
        reply_keyboard = ReplyKeyboardMarkup(keyboard_buttons, resize_keyboard=True, one_time_keyboard=False)
        return message, reply_keyboard
    
    async def _show_submission_view(self, update: Update, context: ContextTypes.DEFAULT_TYPE, submission, db_user):
        """Показать просмотр решения ДЗ (оценка и комментарии к работе)."""
        import html as _html
        
        message = f"👁️ <b>Решение ДЗ</b>\n\n"
        message += f"📝 Задание: {submission.homework.title}\n"
        message += f"📅 Сдано: {submission.submitted_at.strftime('%d.%m.%Y в %H:%M') if submission.submitted_at else 'Неизвестно'}\n"
        message += f"📊 Статус: {submission.get_status_display()}\n"
        
        if submission.score is not None:
            message += f"🎯 Оценка: {submission.score}/{submission.homework.max_score}\n"
        
        # Комментарий к оценённой работе — студент должен всегда видеть отзыв
        mentor_fb = (submission.feedback or "").strip()
        ai_fb = (submission.ai_feedback or "").strip() if submission.ai_checked_at else ""
        
        if mentor_fb or ai_fb:
            message += f"\n📋 <b>Комментарий к вашей работе:</b>\n"
            if mentor_fb:
                feedback_esc = _html.escape(mentor_fb[:800] + "..." if len(mentor_fb) > 800 else mentor_fb)
                message += f"💬 <i>{feedback_esc}</i>\n"
            if ai_fb and ai_fb != mentor_fb:
                ai_esc = _html.escape(ai_fb[:800] + "..." if len(ai_fb) > 800 else ai_fb)
                message += f"🤖 <i>{ai_esc}</i>\n"
        elif submission.status == 'graded':
            message += f"\n📋 <b>Комментарий к вашей работе:</b> нет текста отзыва.\n"
        
        message += f"\n🌐 <a href='{settings.FRONTEND_URL}/homework'>Открыть на сайте</a>"
        
        await update.message.reply_text(message, parse_mode='HTML', disable_web_page_preview=True)

    async def homework_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Обработчик команды /homework - показать домашние задания."""
        user = update.effective_user
        telegram_id = user.id
        
        from apps.users.models import User
        
        try:
            db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
            
            if not db_user:
                await update.message.reply_text(
                    "❌ Аккаунт не связан.\n\n"
                    "Используйте /link <код> для связывания аккаунта."
                )
                return
            
            from apps.homework.models import Homework, HomeworkSubmission
            
            # Для клиента - показать его задания
            if db_user.role == 'client':
                # Используем правильный sync_to_async для избежания ошибки SynchronousOnlyOperation
                def get_client_homeworks():
                    return list(Homework.objects.filter(
                        assigned_to=db_user,
                        deadline__gte=timezone.now()
                    ).order_by('deadline')[:5])
                
                homeworks = await sync_to_async(get_client_homeworks)()
                
                if not homeworks:
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text(
                        "📝 У вас нет активных домашних заданий.",
                        reply_markup=keyboard
                    )
                    return
                
                # Если только одно задание, показываем его сразу с Reply клавиатурой
                if len(homeworks) == 1:
                    hw = homeworks[0]
                    context.user_data['current_homework_id'] = hw.id
                    msg, reply_markup = await self._get_client_homework_detail(hw.id, db_user)
                    if msg and reply_markup:
                        await update.message.reply_text(msg, parse_mode='HTML', reply_markup=reply_markup)
                    else:
                        keyboard = await get_user_keyboard(telegram_id)
                        await update.message.reply_text("❌ Ошибка загрузки задания.", reply_markup=keyboard)
                else:
                    # Несколько заданий: список в виде кнопок в панели Telegram
                    homework_keyboard, homework_buttons = make_homework_list_keyboard(homeworks)
                    context.user_data['homework_buttons'] = homework_buttons
                    context.user_data['homework_list_active'] = True
                    await update.message.reply_text(
                        "📝 <b>Домашние задания</b>\n\nВыберите задание кнопкой в панели ниже:",
                        parse_mode='HTML',
                        reply_markup=homework_keyboard
                    )
            
            # Для родителя - показать задания всех детей
            elif db_user.role == 'parent':
                from apps.users.models import Parent
                try:
                    parent_profile = await sync_to_async(lambda: db_user.parent_profile)()
                    children = await sync_to_async(list)(parent_profile.children.all())
                    
                    if not children:
                        await update.message.reply_text(
                            "❌ У вас нет привязанных детей."
                        )
                        return
                    
                    child_users = [child.user for child in children]
                    homeworks = await sync_to_async(list)(
                        Homework.objects.filter(
                            assigned_to__in=child_users,
                            deadline__gte=timezone.now()
                        ).order_by('deadline')[:5]
                    )
                    
                    if not homeworks:
                        await update.message.reply_text(
                            "📝 У ваших детей нет активных домашних заданий."
                        )
                        return
                    
                    message = "📝 <b>Домашние задания детей:</b>\n\n"
                    
                    for hw in homeworks:
                        deadline_str = hw.deadline.strftime('%d.%m.%Y') if hw.deadline else 'Без дедлайна'
                        
                        # Находим для какого ребёнка это задание
                        child_students = [student for student in hw.assigned_to.all() if student in child_users]
                        child_names = ', '.join([child.get_full_name() for child in child_students[:2]])
                        if len(child_students) > 2:
                            child_names += f" и ещё {len(child_students) - 2}"
                        
                        message += f"<b>{hw.title}</b>\n"
                        message += f"👶 {child_names}\n"
                        message += f"📅 Дедлайн: {deadline_str}\n\n"
                    
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text(message, parse_mode='HTML', reply_markup=keyboard)
                except Exception as e:
                    logger.error(f"Error in homework_command for parent: {e}")
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text(
                        "❌ Ошибка получения домашних заданий.",
                        reply_markup=keyboard
                    )
            
            # Для ментора - показать задания требующие проверки
            elif db_user.role == 'mentor':
                def _mentor_submissions_display(mentor_user):
                    qs = HomeworkSubmission.objects.filter(
                        homework__mentor=mentor_user,
                        status='pending'
                    ).select_related('homework', 'student').order_by('-submitted_at')[:5]
                    return [
                        {
                            'id': s.id,
                            'student_name': (s.student.get_full_name() or 'Студент') if s.student else 'Студент',
                            'hw_title': (s.homework.title or 'Без названия') if s.homework else 'Без названия',
                            'submitted_at': s.submitted_at.strftime('%d.%m.%Y') if s.submitted_at else 'Неизвестно',
                            'ai_checked_at': getattr(s, 'ai_checked_at', None),
                        }
                        for s in qs
                    ]
                submissions_data = await sync_to_async(_mentor_submissions_display)(db_user)
                if not submissions_data:
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text(
                        "📝 Нет домашних заданий, требующих проверки.",
                        reply_markup=keyboard
                    )
                    return
                message = "📝 <b>Домашние задания на проверку:</b>\n\n"
                inline_keyboard = []
                for item in submissions_data:
                    ai_status = " 🤖 ИИ проверил" if item['ai_checked_at'] else ""
                    message += f"<b>{item['hw_title']}</b>{ai_status}\n"
                    message += f"👤 {item['student_name']}\n"
                    message += f"📅 Сдано: {item['submitted_at']}\n\n"
                    btn_text = f"👁️ {item['hw_title'][:28]} — {item['student_name'][:15]}"
                    if len(btn_text) > 60:
                        btn_text = btn_text[:57] + "..."
                    inline_keyboard.append([
                        InlineKeyboardButton(btn_text, callback_data=f"mentor_submission_{item['id']}")
                    ])
                reply_markup = InlineKeyboardMarkup(inline_keyboard)
                await update.message.reply_text(message, parse_mode='HTML', reply_markup=reply_markup)
            else:
                keyboard = await get_user_keyboard(telegram_id)
                await update.message.reply_text(
                    "❌ Эта команда доступна только для менторов, клиентов и родителей.",
                    reply_markup=keyboard
                )
        
        except Exception as e:
            logger.exception("Error in homework_command: %s", e)
            keyboard = await get_user_keyboard(telegram_id)
            await update.message.reply_text(
                "❌ Ошибка получения домашних заданий.",
                reply_markup=keyboard
            )
    
    async def _handle_text_homework_submission(self, update: Update, context: ContextTypes.DEFAULT_TYPE, db_user, homework_id: int, text_content: str):
        """
        Обработка текстового решения домашнего задания.
        
        Args:
            update: Update объект от Telegram
            context: Context объект
            db_user: Пользователь из базы данных
            homework_id: ID домашнего задания
            text_content: Текстовое содержание решения
        """
        try:
            from apps.homework.models import Homework, HomeworkSubmission
            from django.utils import timezone as tz
            
            homework = await sync_to_async(Homework.objects.get)(id=homework_id)
            
            # Проверяем, что пользователь имеет право сдавать это ДЗ
            if db_user.role != 'client' or db_user not in await sync_to_async(list)(homework.assigned_to.all()):
                await update.message.reply_text(
                    "❌ У вас нет доступа к этому заданию."
                )
                context.user_data.pop('waiting_for_homework_file', None)
                return
            
            # Проверяем, есть ли уже решение
            existing_submission = await sync_to_async(
                HomeworkSubmission.objects.filter(
                    homework=homework,
                    student=db_user
                ).order_by('-attempt_number').first
            )()
            
            if existing_submission and existing_submission.status != 'returned':
                # Обновляем существующее решение
                existing_submission.content = text_content
                existing_submission.status = 'pending'
                await sync_to_async(existing_submission.save)()
                
                await update.message.reply_text(
                    f"✅ <b>Решение обновлено!</b>\n\n"
                    f"📝 Задание: {homework.title}\n\n"
                    f"Решение отправлено на проверку.",
                    parse_mode='HTML'
                )
            else:
                # Определяем номер попытки
                attempt_number = 1
                if existing_submission:
                    attempt_number = existing_submission.attempt_number + 1
                
                # Создаем новое решение
                submission = HomeworkSubmission(
                    homework=homework,
                    student=db_user,
                    content=text_content,
                    status='pending',
                    attempt_number=attempt_number
                )
                await sync_to_async(submission.save)()
                
                # Проверяем опоздание
                await sync_to_async(submission.check_if_late)()
                
                # Обновляем статистику задания
                await sync_to_async(homework.update_statistics)()
                
                await update.message.reply_text(
                    f"✅ <b>Решение загружено!</b>\n\n"
                    f"📝 Задание: {homework.title}\n\n"
                    f"Решение отправлено на проверку.",
                    parse_mode='HTML'
                )
            
            # Отправляем уведомление ментору
            from apps.notifications.services import NotificationService
            await sync_to_async(NotificationService.create_notification_with_telegram)(
                recipient=homework.mentor,
                notification_type='homework_submitted',
                title='📝 ДЗ сдано',
                message=f'{db_user.get_full_name()} сдал ДЗ "{homework.title}"',
                priority='normal',
                action_url=f'/homework/{homework.id}/',
                content_object=homework
            )
            
            # Очищаем состояние ожидания
            context.user_data.pop('waiting_for_homework_file', None)
            
            keyboard = await get_user_keyboard(update.effective_user.id)
            await update.message.reply_text(
                "Используйте кнопки для навигации:",
                reply_markup=keyboard
            )
        
        except Homework.DoesNotExist:
            await update.message.reply_text(
                "❌ Домашнее задание не найдено."
            )
            context.user_data.pop('waiting_for_homework_file', None)
        except Exception as e:
            logger.error(f"Error handling text homework submission: {e}", exc_info=True)
            await update.message.reply_text(
                "❌ Ошибка загрузки решения.\n\n"
                "Попробуйте позже или обратитесь в поддержку."
            )
            context.user_data.pop('waiting_for_homework_file', None)
    
    async def _handle_submission_grade_input(self, update: Update, context: ContextTypes.DEFAULT_TYPE, db_user, submission_id: int, message_text: str):
        """Обработка ввода оценки для submission."""
        try:
            from apps.homework.models import HomeworkSubmission
            from django.utils import timezone
            
            from apps.homework.models import Homework
            submission = await sync_to_async(
                HomeworkSubmission.objects.select_related('homework', 'student').get
            )(id=submission_id)
            homework_mentor_id = await sync_to_async(
                lambda hw_id: Homework.objects.values_list('mentor_id', flat=True).get(id=hw_id)
            )(submission.homework_id)
            if db_user.role != 'mentor' or homework_mentor_id != db_user.id:
                await update.message.reply_text("❌ У вас нет доступа к этому заданию.")
                context.user_data.pop('waiting_for_submission_score', None)
                return
            
            hw_max_score = await sync_to_async(lambda s: s.homework.max_score)(submission)
            # Парсим ввод: может быть только оценка или "оценка\nкомментарий"
            lines = message_text.strip().split('\n', 1)
            score_text = lines[0].strip()
            feedback_text = lines[1].strip() if len(lines) > 1 else None
            
            # Пытаемся извлечь оценку
            try:
                score = float(score_text.replace(',', '.'))
                score = int(round(score))
            except ValueError:
                await update.message.reply_text(
                    f"❌ Неверный формат оценки.\n\n"
                    f"Введите число от 1 до {hw_max_score}."
                )
                return
            
            # Проверяем диапазон
            if score < 1 or score > hw_max_score:
                await update.message.reply_text(
                    f"❌ Оценка должна быть от 1 до {hw_max_score}."
                )
                return
            
            # Если комментарий не указан, используем существующий или ai_feedback
            if not feedback_text:
                feedback_text = submission.feedback or submission.ai_feedback or ""
            
            # Выставляем оценку
            await sync_to_async(submission.grade)(score, feedback_text, checked_by=db_user)
            
            def _grade_done_and_notify(sub, sc, fb):
                sub.homework.update_statistics()
                from apps.notifications.services import NotificationService
                msg = f'Проверено ДЗ "{sub.homework.title}". Оценка: {sc}/{sub.homework.max_score}'
                if fb and str(fb).strip():
                    comment = (fb[:500] + '…') if len(fb) > 500 else fb
                    msg += f'\n\n💬 Комментарий:\n{comment}'
                NotificationService.create_notification_with_telegram(
                    recipient=sub.student,
                    notification_type='homework_reviewed',
                    title='✅ ДЗ проверено',
                    message=msg,
                    priority='normal',
                    action_url=f'/homework/{sub.homework.id}/submissions/{sub.id}/',
                    content_object=sub
                )
                return (sub.homework.title, sub.student.get_full_name(), sub.homework.max_score)
            hw_title, student_name, _hw_max = await sync_to_async(_grade_done_and_notify)(submission, score, feedback_text)
            
            context.user_data.pop('waiting_for_submission_score', None)
            
            await update.message.reply_text(
                f"✅ <b>Оценка выставлена!</b>\n\n"
                f"📝 Задание: {hw_title}\n"
                f"👤 Студент: {student_name}\n"
                f"⭐ Оценка: {score}/{_hw_max}\n"
                f"💬 Комментарий: {feedback_text[:100]}{'...' if len(feedback_text) > 100 else ''}",
                parse_mode='HTML'
            )
            
            keyboard = await get_user_keyboard(update.effective_user.id)
            await update.message.reply_text(
                "Используйте кнопки для навигации:",
                reply_markup=keyboard
            )
            
        except HomeworkSubmission.DoesNotExist:
            await update.message.reply_text("❌ Решение не найдено.")
            context.user_data.pop('waiting_for_submission_score', None)
        except Exception as e:
            logger.error(f"Error handling submission grade input: {e}", exc_info=True)
            await update.message.reply_text(
                "❌ Ошибка выставления оценки.\n\n"
                "Попробуйте позже или обратитесь в поддержку."
            )
            context.user_data.pop('waiting_for_submission_score', None)
    
    async def _handle_submission_feedback_input(self, update: Update, context: ContextTypes.DEFAULT_TYPE, db_user, submission_id: int, message_text: str):
        """Обработка ввода комментария для submission."""
        try:
            from apps.homework.models import HomeworkSubmission
            from django.utils import timezone
            
            from apps.homework.models import Homework
            submission = await sync_to_async(
                HomeworkSubmission.objects.select_related('homework', 'student').get
            )(id=submission_id)
            homework_mentor_id = await sync_to_async(
                lambda hw_id: Homework.objects.values_list('mentor_id', flat=True).get(id=hw_id)
            )(submission.homework_id)
            if db_user.role != 'mentor' or homework_mentor_id != db_user.id:
                await update.message.reply_text("❌ У вас нет доступа к этому заданию.")
                context.user_data.pop('waiting_for_submission_feedback', None)
                return
            
            # Обновляем комментарий
            submission.feedback = message_text.strip()
            await sync_to_async(submission.save)(update_fields=['feedback'])
            
            # Если есть оценка, обновляем статус на graded
            if submission.score is not None and submission.status != 'graded':
                submission.status = 'graded'
                submission.checked_by = db_user
                submission.checked_at = timezone.now()
                await sync_to_async(submission.save)(update_fields=['status', 'checked_by', 'checked_at'])
            
            await sync_to_async(lambda s: s.homework.update_statistics())(submission)
            context.user_data.pop('waiting_for_submission_feedback', None)
            hw_title_f, student_name_f = await sync_to_async(
                lambda s: (s.homework.title, s.student.get_full_name())
            )(submission)
            await update.message.reply_text(
                f"✅ <b>Ответ сохранён!</b>\n\n"
                f"📝 Задание: {hw_title_f}\n"
                f"👤 Студент: {student_name_f}\n"
                f"💬 Ответ: {message_text[:200]}{'...' if len(message_text) > 200 else ''}",
                parse_mode='HTML'
            )
            
            keyboard = await get_user_keyboard(update.effective_user.id)
            await update.message.reply_text(
                "Используйте кнопки для навигации:",
                reply_markup=keyboard
            )
            
        except HomeworkSubmission.DoesNotExist:
            await update.message.reply_text("❌ Решение не найдено.")
            context.user_data.pop('waiting_for_submission_feedback', None)
        except Exception as e:
            logger.error(f"Error handling submission feedback input: {e}", exc_info=True)
            await update.message.reply_text(
                "❌ Ошибка сохранения комментария.\n\n"
                "Попробуйте позже или обратитесь в поддержку."
            )
            context.user_data.pop('waiting_for_submission_feedback', None)
    
    async def _handle_return_revision_input(
        self, update: Update, context: ContextTypes.DEFAULT_TYPE, db_user, submission_id: int, feedback_text: str
    ):
        """Вернуть ДЗ на доработку и уведомить студента."""
        try:
            from apps.homework.models import HomeworkSubmission, Homework
            from apps.notifications.services import NotificationService
            
            submission = await sync_to_async(
                HomeworkSubmission.objects.select_related('homework', 'student').get
            )(id=submission_id)
            homework_mentor_id = await sync_to_async(
                lambda hw_id: Homework.objects.values_list('mentor_id', flat=True).get(id=hw_id)
            )(submission.homework_id)
            if db_user.role != 'mentor' or homework_mentor_id != db_user.id:
                await update.message.reply_text("❌ У вас нет доступа к этому заданию.")
                context.user_data.pop('waiting_for_return_revision', None)
                return
            
            feedback_text = (feedback_text or '').strip() or 'Нужно доработать решение.'
            
            def _do_return_and_notify():
                submission.return_for_revision(feedback_text, checked_by=db_user)
                hw_title = submission.homework.title
                student_name = submission.student.get_full_name()
                msg = f'ДЗ "{hw_title}" возвращено на доработку. Нужно отправить решение заново.'
                comment = (feedback_text[:500] + '…') if len(feedback_text) > 500 else feedback_text
                msg += f'\n\n💬 Комментарий:\n{comment}'
                NotificationService.create_notification_with_telegram(
                    recipient=submission.student,
                    notification_type='homework_returned',
                    title='🔄 ДЗ возвращено на доработку',
                    message=msg,
                    priority='normal',
                    action_url=f'/homework/{submission.homework.id}/submissions/{submission.id}/',
                    content_object=submission
                )
                return (hw_title, student_name)
            
            hw_title, student_name = await sync_to_async(_do_return_and_notify)()
            
            context.user_data.pop('waiting_for_return_revision', None)
            await update.message.reply_text(
                f"🔄 <b>ДЗ возвращено на доработку</b>\n\n"
                f"📝 Задание: {hw_title}\n"
                f"👤 Студент: {student_name}\n"
                f"💬 Комментарий отправлен. Студент получил уведомление и может отправить решение заново.",
                parse_mode='HTML'
            )
            keyboard = await get_user_keyboard(update.effective_user.id)
            await update.message.reply_text("Используйте кнопки для навигации:", reply_markup=keyboard)
        except HomeworkSubmission.DoesNotExist:
            await update.message.reply_text("❌ Решение не найдено.")
            context.user_data.pop('waiting_for_return_revision', None)
        except Exception as e:
            logger.error(f"Error handling return revision: {e}", exc_info=True)
            await update.message.reply_text("❌ Ошибка. Попробуйте позже.")
            context.user_data.pop('waiting_for_return_revision', None)
    
    async def _refresh_settings_message(self, query, db_user, preferences):
        """Обновить сообщение с настройками."""
        message_text = "⚙️ <b>Настройки</b>\n\n"
        
        all_status = "✅ Включены" if preferences.enabled else "❌ Выключены"
        telegram_status = "✅ Вкл" if preferences.telegram_enabled else "❌ Выкл"
        email_status = "✅ Вкл" if preferences.email_enabled else "❌ Выкл"
        in_app_status = "✅ Вкл" if preferences.in_app_enabled else "❌ Выкл"
        
        message_text += f"🔔 Все уведомления: {all_status}\n"
        message_text += f"📱 Telegram: {telegram_status}\n"
        message_text += f"📧 Email: {email_status}\n"
        message_text += f"💬 В приложении: {in_app_status}\n\n"
        
        if preferences.quiet_hours_enabled and preferences.quiet_hours_start and preferences.quiet_hours_end:
            quiet_start = preferences.quiet_hours_start.strftime('%H:%M')
            quiet_end = preferences.quiet_hours_end.strftime('%H:%M')
            message_text += f"🔇 Режим тишины: {quiet_start} - {quiet_end}\n\n"
        else:
            message_text += "🔇 Режим тишины: ❌ Выключен\n\n"
        
        user_lang = db_user.language or 'ru'
        lang_display = 'Русский' if user_lang == 'ru' else 'English'
        message_text += f"🌐 Язык: {lang_display}\n"
        
        keyboard = []
        keyboard.append([
            InlineKeyboardButton(
                "🔔 " + ("Выключить все" if preferences.enabled else "Включить все"),
                callback_data="settings_toggle_all"
            )
        ])
        keyboard.append([
            InlineKeyboardButton(
                "📱 Telegram: " + ("Выкл" if preferences.telegram_enabled else "Вкл"),
                callback_data="settings_toggle_telegram"
            ),
            InlineKeyboardButton(
                "📧 Email: " + ("Выкл" if preferences.email_enabled else "Вкл"),
                callback_data="settings_toggle_email"
            )
        ])
        keyboard.append([
            InlineKeyboardButton("🔇 Режим тишины", callback_data="settings_quiet_hours"),
            InlineKeyboardButton("📋 Типы уведомлений", callback_data="settings_notification_types")
        ])
        keyboard.append([
            InlineKeyboardButton("🌐 Язык", callback_data="settings_language")
        ])
        
        frontend_url = settings.FRONTEND_URL
        if frontend_url and 'localhost' not in frontend_url and '127.0.0.1' not in frontend_url:
            keyboard.append([
                InlineKeyboardButton("🌐 Открыть на сайте", url=f"{frontend_url}/profile")
            ])
        
        reply_markup = InlineKeyboardMarkup(keyboard)
        await query.edit_message_text(message_text, parse_mode='HTML', reply_markup=reply_markup)
    
    async def _handle_quiet_hours(self, query, db_user, preferences):
        """Обработка настроек режима тишины."""
        from datetime import time
        
        message_text = "🔇 <b>Режим тишины</b>\n\n"
        
        if preferences.quiet_hours_enabled and preferences.quiet_hours_start and preferences.quiet_hours_end:
            quiet_start = preferences.quiet_hours_start.strftime('%H:%M')
            quiet_end = preferences.quiet_hours_end.strftime('%H:%M')
            message_text += f"Текущий: {quiet_start} - {quiet_end}\n\n"
        else:
            message_text += "Текущий: ❌ Выключен\n\n"
        
        message_text += "Выберите действие:"
        
        keyboard = []
        
        # Предустановленные варианты
        if not preferences.quiet_hours_enabled:
            keyboard.append([
                InlineKeyboardButton("✅ Включить (22:00 - 08:00)", callback_data="quiet_hours_enable_22_8")
            ])
            keyboard.append([
                InlineKeyboardButton("✅ Включить (23:00 - 07:00)", callback_data="quiet_hours_enable_23_7")
            ])
        else:
            keyboard.append([
                InlineKeyboardButton("❌ Выключить", callback_data="quiet_hours_disable")
            ])
            keyboard.append([
                InlineKeyboardButton("🕐 Изменить время", callback_data="quiet_hours_custom")
            ])
        
        keyboard.append([
            InlineKeyboardButton("◀️ Назад к настройкам", callback_data="settings_back")
        ])
        
        reply_markup = InlineKeyboardMarkup(keyboard)
        await query.edit_message_text(message_text, parse_mode='HTML', reply_markup=reply_markup)
    
    async def _handle_notification_types(self, query, db_user, preferences):
        """Обработка настроек типов уведомлений."""
        from .models import Notification
        
        # Показываем меню выбора типов уведомлений
        message_text = "📋 <b>Типы уведомлений</b>\n\n"
        message_text += "Выберите типы уведомлений для Telegram:\n\n"
        
        # Группируем типы по категориям
        lesson_types = [t for t in Notification.TYPE_CHOICES if 'lesson' in t[0]]
        homework_types = [t for t in Notification.TYPE_CHOICES if 'homework' in t[0]]
        other_types = [t for t in Notification.TYPE_CHOICES if 'lesson' not in t[0] and 'homework' not in t[0]]
        
        keyboard = []
        
        # Кнопки для занятий
        if lesson_types:
            keyboard.append([InlineKeyboardButton("📅 Занятия", callback_data="noop")])
            for ntype, display in lesson_types:
                type_prefs = preferences.type_preferences.get(ntype, {})
                if not isinstance(type_prefs, dict):
                    type_prefs = {}
                enabled = type_prefs.get('telegram', True)
                status = "✅" if enabled else "❌"
                # Сокращаем длинные названия
                short_display = display.replace('Занятие ', '').replace(' занятие', '')
                keyboard.append([
                    InlineKeyboardButton(
                        f"{status} {short_display}",
                        callback_data=f"toggle_type_{ntype}"
                    )
                ])
        
        # Кнопки для домашних заданий
        if homework_types:
            keyboard.append([InlineKeyboardButton("📝 Домашние задания", callback_data="noop")])
            for ntype, display in homework_types:
                type_prefs = preferences.type_preferences.get(ntype, {})
                if not isinstance(type_prefs, dict):
                    type_prefs = {}
                enabled = type_prefs.get('telegram', True)
                status = "✅" if enabled else "❌"
                short_display = display.replace('Домашнее задание', 'ДЗ')
                keyboard.append([
                    InlineKeyboardButton(
                        f"{status} {short_display}",
                        callback_data=f"toggle_type_{ntype}"
                    )
                ])
        
        # Кнопки для других типов (первые 3)
        if other_types:
            keyboard.append([InlineKeyboardButton("📢 Другие", callback_data="noop")])
            for ntype, display in other_types[:3]:
                type_prefs = preferences.type_preferences.get(ntype, {})
                if not isinstance(type_prefs, dict):
                    type_prefs = {}
                enabled = type_prefs.get('telegram', True)
                status = "✅" if enabled else "❌"
                keyboard.append([
                    InlineKeyboardButton(
                        f"{status} {display}",
                        callback_data=f"toggle_type_{ntype}"
                    )
                ])
        
        keyboard.append([
            InlineKeyboardButton("◀️ Назад к настройкам", callback_data="settings_back")
        ])
        
        reply_markup = InlineKeyboardMarkup(keyboard)
        await query.edit_message_text(message_text, parse_mode='HTML', reply_markup=reply_markup)
    
    async def _handle_timezone(self, query, db_user):
        """Обработка настройки часового пояса."""
        # Популярные часовые пояса
        popular_timezones = [
            ('Europe/Moscow', 'Москва (UTC+3)'),
            ('Europe/Kiev', 'Киев (UTC+2)'),
            ('Asia/Almaty', 'Алматы (UTC+6)'),
            ('Europe/Minsk', 'Минск (UTC+3)'),
            ('Asia/Tashkent', 'Ташкент (UTC+5)'),
            ('Asia/Yekaterinburg', 'Екатеринбург (UTC+5)'),
            ('Asia/Novosibirsk', 'Новосибирск (UTC+7)'),
            ('Europe/Kaliningrad', 'Калининград (UTC+2)'),
        ]
        
        message_text = "🕐 <b>Часовой пояс</b>\n\n"
        message_text += "Текущий: " + (db_user.timezone or 'Europe/Moscow') + "\n\n"
        message_text += "Выберите часовой пояс:"
        
        keyboard = []
        for tz, name in popular_timezones:
            keyboard.append([
                InlineKeyboardButton(
                    name + (" ✅" if db_user.timezone == tz else ""),
                    callback_data=f"set_timezone_{tz}"
                )
            ])
        
        keyboard.append([
            InlineKeyboardButton("◀️ Назад к настройкам", callback_data="settings_back")
        ])
        
        reply_markup = InlineKeyboardMarkup(keyboard)
        await query.edit_message_text(message_text, parse_mode='HTML', reply_markup=reply_markup)
    
    async def _handle_language(self, query, db_user):
        """Обработка настройки языка."""
        message_text = "🌐 <b>Язык интерфейса</b>\n\n"
        message_text += "Текущий: " + ('Русский' if db_user.language == 'ru' else 'English') + "\n\n"
        message_text += "Выберите язык:"
        
        keyboard = [
            [
                InlineKeyboardButton(
                    "Русский" + (" ✅" if db_user.language == 'ru' else ""),
                    callback_data="set_language_ru"
                ),
                InlineKeyboardButton(
                    "English" + (" ✅" if db_user.language == 'en' else ""),
                    callback_data="set_language_en"
                )
            ],
            [
                InlineKeyboardButton("◀️ Назад к настройкам", callback_data="settings_back")
            ]
        ]
        
        reply_markup = InlineKeyboardMarkup(keyboard)
        await query.edit_message_text(message_text, parse_mode='HTML', reply_markup=reply_markup)
    
    async def clients_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Обработчик команды /clients - список клиентов ментора."""
        user = update.effective_user
        telegram_id = user.id
        
        from apps.users.models import User, Client
        
        try:
            db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
            
            if not db_user:
                keyboard = get_main_keyboard(None)
                await update.message.reply_text(
                    "❌ Аккаунт не связан.\n\n"
                    "Используйте /link <код> для связывания аккаунта.",
                    reply_markup=keyboard
                )
                return
            
            if db_user.role != 'mentor':
                keyboard = await get_user_keyboard(telegram_id)
                await update.message.reply_text(
                    "❌ Эта команда доступна только для менторов.",
                    reply_markup=keyboard
                )
                return
            
            # Получаем клиентов ментора
            clients = await sync_to_async(list)(
                Client.objects.filter(mentors=db_user).select_related('user')[:10]
            )
            
            if not clients:
                keyboard = await get_user_keyboard(telegram_id)
                await update.message.reply_text(
                    "👥 У вас пока нет клиентов.\n\n"
                    "Клиенты появятся здесь после того, как они запишутся на ваши занятия.",
                    reply_markup=keyboard
                )
                return
            
            message = "👥 <b>Ваши клиенты:</b>\n\n"
            
            from apps.schedule.models import Lesson
            from apps.homework.models import HomeworkSubmission
            from django.utils import timezone
            
            inline_keyboard = []
            for client in clients:
                client_name = client.user.get_full_name() or client.user.email
                message += f"👤 <b>{client_name}</b>\n"
                
                # Статистика занятий
                lessons = await sync_to_async(list)(
                    Lesson.objects.filter(
                        mentor=db_user,
                        client=client
                    )
                )
                total_lessons = len(lessons)
                completed_lessons = len([l for l in lessons if l.status == 'completed'])
                upcoming_lessons = len([
                    l for l in lessons 
                    if l.start_time >= timezone.now() and l.status == 'scheduled'
                ])
                
                message += f"📚 Занятий: {total_lessons} (завершено: {completed_lessons}, предстоящих: {upcoming_lessons})\n"
                
                # Статистика ДЗ
                submissions = await sync_to_async(list)(
                    HomeworkSubmission.objects.filter(
                        homework__mentor=db_user,
                        student=client.user
                    )
                )
                total_homeworks = len(submissions)
                graded_homeworks = len([s for s in submissions if s.status == 'graded'])
                if graded_homeworks > 0:
                    scores = [s.score for s in submissions if s.score is not None]
                    avg_score = sum(scores) / len(scores) if scores else 0
                    message += f"📝 ДЗ: {total_homeworks} (проверено: {graded_homeworks}, средний балл: {avg_score:.1f})\n"
                else:
                    message += f"📝 ДЗ: {total_homeworks}\n"
                
                message += "\n"
                
                # Добавляем кнопку для просмотра деталей клиента
                inline_keyboard.append([
                    InlineKeyboardButton(
                        f"👤 {client_name[:30]}",
                        callback_data=f"client_detail_{client.id}"
                    )
                ])
            
            reply_markup = InlineKeyboardMarkup(inline_keyboard) if inline_keyboard else None
            keyboard = await get_user_keyboard(telegram_id)
            await update.message.reply_text(message, parse_mode='HTML', reply_markup=reply_markup)
        
        except Exception as e:
            logger.error(f"Error in clients_command: {e}", exc_info=True)
            keyboard = await get_user_keyboard(telegram_id)
            await update.message.reply_text(
                "❌ Ошибка получения списка клиентов.\n\n"
                "Попробуйте позже или обратитесь в поддержку.",
                reply_markup=keyboard
            )
    
    async def stats_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Обработчик команды /stats - статистика для ментора."""
        user = update.effective_user
        telegram_id = user.id
        
        from apps.users.models import User, Client
        
        try:
            db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
            
            if not db_user:
                keyboard = get_main_keyboard(None)
                await update.message.reply_text(
                    "❌ Аккаунт не связан.\n\n"
                    "Используйте /link <код> для связывания аккаунта.",
                    reply_markup=keyboard
                )
                return
            
            if db_user.role != 'mentor':
                keyboard = await get_user_keyboard(telegram_id)
                await update.message.reply_text(
                    "❌ Эта команда доступна только для менторов.",
                    reply_markup=keyboard
                )
                return
            
            from apps.schedule.models import Lesson
            from apps.homework.models import Homework, HomeworkSubmission
            from django.utils import timezone
            from datetime import timedelta
            
            now = timezone.now()
            month_ago = now - timedelta(days=30)
            
            # Общая статистика
            total_clients = await sync_to_async(Client.objects.filter(mentors=db_user).count)()
            
            # Занятия
            all_lessons = await sync_to_async(list)(
                Lesson.objects.filter(mentor=db_user)
            )
            total_lessons = len(all_lessons)
            completed_lessons = len([l for l in all_lessons if l.status == 'completed'])
            upcoming_lessons = len([
                l for l in all_lessons 
                if l.start_time >= now and l.status == 'scheduled'
            ])
            lessons_this_month = len([
                l for l in all_lessons 
                if l.start_time >= month_ago
            ])
            
            # Домашние задания
            all_submissions = await sync_to_async(list)(
                HomeworkSubmission.objects.filter(homework__mentor=db_user)
            )
            total_homeworks = len(all_submissions)
            pending_homeworks = len([s for s in all_submissions if s.status == 'pending'])
            graded_homeworks = len([s for s in all_submissions if s.status == 'graded'])
            
            if graded_homeworks > 0:
                scores = [s.score for s in all_submissions if s.score is not None]
                avg_score = sum(scores) / len(scores) if scores else 0
            else:
                avg_score = 0
            
            message = "📊 <b>Ваша статистика:</b>\n\n"
            message += f"👥 Клиентов: {total_clients}\n\n"
            message += f"📚 <b>Занятия:</b>\n"
            message += f"• Всего: {total_lessons}\n"
            message += f"• Завершено: {completed_lessons}\n"
            message += f"• Предстоящих: {upcoming_lessons}\n"
            message += f"• За месяц: {lessons_this_month}\n\n"
            message += f"📝 <b>Домашние задания:</b>\n"
            message += f"• Всего решений: {total_homeworks}\n"
            message += f"• На проверке: {pending_homeworks}\n"
            message += f"• Проверено: {graded_homeworks}\n"
            if avg_score > 0:
                message += f"• Средний балл: {avg_score:.1f}\n"
            
            # Доходы (если есть занятия с ценой)
            lessons_with_price = [l for l in all_lessons if l.price and l.status == 'completed']
            if lessons_with_price:
                total_revenue = sum([float(l.price) for l in lessons_with_price])
                avg_price = total_revenue / len(lessons_with_price) if lessons_with_price else 0
                revenue_this_month = sum([
                    float(l.price) for l in lessons_with_price 
                    if l.start_time >= month_ago
                ])
                
                message += f"\n💰 <b>Доходы:</b>\n"
                message += f"• Всего: {total_revenue:.2f} ₽\n"
                message += f"• Средняя цена: {avg_price:.2f} ₽\n"
                message += f"• За месяц: {revenue_this_month:.2f} ₽\n"
            
            keyboard = await get_user_keyboard(telegram_id)
            await update.message.reply_text(message, parse_mode='HTML', reply_markup=keyboard)
        
        except Exception as e:
            logger.error(f"Error in stats_command: {e}", exc_info=True)
            keyboard = await get_user_keyboard(telegram_id)
            await update.message.reply_text(
                "❌ Ошибка получения статистики.\n\n"
                "Попробуйте позже или обратитесь в поддержку.",
                reply_markup=keyboard
            )
    
    async def progress_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Мой прогресс: выбор предмета → период → средние оценки от репетитора и от школы."""
        user = update.effective_user
        telegram_id = user.id

        from apps.users.models import User

        try:
            db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()

            if not db_user:
                keyboard = get_main_keyboard(None)
                await update.message.reply_text(
                    "❌ Аккаунт не связан.\n\n"
                    "Используйте /link <код> для связывания аккаунта.",
                    reply_markup=keyboard
                )
                return

            if db_user.role != 'client':
                keyboard = await get_user_keyboard(telegram_id)
                await update.message.reply_text(
                    "❌ Эта команда доступна только для учеников.",
                    reply_markup=keyboard
                )
                return

            from apps.schedule.models import Lesson

            def _get_subject_names():
                lessons = Lesson.objects.filter(client__user=db_user).select_related('subject', 'mentor_subject')
                names = set()
                for lec in lessons:
                    name = lec.subject_name or (lec.subject.name if lec.subject else '') or (lec.mentor_subject.name if lec.mentor_subject else '') or 'Без предмета'
                    if name and name.strip():
                        names.add(name.strip())
                return sorted(names)

            subject_names = await sync_to_async(_get_subject_names)()

            if not subject_names:
                keyboard = await get_user_keyboard(telegram_id)
                await update.message.reply_text(
                    "📊 У вас пока нет занятий по предметам.\n"
                    "После проведённых занятий здесь можно будет посмотреть прогресс.",
                    reply_markup=keyboard
                )
                return

            context.user_data['progress_step'] = 'subject'
            context.user_data['progress_subjects'] = subject_names

            rows = [[KeyboardButton(name)] for name in subject_names]
            rows.append([KeyboardButton(PROGRESS_BACK_TO_MENU)])
            keyboard = ReplyKeyboardMarkup(rows, resize_keyboard=True, one_time_keyboard=False)

            await update.message.reply_text(
                "📊 <b>Мой прогресс</b>\n\n"
                "Выберите предмет, по которому проводились занятия:",
                parse_mode='HTML',
                reply_markup=keyboard
            )

        except Exception as e:
            logger.error(f"Error in progress_command: {e}", exc_info=True)
            keyboard = await get_user_keyboard(telegram_id)
            await update.message.reply_text(
                "❌ Ошибка. Попробуйте позже.",
                reply_markup=keyboard
            )

    async def _progress_send_result(
        self, update: Update, context: ContextTypes.DEFAULT_TYPE,
        db_user, subject_name: str, period: str
    ):
        """Посчитать и отправить прогресс по предмету за период (средняя от репетитора, от школы)."""
        from apps.schedule.models import Lesson
        from django.utils import timezone
        from datetime import timedelta

        now = timezone.now()
        if period == PROGRESS_PERIOD_WEEK:
            start = now - timedelta(days=7)
        elif period == PROGRESS_PERIOD_30:
            start = now - timedelta(days=30)
        else:
            start = None

        def _get_lessons_and_grades():
            qs = Lesson.objects.filter(client__user=db_user).select_related('subject', 'mentor_subject')
            if start:
                qs = qs.filter(start_time__gte=start)
            lessons = list(qs)
            mentor_grades = []
            school_grades = []
            count = 0
            target = (subject_name or '').strip()
            for lec in lessons:
                name = ((lec.subject_name or '') or (lec.subject.name if lec.subject else '') or (lec.mentor_subject.name if lec.mentor_subject else '') or 'Без предмета').strip()
                if name != target:
                    continue
                count += 1
                if lec.mentor_grade is not None:
                    mentor_grades.append(lec.mentor_grade)
                if lec.school_grade is not None:
                    school_grades.append(lec.school_grade)
            return count, mentor_grades, school_grades

        total_lessons, mentor_grades, school_grades = await sync_to_async(_get_lessons_and_grades)()

        avg_mentor = sum(mentor_grades) / len(mentor_grades) if mentor_grades else None
        avg_school = sum(school_grades) / len(school_grades) if school_grades else None

        period_label = "за текущую неделю" if period == PROGRESS_PERIOD_WEEK else "за последние 30 дней" if period == PROGRESS_PERIOD_30 else "за всё время"
        mentor_str = f"{avg_mentor:.1f}" if avg_mentor is not None else "—"
        school_str = f"{avg_school:.1f}" if avg_school is not None else "—"
        message = (
            f"📊 <b>Прогресс: {subject_name}</b>\n\n"
            f"Период: {period_label}\n"
            f"Занятий: {total_lessons}\n\n"
            f"📌 <b>Средняя оценка от репетитора:</b> {mentor_str}\n"
            f"📌 <b>Средняя оценка от школы:</b> {school_str}"
        )

        context.user_data.pop('progress_step', None)
        context.user_data.pop('progress_subjects', None)
        context.user_data.pop('progress_subject', None)
        keyboard = await get_user_keyboard(update.effective_user.id)
        await update.message.reply_text(message, parse_mode='HTML', reply_markup=keyboard)

    async def handle_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Обработчик обычных сообщений и кнопок."""
        user = update.effective_user
        telegram_id = user.id
        message_text = update.message.text
        
        from apps.users.models import User
        db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
        
        # Проверяем, ожидается ли ввод оценки или комментария для submission
        if db_user and db_user.role == 'mentor':
            submission_id = context.user_data.get('waiting_for_submission_score')
            if submission_id:
                # Если пользователь отправил текст "отмена", отменяем
                if message_text and message_text.lower() in ['отмена', 'cancel', '/cancel']:
                    context.user_data.pop('waiting_for_submission_score', None)
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text(
                        "❌ Выставление оценки отменено.",
                        reply_markup=keyboard
                    )
                    return
                else:
                    # Обрабатываем ввод оценки
                    await self._handle_submission_grade_input(update, context, db_user, submission_id, message_text)
                    return
            
            submission_id = context.user_data.get('waiting_for_submission_feedback')
            if submission_id:
                # Если пользователь отправил текст "отмена", отменяем
                if message_text and message_text.lower() in ['отмена', 'cancel', '/cancel']:
                    context.user_data.pop('waiting_for_submission_feedback', None)
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text(
                        "❌ Редактирование ответа отменено.",
                        reply_markup=keyboard
                    )
                    return
                else:
                    # Обрабатываем ввод комментария
                    await self._handle_submission_feedback_input(update, context, db_user, submission_id, message_text)
                    return
            
            submission_id = context.user_data.get('waiting_for_return_revision')
            if submission_id:
                if message_text and message_text.lower() in ['отмена', 'cancel', '/cancel']:
                    context.user_data.pop('waiting_for_return_revision', None)
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text("❌ Возврат на доработку отменён.", reply_markup=keyboard)
                    return
                else:
                    await self._handle_return_revision_input(update, context, db_user, submission_id, message_text or '')
                    return
        
        # Проверяем, ожидается ли загрузка решения для ДЗ
        if db_user:
            homework_id = context.user_data.get('waiting_for_homework_file')
            if homework_id:
                # Если пользователь отправил текст "отмена", отменяем загрузку
                if message_text and message_text.lower() in ['отмена', 'cancel', '/cancel']:
                    context.user_data.pop('waiting_for_homework_file', None)
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text(
                        "❌ Загрузка решения отменена.",
                        reply_markup=keyboard
                    )
                    return
                else:
                    # Обрабатываем текстовое решение
                    await self._handle_text_homework_submission(update, context, db_user, homework_id, message_text)
                    return
        
        # Список заданий в панели: нажатие на задание или «Назад в меню»
        if db_user and db_user.role == 'client':
            # Обработка кнопок управления конкретным ДЗ
            if message_text == "🏠 В главное меню":
                context.user_data.pop('homework_list_active', None)
                context.user_data.pop('homework_buttons', None)
                context.user_data.pop('current_homework_id', None)
                keyboard = await get_user_keyboard(telegram_id)
                await update.message.reply_text("Возврат в главное меню.", reply_markup=keyboard)
                return
            
            if message_text == "◀️ Назад к списку":
                # Возврат к списку заданий
                from apps.homework.models import Homework
                
                def get_homeworks():
                    return list(Homework.objects.filter(
                        assigned_to=db_user,
                        deadline__gte=timezone.now()
                    ).order_by('deadline')[:5])
                
                homeworks = await sync_to_async(get_homeworks)()
                if homeworks:
                    homework_keyboard, homework_buttons = make_homework_list_keyboard(homeworks)
                    context.user_data['homework_buttons'] = homework_buttons
                    context.user_data['homework_list_active'] = True
                    context.user_data.pop('current_homework_id', None)
                    await update.message.reply_text(
                        "📝 <b>Домашние задания</b>\n\nВыберите задание кнопкой в панели ниже:",
                        parse_mode='HTML',
                        reply_markup=homework_keyboard
                    )
                else:
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text("📝 У вас нет активных домашних заданий.", reply_markup=keyboard)
                return
            
            if message_text == "📎 Загрузить решение":
                homework_id = context.user_data.get('current_homework_id')
                if homework_id:
                    context.user_data['waiting_for_homework_file'] = homework_id
                    await update.message.reply_text(
                        "📎 <b>Загрузка решения</b>\n\n"
                        "Отправьте файл с решением (документ, фото) или текстовое решение.\n\n"
                        "Или отправьте 'отмена' для отмены.",
                        parse_mode='HTML'
                    )
                return
            
            if message_text == "👁️ Просмотреть решение":
                homework_id = context.user_data.get('current_homework_id')
                if homework_id:
                    from apps.homework.models import HomeworkSubmission
                    # select_related чтобы не было lazy load в async и комментарии точно подгружены
                    submission = await sync_to_async(
                        lambda: HomeworkSubmission.objects.select_related('homework').filter(
                            homework_id=homework_id, student=db_user
                        ).first()
                    )()
                    if submission:
                        await self._show_submission_view(update, context, submission, db_user)
                return
            
            # Обработка выбора задания из списка
            if context.user_data.get('homework_list_active'):
                homework_buttons = context.user_data.get('homework_buttons') or {}
                if message_text == HOMEWORK_LIST_BACK_BUTTON:
                    context.user_data.pop('homework_list_active', None)
                    context.user_data.pop('homework_buttons', None)
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text("Возврат в главное меню.", reply_markup=keyboard)
                    return
                if message_text in homework_buttons:
                    homework_id = homework_buttons[message_text]
                    context.user_data['current_homework_id'] = homework_id
                    msg, reply_markup = await self._get_client_homework_detail(homework_id, db_user)
                    if msg and reply_markup:
                        await update.message.reply_text(msg, parse_mode='HTML', reply_markup=reply_markup)
                    else:
                        await update.message.reply_text("❌ Задание не найдено или у вас нет доступа.")
                    return
        
        # Мой прогресс: выбор предмета → период → результат
        if db_user and db_user.role == 'client':
            progress_step = context.user_data.get('progress_step')
            if progress_step == 'subject':
                if message_text == PROGRESS_BACK_TO_MENU:
                    context.user_data.pop('progress_step', None)
                    context.user_data.pop('progress_subjects', None)
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text("Возврат в меню.", reply_markup=keyboard)
                    return
                subjects = context.user_data.get('progress_subjects') or []
                if message_text in subjects:
                    context.user_data['progress_subject'] = message_text
                    context.user_data['progress_step'] = 'period'
                    period_keyboard = ReplyKeyboardMarkup(
                        [
                            [KeyboardButton(PROGRESS_PERIOD_WEEK)],
                            [KeyboardButton(PROGRESS_PERIOD_30)],
                            [KeyboardButton(PROGRESS_PERIOD_ALL)],
                            [KeyboardButton(PROGRESS_BACK_SUBJECT), KeyboardButton(PROGRESS_BACK_TO_MENU)],
                        ],
                        resize_keyboard=True,
                        one_time_keyboard=False,
                    )
                    await update.message.reply_text(
                        f"📊 Предмет: <b>{message_text}</b>\n\nВыберите период:",
                        parse_mode='HTML',
                        reply_markup=period_keyboard
                    )
                    return
            elif progress_step == 'period':
                if message_text == PROGRESS_BACK_TO_MENU:
                    context.user_data.pop('progress_step', None)
                    context.user_data.pop('progress_subjects', None)
                    context.user_data.pop('progress_subject', None)
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text("Возврат в меню.", reply_markup=keyboard)
                    return
                if message_text == PROGRESS_BACK_SUBJECT:
                    from apps.schedule.models import Lesson
                    def _get_subject_names():
                        lessons = Lesson.objects.filter(client__user=db_user).select_related('subject', 'mentor_subject')
                        names = set()
                        for lec in lessons:
                            name = lec.subject_name or (lec.subject.name if lec.subject else '') or (lec.mentor_subject.name if lec.mentor_subject else '') or 'Без предмета'
                            if name and name.strip():
                                names.add(name.strip())
                        return sorted(names)
                    subject_names = await sync_to_async(_get_subject_names)()
                    context.user_data['progress_step'] = 'subject'
                    context.user_data['progress_subjects'] = subject_names
                    context.user_data.pop('progress_subject', None)
                    rows = [[KeyboardButton(n)] for n in subject_names]
                    rows.append([KeyboardButton(PROGRESS_BACK_TO_MENU)])
                    keyboard = ReplyKeyboardMarkup(rows, resize_keyboard=True, one_time_keyboard=False)
                    await update.message.reply_text(
                        "📊 Выберите предмет:",
                        parse_mode='HTML',
                        reply_markup=keyboard
                    )
                    return
                if message_text in (PROGRESS_PERIOD_WEEK, PROGRESS_PERIOD_30, PROGRESS_PERIOD_ALL):
                    subject_name = context.user_data.get('progress_subject', '')
                    await self._progress_send_result(update, context, db_user, subject_name, message_text)
                    return

        # Обработка нажатий на кнопки
        if message_text == "📅 Расписание" or message_text == "📅 Моё расписание" or message_text == "📅 Расписание детей":
            await self.schedule_command(update, context)
        elif message_text == "📚 Следующее занятие":
            await self.nextlesson_command(update, context)
        elif message_text == "📝 Домашние задания" or message_text == "📝 Мои задания" or message_text == "📝 Задания детей":
            await self.homework_command(update, context)
        elif message_text == "📊 Мой прогресс":
            await self.progress_command(update, context)
        elif message_text == "👥 Клиенты":
            await self.clients_command(update, context)
        elif message_text == "📊 Статистика":
            await self.stats_command(update, context)
        elif message_text == "⚙️ Настройки":
            await self.settings_command(update, context)
        elif message_text == "ℹ️ Статус":
            await self.status_command(update, context)
        elif message_text == "❓ Помощь":
            await self.help_command(update, context)
        elif message_text == "🔗 Связать аккаунт":
            await update.message.reply_text(
                "🔗 <b>Связывание аккаунта</b>\n\n"
                "1. Войдите на платформу\n"
                "2. Перейдите в Профиль → Настройки → Telegram\n"
                "3. Нажмите \"Связать Telegram\"\n"
                "4. Отправьте команду: /link ВАШ_КОД\n\n"
                "Или используйте команду:\n"
                "/link &lt;ваш_код_связывания&gt;",
                parse_mode='HTML'
            )
        else:
            # Если аккаунт связан, показываем клавиатуру
            if db_user:
                keyboard = get_main_keyboard(db_user.role)
                await update.message.reply_text(
                    "Используйте кнопки или команды для работы с ботом.\n\n"
                    "Введите /help для списка команд.",
                    reply_markup=keyboard
                )
            else:
                keyboard = get_main_keyboard(None)
                await update.message.reply_text(
                    "Используйте кнопки или команды для работы с ботом.\n\n"
                    "Введите /help для списка команд.",
                    reply_markup=keyboard
                )
    
    async def handle_document(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Обработчик загрузки документов (для решений ДЗ)."""
        user = update.effective_user
        telegram_id = user.id
        
        from apps.users.models import User
        db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
        
        if not db_user:
            await update.message.reply_text(
                "❌ Аккаунт не связан.\n\n"
                "Используйте /link <код> для связывания аккаунта."
            )
            return
        
        # Проверяем, ожидается ли загрузка файла для ДЗ
        homework_id = context.user_data.get('waiting_for_homework_file')
        if not homework_id:
            await update.message.reply_text(
                "📎 Чтобы загрузить файл для решения ДЗ:\n\n"
                "1. Используйте команду /homework\n"
                "2. Выберите задание\n"
                "3. Нажмите кнопку '📎 Загрузить решение'"
            )
            return
        
        # Получаем файл
        document = update.message.document
        if not document:
            await update.message.reply_text("❌ Файл не найден.")
            return
        
        try:
            # Скачиваем файл из Telegram
            from telegram import Bot
            bot = Bot(token=settings.TELEGRAM_BOT_TOKEN)
            file = await bot.get_file(document.file_id)
            
            # Получаем домашнее задание для проверок
            from apps.homework.models import Homework, HomeworkSubmission
            homework = await sync_to_async(Homework.objects.get)(id=homework_id)
            
            # Безопасность: Проверка размера файла (максимум 50MB для Telegram, но проверяем и настройки задания)
            MAX_TELEGRAM_FILE_SIZE = 50 * 1024 * 1024  # 50 MB - максимум для Telegram
            file_size = document.file_size or 0
            
            if file_size > MAX_TELEGRAM_FILE_SIZE:
                await update.message.reply_text(
                    f"❌ Файл слишком большой. Максимальный размер: {MAX_TELEGRAM_FILE_SIZE / (1024*1024):.0f} MB"
                )
                await bot.close()
                return
            
            # Проверяем размер файла согласно настройкам задания
            if homework.max_file_size > 0 and file_size > homework.max_file_size:
                max_size_mb = homework.max_file_size / (1024 * 1024)
                await update.message.reply_text(
                    f"❌ Файл слишком большой. Максимальный размер для этого задания: {max_size_mb:.1f} MB"
                )
                await bot.close()
                return
            
            # Безопасность: Проверка типа файла
            from apps.homework.utils import validate_file_type, sanitize_filename
            safe_filename = sanitize_filename(document.file_name or 'file')
            
            if homework.allowed_file_types and not validate_file_type(safe_filename, homework.allowed_file_types):
                allowed = homework.allowed_file_types.replace(',', ', ')
                await update.message.reply_text(
                    f"❌ Тип файла не разрешен.\n\n"
                    f"Разрешенные типы: {allowed}"
                )
                await bot.close()
                return
            
            # Создаем временный файл
            import tempfile
            import os
            from django.core.files import File
            
            file_ext = os.path.splitext(safe_filename)[1]
            tmp_file_path = None
            try:
                with tempfile.NamedTemporaryFile(delete=False, suffix=file_ext) as tmp_file:
                    tmp_file_path = tmp_file.name
                    await file.download_to_drive(tmp_file_path)
                    
                    # Проверяем, что пользователь имеет право сдавать это ДЗ
                    if db_user.role != 'client' or db_user not in await sync_to_async(list)(homework.assigned_to.all()):
                        await update.message.reply_text(
                            "❌ У вас нет доступа к этому заданию."
                        )
                        await bot.close()
                        return
                
                    # Проверяем, есть ли уже решение
                    existing_submission = await sync_to_async(
                        HomeworkSubmission.objects.filter(
                            homework=homework,
                            student=db_user
                        ).order_by('-attempt_number').first
                    )()
                    
                    if existing_submission and existing_submission.status != 'returned':
                        # Обновляем существующее решение
                        with open(tmp_file_path, 'rb') as f:
                            django_file = File(f, name=safe_filename)
                            existing_submission.attachment = django_file
                            existing_submission.content = f"Решение загружено через Telegram: {safe_filename}"
                            existing_submission.status = 'pending'
                            await sync_to_async(existing_submission.save)()
                        
                        await update.message.reply_text(
                            f"✅ <b>Решение обновлено!</b>\n\n"
                            f"📎 Файл: {safe_filename}\n"
                            f"📝 Задание: {homework.title}\n\n"
                            f"Решение отправлено на проверку.",
                            parse_mode='HTML'
                        )
                    else:
                        # Определяем номер попытки
                        attempt_number = 1
                        if existing_submission:
                            attempt_number = existing_submission.attempt_number + 1
                        
                        # Создаем новое решение
                        with open(tmp_file_path, 'rb') as f:
                            django_file = File(f, name=safe_filename)
                            submission = HomeworkSubmission(
                                homework=homework,
                                student=db_user,
                                content=f"Решение загружено через Telegram: {safe_filename}",
                                attachment=django_file,
                                status='pending',
                                attempt_number=attempt_number
                            )
                            await sync_to_async(submission.save)()
                        
                        # Проверяем опоздание
                        await sync_to_async(submission.check_if_late)()
                        
                        # Обновляем статистику задания
                        await sync_to_async(homework.update_statistics)()
                        
                        await update.message.reply_text(
                            f"✅ <b>Решение загружено!</b>\n\n"
                            f"📎 Файл: {safe_filename}\n"
                            f"📝 Задание: {homework.title}\n\n"
                            f"Решение отправлено на проверку.",
                            parse_mode='HTML'
                        )
                    
                    # Отправляем уведомление ментору
                    from apps.notifications.services import NotificationService
                    await sync_to_async(NotificationService.create_notification_with_telegram)(
                        recipient=homework.mentor,
                        notification_type='homework_submitted',
                        title='📝 ДЗ сдано',
                        message=f'{db_user.get_full_name()} сдал ДЗ "{homework.title}"',
                        priority='normal',
                        action_url=f'/homework/{homework.id}/',
                        content_object=homework
                    )
                    
                    # Очищаем состояние ожидания
                    context.user_data.pop('waiting_for_homework_file', None)
                    
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text(
                        "Используйте кнопки для навигации:",
                        reply_markup=keyboard
                    )
            finally:
                # Гарантированно удаляем временный файл
                if tmp_file_path and os.path.exists(tmp_file_path):
                    try:
                        os.unlink(tmp_file_path)
                    except Exception as e:
                        logger.error(f"Error deleting temp file {tmp_file_path}: {e}")
                
                await bot.close()
            
        except Homework.DoesNotExist:
            await update.message.reply_text(
                "❌ Домашнее задание не найдено."
            )
            context.user_data.pop('waiting_for_homework_file', None)
        except Exception as e:
            logger.error(f"Error handling document upload: {e}", exc_info=True)
            await update.message.reply_text(
                "❌ Ошибка загрузки файла.\n\n"
                "Попробуйте позже или обратитесь в поддержку."
            )
            context.user_data.pop('waiting_for_homework_file', None)
    
    async def handle_photo(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Обработчик загрузки фото (для решений ДЗ)."""
        user = update.effective_user
        telegram_id = user.id
        
        from apps.users.models import User
        db_user = await sync_to_async(User.objects.filter(telegram_id=telegram_id).first)()
        
        if not db_user:
            await update.message.reply_text(
                "❌ Аккаунт не связан.\n\n"
                "Используйте /link <код> для связывания аккаунта."
            )
            return
        
        # Проверяем, ожидается ли загрузка файла для ДЗ
        homework_id = context.user_data.get('waiting_for_homework_file')
        if not homework_id:
            await update.message.reply_text(
                "📎 Чтобы загрузить фото для решения ДЗ:\n\n"
                "1. Используйте команду /homework\n"
                "2. Выберите задание\n"
                "3. Нажмите кнопку '📎 Загрузить решение'"
            )
            return
        
        # Получаем фото (берем самое большое)
        photos = update.message.photo
        if not photos:
            await update.message.reply_text("❌ Фото не найдено.")
            return
        
        photo = photos[-1]  # Самое большое фото
        
        try:
            # Скачиваем фото из Telegram
            from telegram import Bot
            bot = Bot(token=settings.TELEGRAM_BOT_TOKEN)
            file = await bot.get_file(photo.file_id)
            
            # Получаем домашнее задание для проверок
            from apps.homework.models import Homework, HomeworkSubmission
            homework = await sync_to_async(Homework.objects.get)(id=homework_id)
            
            # Безопасность: Проверка размера файла (максимум 50MB для Telegram)
            MAX_TELEGRAM_FILE_SIZE = 50 * 1024 * 1024  # 50 MB - максимум для Telegram
            file_size = photo.file_size or 0
            
            if file_size > MAX_TELEGRAM_FILE_SIZE:
                await update.message.reply_text(
                    f"❌ Фото слишком большое. Максимальный размер: {MAX_TELEGRAM_FILE_SIZE / (1024*1024):.0f} MB"
                )
                await bot.close()
                return
            
            # Проверяем размер файла согласно настройкам задания
            if homework.max_file_size > 0 and file_size > homework.max_file_size:
                max_size_mb = homework.max_file_size / (1024 * 1024)
                await update.message.reply_text(
                    f"❌ Фото слишком большое. Максимальный размер для этого задания: {max_size_mb:.1f} MB"
                )
                await bot.close()
                return
            
            # Безопасность: Проверка типа файла (фото должно быть разрешено)
            from apps.homework.utils import validate_file_type, sanitize_filename
            if homework.allowed_file_types and not validate_file_type('photo.jpg', homework.allowed_file_types):
                allowed = homework.allowed_file_types.replace(',', ', ')
                await update.message.reply_text(
                    f"❌ Фото не разрешено для этого задания.\n\n"
                    f"Разрешенные типы: {allowed}"
                )
                await bot.close()
                return
            
            # Создаем временный файл
            import tempfile
            import os
            from django.core.files import File
            
            tmp_file_path = None
            try:
                with tempfile.NamedTemporaryFile(delete=False, suffix='.jpg') as tmp_file:
                    tmp_file_path = tmp_file.name
                    await file.download_to_drive(tmp_file_path)
                    
                    # Проверяем, что пользователь имеет право сдавать это ДЗ
                    if db_user.role != 'client' or db_user not in await sync_to_async(list)(homework.assigned_to.all()):
                        await update.message.reply_text(
                            "❌ У вас нет доступа к этому заданию."
                        )
                        await bot.close()
                        return
                    
                    from django.utils import timezone as tz
                    from apps.homework.utils import sanitize_filename
                    filename = sanitize_filename(f"photo_{homework.id}_{tz.now().strftime('%Y%m%d_%H%M%S')}.jpg")
                    
                    # Проверяем, есть ли уже решение
                    existing_submission = await sync_to_async(
                        HomeworkSubmission.objects.filter(
                            homework=homework,
                            student=db_user
                        ).order_by('-attempt_number').first
                    )()
                    
                    if existing_submission and existing_submission.status != 'returned':
                        # Обновляем существующее решение
                        with open(tmp_file_path, 'rb') as f:
                            django_file = File(f, name=filename)
                            existing_submission.attachment = django_file
                            existing_submission.content = f"Решение загружено через Telegram (фото)"
                            existing_submission.status = 'pending'
                            await sync_to_async(existing_submission.save)()
                        
                        await update.message.reply_text(
                            f"✅ <b>Решение обновлено!</b>\n\n"
                            f"📎 Фото загружено\n"
                            f"📝 Задание: {homework.title}\n\n"
                            f"Решение отправлено на проверку.",
                            parse_mode='HTML'
                        )
                    else:
                        # Определяем номер попытки
                        attempt_number = 1
                        if existing_submission:
                            attempt_number = existing_submission.attempt_number + 1
                        
                        # Создаем новое решение
                        with open(tmp_file_path, 'rb') as f:
                            django_file = File(f, name=filename)
                            submission = HomeworkSubmission(
                                homework=homework,
                                student=db_user,
                                content="Решение загружено через Telegram (фото)",
                                attachment=django_file,
                                status='pending',
                                attempt_number=attempt_number
                            )
                            await sync_to_async(submission.save)()
                        
                        # Проверяем опоздание
                        await sync_to_async(submission.check_if_late)()
                        
                        # Обновляем статистику задания
                        await sync_to_async(homework.update_statistics)()
                        
                        await update.message.reply_text(
                            f"✅ <b>Решение загружено!</b>\n\n"
                            f"📎 Фото загружено\n"
                            f"📝 Задание: {homework.title}\n\n"
                            f"Решение отправлено на проверку.",
                            parse_mode='HTML'
                        )
                    
                    # Отправляем уведомление ментору
                    from apps.notifications.services import NotificationService
                    await sync_to_async(NotificationService.create_notification_with_telegram)(
                        recipient=homework.mentor,
                        notification_type='homework_submitted',
                        title='📝 ДЗ сдано',
                        message=f'{db_user.get_full_name()} сдал ДЗ "{homework.title}"',
                        priority='normal',
                        action_url=f'/homework/{homework.id}/',
                        content_object=homework
                    )
                    
                    # Очищаем состояние ожидания
                    context.user_data.pop('waiting_for_homework_file', None)
                    
                    keyboard = await get_user_keyboard(telegram_id)
                    await update.message.reply_text(
                        "Используйте кнопки для навигации:",
                        reply_markup=keyboard
                    )
            finally:
                # Гарантированно удаляем временный файл
                if tmp_file_path and os.path.exists(tmp_file_path):
                    try:
                        os.unlink(tmp_file_path)
                    except Exception as e:
                        logger.error(f"Error deleting temp file {tmp_file_path}: {e}")
                
                await bot.close()
            
        except Homework.DoesNotExist:
            await update.message.reply_text(
                "❌ Домашнее задание не найдено."
            )
            context.user_data.pop('waiting_for_homework_file', None)
        except Exception as e:
            logger.error(f"Error handling photo upload: {e}", exc_info=True)
            await update.message.reply_text(
                "❌ Ошибка загрузки фото.\n\n"
                "Попробуйте позже или обратитесь в поддержку."
            )
            context.user_data.pop('waiting_for_homework_file', None)
    
    def setup_handlers(self):
        """Настройка обработчиков команд."""
        if not self.application:
            return
        
        # Команды
        self.application.add_handler(CommandHandler("start", self.start_command))
        self.application.add_handler(CommandHandler("help", self.help_command))
        self.application.add_handler(CommandHandler("link", self.link_command))
        self.application.add_handler(CommandHandler("unlink", self.unlink_command))
        self.application.add_handler(CommandHandler("status", self.status_command))
        self.application.add_handler(CommandHandler("settings", self.settings_command))
        
        # Команды для клиентов и менторов
        self.application.add_handler(CommandHandler("schedule", self.schedule_command))
        self.application.add_handler(CommandHandler("nextlesson", self.nextlesson_command))
        self.application.add_handler(CommandHandler("homework", self.homework_command))
        
        # Команды для клиентов
        self.application.add_handler(CommandHandler("progress", self.progress_command))
        
        # Команды для менторов
        self.application.add_handler(CommandHandler("clients", self.clients_command))
        self.application.add_handler(CommandHandler("stats", self.stats_command))
        
        # Кнопки
        self.application.add_handler(CallbackQueryHandler(self.button_callback))
        
        # Обычные сообщения
        self.application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, self.handle_message))
        
        # Загрузка документов (для решений ДЗ)
        self.application.add_handler(MessageHandler(filters.Document.ALL, self.handle_document))
        
        # Загрузка фото (для решений ДЗ)
        self.application.add_handler(MessageHandler(filters.PHOTO, self.handle_photo))
    
    async def start(self):
        """Запуск бота."""
        if not self.token:
            logger.error("TELEGRAM_BOT_TOKEN not set")
            return
        
        logger.info("Starting Telegram bot...")
        
        # Создаем приложение
        self.application = Application.builder().token(self.token).build()
        
        # Настраиваем обработчики
        self.setup_handlers()
        
        # Запускаем бота
        await self.application.initialize()
        await self.application.start()
        
        if self.use_webhook and self.webhook_url:
            # Используем webhook режим
            logger.info(f"Setting up webhook: {self.webhook_url}")
            await self.setup_webhook()
        else:
            # Используем polling режим
            logger.info("Starting bot in polling mode...")
            await self.application.updater.start_polling()
        
        logger.info("Telegram bot started successfully")
    
    async def setup_webhook(self):
        """Настройка webhook для бота."""
        from telegram import Bot
        from telegram.error import TelegramError
        
        try:
            bot = Bot(token=self.token)
            
            # Устанавливаем webhook
            webhook_kwargs = {
                'url': self.webhook_url,
                'allowed_updates': ['message', 'callback_query', 'inline_query', 'chosen_inline_result'],
            }
            
            # Добавляем secret token если указан
            if self.webhook_secret_token:
                webhook_kwargs['secret_token'] = self.webhook_secret_token
            
            await bot.set_webhook(**webhook_kwargs)
            
            # Проверяем информацию о webhook
            webhook_info = await bot.get_webhook_info()
            logger.info(f"Webhook info: {webhook_info.url}, pending updates: {webhook_info.pending_update_count}")
            
            await bot.close()
            logger.info("Webhook set successfully")
        except TelegramError as e:
            logger.error(f"Error setting webhook: {e}")
            raise
        except Exception as e:
            logger.error(f"Unexpected error setting webhook: {e}")
            raise
    
    async def remove_webhook(self):
        """Удаление webhook."""
        from telegram import Bot
        from telegram.error import TelegramError
        
        try:
            bot = Bot(token=self.token)
            await bot.delete_webhook(drop_pending_updates=True)
            await bot.close()
            logger.info("Webhook removed successfully")
        except TelegramError as e:
            logger.error(f"Error removing webhook: {e}")
            raise
        except Exception as e:
            logger.error(f"Unexpected error removing webhook: {e}")
            raise
    
    async def stop(self):
        """Остановка бота."""
        if self.application:
            logger.info("Stopping Telegram bot...")
            if not self.use_webhook:
                # Останавливаем polling только если не используем webhook
                await self.application.updater.stop()
            await self.application.stop()
            await self.application.shutdown()
            logger.info("Telegram bot stopped")
    
    def get_application(self):
        """
        Получить экземпляр Application для обработки webhook.
        
        ВАЖНО: Этот метод создает приложение, но не инициализирует его.
        Инициализация происходит в process_webhook_update при первом запросе.
        """
        if not self.application:
            if not self.token:
                logger.error("TELEGRAM_BOT_TOKEN not set")
                return None
            
            # Создаем приложение
            self.application = Application.builder().token(self.token).build()
            
            # Настраиваем обработчики
            self.setup_handlers()
            
            logger.info("Bot application created for webhook")
        
        return self.application
    
    async def process_webhook_update(self, update: Update):
        """
        Обработать update от webhook.
        
        Args:
            update: Update объект от Telegram
        """
        # Получаем или создаем приложение
        if not self.application:
            self.get_application()
        
        if not self.application:
            logger.error("Failed to initialize bot application")
            return False
        
        try:
            # Убеждаемся что приложение инициализировано и запущено
            # Для webhook режима мы не используем updater, только application
            if not hasattr(self.application, '_webhook_initialized'):
                await self.application.initialize()
                await self.application.start()
                self.application._webhook_initialized = True
                logger.info("Bot application initialized for webhook")
            
            # Обрабатываем update
            await self.application.process_update(update)
            return True
        except Exception as e:
            logger.error(f"Error processing webhook update: {e}", exc_info=True)
            return False


# Глобальный экземпляр бота
bot_instance = None


async def get_bot():
    """Получить экземпляр бота."""
    global bot_instance
    
    if bot_instance is None:
        bot_instance = TelegramBot()
        await bot_instance.start()
    
    return bot_instance


async def send_telegram_message(telegram_id: int, message: str, parse_mode: str = 'HTML'):
    """
    Отправить сообщение в Telegram.
    
    Args:
        telegram_id: ID пользователя в Telegram
        message: Текст сообщения
        parse_mode: Режим парсинга (HTML, Markdown)
    """
    from telegram import Bot
    from telegram.error import TelegramError
    
    if not settings.TELEGRAM_BOT_TOKEN:
        logger.error("TELEGRAM_BOT_TOKEN not set")
        return False
    
    try:
        # Создаем временный экземпляр бота для отправки сообщения
        bot = Bot(token=settings.TELEGRAM_BOT_TOKEN)
        await bot.send_message(
            chat_id=telegram_id,
            text=message,
            parse_mode=parse_mode
        )
        await bot.close()
        logger.info(f"Telegram message sent to {telegram_id}")
        return True
    except TelegramError as e:
        logger.error(f"Telegram API error sending message to {telegram_id}: {e}")
        return False
    except Exception as e:
        logger.error(f"Error sending Telegram message to {telegram_id}: {e}")
        return False


async def send_telegram_message_with_buttons(telegram_id: int, message: str, reply_markup, parse_mode: str = 'HTML'):
    """
    Отправить сообщение в Telegram с кнопками.
    
    Args:
        telegram_id: ID пользователя в Telegram
        message: Текст сообщения
        reply_markup: InlineKeyboardMarkup с кнопками
        parse_mode: Режим парсинга (HTML, Markdown)
    """
    from telegram import Bot
    from telegram.error import TelegramError
    
    if not settings.TELEGRAM_BOT_TOKEN:
        logger.error("TELEGRAM_BOT_TOKEN not set")
        return False
    
    try:
        bot = Bot(token=settings.TELEGRAM_BOT_TOKEN)
        await bot.send_message(
            chat_id=telegram_id,
            text=message,
            parse_mode=parse_mode,
            reply_markup=reply_markup
        )
        await bot.close()
        logger.info(f"Telegram message with buttons sent to {telegram_id}")
        return True
    except TelegramError as e:
        logger.error(f"Telegram API error sending message with buttons to {telegram_id}: {e}")
        return False
    except Exception as e:
        logger.error(f"Error sending Telegram message with buttons to {telegram_id}: {e}")
        return False

