#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Агент файлового менеджера для Synology Power Control Bot.
Предоставляет расширенный интерфейс для работы с файловой системой Synology NAS.
"""

import os
import time
import logging
import html
from typing import Dict, List, Any, Optional, Union, Tuple

from telegram import (
    Update, 
    InlineKeyboardButton, 
    InlineKeyboardMarkup, 
    InputFile
)
from telegram.constants import ParseMode
from telegram.ext import (
    ContextTypes,
    ConversationHandler,
    CallbackQueryHandler,
    CommandHandler,
    MessageHandler,
    filters
)

from src.api.synology import SynologyAPI
from src.utils.admin_utils import admin_required

# Настройка логирования
logger = logging.getLogger(__name__)

# Состояния для ConversationHandler
BROWSING, UPLOADING, RENAMING, DELETING, CREATING_FOLDER = range(5)

# Константы для максимального количества элементов на странице
MAX_ITEMS_PER_PAGE = 10

class FileManagerAgent:
    """Агент файлового менеджера для взаимодействия с файловой системой NAS."""
    
    def __init__(self, synology_api: SynologyAPI):
        """Инициализация агента файлового менеджера."""
        self.synology_api = synology_api
        self.user_data = {}  # Хранилище для пользовательских данных (текущий путь и т.д.)
        
        # Создаем обработчики для регистрации в боте
        self.handlers = [
            CommandHandler("files", self.start_file_manager),
            CallbackQueryHandler(self.browse_callback, pattern="^fm:browse:"),
            CallbackQueryHandler(self.download_callback, pattern="^fm:download:"),
            CallbackQueryHandler(self.upload_callback, pattern="^fm:upload:"),
            CallbackQueryHandler(self.delete_callback, pattern="^fm:delete:"),
            CallbackQueryHandler(self.rename_callback, pattern="^fm:rename:"),
            CallbackQueryHandler(self.create_folder_callback, pattern="^fm:mkdir:"),
            CallbackQueryHandler(self.navigation_callback, pattern="^fm:nav:"),
            MessageHandler(filters.ATTACHMENT & ~filters.COMMAND, self.handle_file_upload),
        ]
    
    def get_user_path(self, user_id: int) -> str:
        """Получает текущий путь для пользователя."""
        return self.user_data.get(user_id, {}).get('current_path', '/')
    
    def set_user_path(self, user_id: int, path: str) -> None:
        """Устанавливает текущий путь для пользователя."""
        if user_id not in self.user_data:
            self.user_data[user_id] = {}
        self.user_data[user_id]['current_path'] = path
    
    def get_user_pagination(self, user_id: int) -> dict:
        """Получает информацию о пагинации для пользователя."""
        return self.user_data.get(user_id, {}).get('pagination', {'page': 0, 'total_pages': 1})
    
    def set_user_pagination(self, user_id: int, page: int, total_pages: int) -> None:
        """Устанавливает информацию о пагинации для пользователя."""
        if user_id not in self.user_data:
            self.user_data[user_id] = {}
        if 'pagination' not in self.user_data[user_id]:
            self.user_data[user_id]['pagination'] = {}
        self.user_data[user_id]['pagination']['page'] = page
        self.user_data[user_id]['pagination']['total_pages'] = total_pages
    
    @admin_required
    async def start_file_manager(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
        """Запускает файловый менеджер."""
        user_id = update.effective_user.id
        
        # Устанавливаем начальный путь
        initial_path = '/'
        if context.args and context.args[0]:
            initial_path = context.args[0]
        self.set_user_path(user_id, initial_path)
        
        # Отображаем содержимое начального пути
        await self.display_directory_content(update, context)
        return BROWSING
    
    async def display_directory_content(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
        """Отображает содержимое директории."""
        user_id = update.effective_user.id
        current_path = self.get_user_path(user_id)
        pagination = self.get_user_pagination(user_id)
        current_page = pagination['page']
        
        # Получаем список файлов и папок
        files_and_folders = self.synology_api.list_files(current_path)
        
        if not files_and_folders:
            await self.send_or_edit_message(
                update,
                f"📁 <b>Путь:</b> <code>{html.escape(current_path)}</code>\n\n"
                f"📭 <i>Папка пуста или недоступна</i>",
                self.get_empty_folder_keyboard(current_path)
            )
            return
        
        # Разделяем на папки и файлы, сортируем по имени
        folders = sorted([item for item in files_and_folders if item.get('isdir', False)], 
                          key=lambda x: x.get('name', '').lower())
        files = sorted([item for item in files_and_folders if not item.get('isdir', False)], 
                        key=lambda x: x.get('name', '').lower())
        
        # Подготавливаем информацию для пагинации
        all_items = folders + files
        total_items = len(all_items)
        total_pages = max(1, (total_items + MAX_ITEMS_PER_PAGE - 1) // MAX_ITEMS_PER_PAGE)
        
        # Корректируем текущую страницу, если она некорректна
        if current_page >= total_pages:
            current_page = 0
        elif current_page < 0:
            current_page = total_pages - 1
        
        # Обновляем информацию о пагинации
        self.set_user_pagination(user_id, current_page, total_pages)
        
        # Определяем диапазон элементов для текущей страницы
        start_idx = current_page * MAX_ITEMS_PER_PAGE
        end_idx = min(start_idx + MAX_ITEMS_PER_PAGE, total_items)
        current_items = all_items[start_idx:end_idx]
        
        # Формируем сообщение с информацией о директории
        message_text = f"📁 <b>Путь:</b> <code>{html.escape(current_path)}</code>\n\n"
        message_text += f"📂 <b>Папок:</b> {len(folders)}\n"
        message_text += f"📄 <b>Файлов:</b> {len(files)}\n"
        
        if files:
            total_size = sum(file.get('size', 0) for file in files)
            message_text += f"💾 <b>Общий размер:</b> {self.get_human_readable_size(total_size)}\n"
        
        message_text += f"\n<b>Страница {current_page + 1}/{total_pages}</b>"
        
        # Формируем клавиатуру с элементами и навигационными кнопками
        keyboard = self.create_file_browser_keyboard(current_items, current_path, current_page, total_pages)
        
        # Отправляем или обновляем сообщение
        await self.send_or_edit_message(update, message_text, keyboard)
    
    def create_file_browser_keyboard(self, items: List[Dict], current_path: str, 
                                    current_page: int, total_pages: int) -> InlineKeyboardMarkup:
        """Создает клавиатуру для просмотра файлов и папок."""
        keyboard = []
        
        # Добавляем кнопки для каждого элемента
        for item in items:
            name = item.get('name', 'Unknown')
            is_dir = item.get('isdir', False)
            
            if is_dir:
                # Формируем путь к подпапке
                folder_path = os.path.join(current_path, name).replace('\\', '/')
                if folder_path.endswith('//'):
                    folder_path = folder_path[:-1]
                
                keyboard.append([
                    InlineKeyboardButton(
                        f"📁 {name}", 
                        callback_data=f"fm:browse:{folder_path}"
                    )
                ])
            else:
                # Формируем путь к файлу
                file_path = os.path.join(current_path, name).replace('\\', '/')
                file_size = self.get_human_readable_size(item.get('size', 0))
                
                keyboard.append([
                    InlineKeyboardButton(
                        f"📄 {name} ({file_size})",
                        callback_data=f"fm:download:{file_path}"
                    )
                ])
        
        # Добавляем кнопки навигации
        nav_buttons = []
        
        # Кнопка "Вверх", если не в корневой директории
        if current_path != "/" and current_path:
            parent_path = os.path.dirname(current_path) or "/"
            nav_buttons.append(InlineKeyboardButton("⬆️ Вверх", callback_data=f"fm:browse:{parent_path}"))
        
        # Кнопки пагинации
        if total_pages > 1:
            nav_buttons.append(InlineKeyboardButton(
                "⬅️", 
                callback_data=f"fm:nav:prev:{current_path}"
            ))
            nav_buttons.append(InlineKeyboardButton(
                f"{current_page + 1}/{total_pages}", 
                callback_data=f"fm:nav:refresh:{current_path}"
            ))
            nav_buttons.append(InlineKeyboardButton(
                "➡️", 
                callback_data=f"fm:nav:next:{current_path}"
            ))
        
        keyboard.append(nav_buttons)
        
        # Добавляем кнопки действий
        action_buttons = [
            InlineKeyboardButton("📤 Загрузить файл", callback_data=f"fm:upload:{current_path}"),
            InlineKeyboardButton("📁 Новая папка", callback_data=f"fm:mkdir:{current_path}")
        ]
        keyboard.append(action_buttons)
        
        # Кнопка закрытия
        keyboard.append([InlineKeyboardButton("🔚 Закрыть", callback_data="fm:nav:close")])
        
        return InlineKeyboardMarkup(keyboard)
    
    def get_empty_folder_keyboard(self, current_path: str) -> InlineKeyboardMarkup:
        """Создает клавиатуру для пустой папки."""
        keyboard = []
        
        # Кнопка "Вверх", если не в корневой директории
        if current_path != "/" and current_path:
            parent_path = os.path.dirname(current_path) or "/"
            keyboard.append([InlineKeyboardButton("⬆️ Вверх", callback_data=f"fm:browse:{parent_path}")])
        
        # Добавляем кнопки действий
        action_buttons = [
            InlineKeyboardButton("📤 Загрузить файл", callback_data=f"fm:upload:{current_path}"),
            InlineKeyboardButton("📁 Новая папка", callback_data=f"fm:mkdir:{current_path}")
        ]
        keyboard.append(action_buttons)
        
        # Кнопка закрытия
        keyboard.append([InlineKeyboardButton("🔚 Закрыть", callback_data="fm:nav:close")])
        
        return InlineKeyboardMarkup(keyboard)
    
    async def send_or_edit_message(self, update: Update, text: str, reply_markup: InlineKeyboardMarkup) -> None:
        """Отправляет новое сообщение или редактирует существующее."""
        if update.callback_query:
            await update.callback_query.answer()
            try:
                await update.callback_query.edit_message_text(
                    text,
                    reply_markup=reply_markup,
                    parse_mode=ParseMode.HTML
                )
            except Exception as e:
                logger.error(f"Error editing message: {e}")
                if update.callback_query.message:
                    await update.callback_query.message.edit_text(
                        text,
                        reply_markup=reply_markup,
                        parse_mode=ParseMode.HTML
                    )
        elif update.message:
            await update.message.reply_text(
                text,
                reply_markup=reply_markup,
                parse_mode=ParseMode.HTML
            )
    
    async def browse_callback(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
        """Обрабатывает переходы по директориям."""
        query = update.callback_query
        if not query:
            return BROWSING
        
        user_id = update.effective_user.id
        path = query.data.split("fm:browse:")[1]
        
        # Устанавливаем новый путь для пользователя
        self.set_user_path(user_id, path)
        # Сбрасываем пагинацию
        self.set_user_pagination(user_id, 0, 1)
        
        # Отображаем содержимое нового пути
        await self.display_directory_content(update, context)
        return BROWSING
    
    async def download_callback(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
        """Обрабатывает запросы на скачивание файлов."""
        query = update.callback_query
        if not query:
            return BROWSING
        
        user_id = update.effective_user.id
        file_path = query.data.split("fm:download:")[1]
        
        # Информация о файле
        file_name = os.path.basename(file_path)
        file_dir = os.path.dirname(file_path)
        
        await query.answer(f"Подготовка к скачиванию {file_name}...")
        
        # Создаем клавиатуру с кнопками действий для файла
        keyboard = [
            [
                InlineKeyboardButton("⬇️ Скачать", callback_data=f"fm:download:get:{file_path}"),
                InlineKeyboardButton("❌ Удалить", callback_data=f"fm:delete:confirm:{file_path}")
            ],
            [
                InlineKeyboardButton("✏️ Переименовать", callback_data=f"fm:rename:start:{file_path}"),
                InlineKeyboardButton("🔙 Назад", callback_data=f"fm:browse:{file_dir}")
            ]
        ]
        
        # Получаем дополнительную информацию о файле
        file_info = self.synology_api.get_file_info(file_path)
        
        if file_info:
            file_size = self.get_human_readable_size(file_info.get('size', 0))
            file_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(file_info.get('time', {}).get('mtime', 0)))
            file_owner = file_info.get('owner', {}).get('user', 'Unknown')
            
            message_text = (
                f"📄 <b>Файл:</b> <code>{html.escape(file_name)}</code>\n\n"
                f"📂 <b>Расположение:</b> <code>{html.escape(file_dir)}</code>\n"
                f"💾 <b>Размер:</b> {file_size}\n"
                f"🕒 <b>Изменён:</b> {file_time}\n"
                f"👤 <b>Владелец:</b> {file_owner}\n\n"
                f"Выберите действие:"
            )
        else:
            message_text = (
                f"📄 <b>Файл:</b> <code>{html.escape(file_name)}</code>\n\n"
                f"📂 <b>Расположение:</b> <code>{html.escape(file_dir)}</code>\n\n"
                f"Выберите действие:"
            )
        
        await query.edit_message_text(
            message_text,
            reply_markup=InlineKeyboardMarkup(keyboard),
            parse_mode=ParseMode.HTML
        )
        
        return BROWSING
    
    async def upload_callback(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
        """Начинает процесс загрузки файла."""
        query = update.callback_query
        if not query:
            return BROWSING
        
        user_id = update.effective_user.id
        path = query.data.split("fm:upload:")[1]
        
        # Сохраняем путь для загрузки в данные пользователя
        self.set_user_path(user_id, path)
        
        await query.answer()
        await query.edit_message_text(
            f"📤 <b>Загрузка файла</b>\n\n"
            f"Путь: <code>{html.escape(path)}</code>\n\n"
            f"Пожалуйста, отправьте файл, который хотите загрузить, или нажмите 'Отмена'.",
            reply_markup=InlineKeyboardMarkup([
                [InlineKeyboardButton("❌ Отмена", callback_data=f"fm:browse:{path}")]
            ]),
            parse_mode=ParseMode.HTML
        )
        
        return UPLOADING
    
    async def handle_file_upload(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
        """Обрабатывает загрузку файла от пользователя."""
        user_id = update.effective_user.id
        upload_path = self.get_user_path(user_id)
        
        # Проверяем наличие файла
        if not update.message.document:
            await update.message.reply_text(
                "❌ Не найден файл для загрузки. Пожалуйста, отправьте файл."
            )
            return UPLOADING
        
        document = update.message.document
        file_name = document.file_name or f"file_{int(time.time())}"
        
        # Сообщение о начале загрузки
        status_message = await update.message.reply_text(
            f"⏳ Начинаем загрузку файла {file_name}..."
        )
        
        try:
            # Получаем файл
            file = await context.bot.get_file(document.file_id)
            file_path = os.path.join(upload_path, file_name).replace("\\", "/")
            
            # Временный путь для сохранения файла
            temp_file_path = f"temp_{user_id}_{int(time.time())}_{file_name}"
            
            # Скачиваем файл во временную директорию
            await file.download_to_drive(temp_file_path)
            
            # Загружаем файл на Synology NAS
            success = self.synology_api.upload_file(temp_file_path, file_path)
            
            # Удаляем временный файл
            if os.path.exists(temp_file_path):
                os.remove(temp_file_path)
            
            if success:
                await status_message.edit_text(
                    f"✅ Файл {file_name} успешно загружен в {upload_path}"
                )
                
                # Показываем содержимое директории
                await self.display_directory_content(update, context)
                return BROWSING
            else:
                await status_message.edit_text(
                    f"❌ Не удалось загрузить файл {file_name}. Пожалуйста, попробуйте снова."
                )
                return UPLOADING
                
        except Exception as e:
            logger.error(f"Error uploading file: {e}")
            await status_message.edit_text(
                f"❌ Произошла ошибка при загрузке файла: {str(e)}"
            )
            return UPLOADING
    
    async def delete_callback(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
        """Обрабатывает запросы на удаление файлов."""
        query = update.callback_query
        if not query:
            return BROWSING
        
        # Извлекаем путь и режим из callback_data
        callback_data = query.data
        if ":confirm:" in callback_data:
            # Запрос на подтверждение удаления
            file_path = callback_data.split("fm:delete:confirm:")[1]
            file_name = os.path.basename(file_path)
            file_dir = os.path.dirname(file_path)
            
            await query.answer()
            await query.edit_message_text(
                f"❗ <b>Подтверждение удаления</b>\n\n"
                f"Вы действительно хотите удалить файл <code>{html.escape(file_name)}</code>?",
                reply_markup=InlineKeyboardMarkup([
                    [
                        InlineKeyboardButton("✅ Да, удалить", callback_data=f"fm:delete:execute:{file_path}"),
                        InlineKeyboardButton("❌ Отмена", callback_data=f"fm:browse:{file_dir}")
                    ]
                ]),
                parse_mode=ParseMode.HTML
            )
            return DELETING
            
        elif ":execute:" in callback_data:
            # Выполнение удаления
            file_path = callback_data.split("fm:delete:execute:")[1]
            file_name = os.path.basename(file_path)
            file_dir = os.path.dirname(file_path)
            
            await query.answer("Удаление файла...")
            
            # Удаляем файл
            success = self.synology_api.delete_file(file_path)
            
            if success:
                await query.edit_message_text(
                    f"✅ Файл {file_name} успешно удален.",
                    reply_markup=InlineKeyboardMarkup([
                        [InlineKeyboardButton("🔙 К папке", callback_data=f"fm:browse:{file_dir}")]
                    ])
                )
            else:
                await query.edit_message_text(
                    f"❌ Не удалось удалить файл {file_name}.",
                    reply_markup=InlineKeyboardMarkup([
                        [InlineKeyboardButton("🔙 К папке", callback_data=f"fm:browse:{file_dir}")]
                    ])
                )
            
            # Возвращаемся к просмотру директории
            return BROWSING
        
        return BROWSING
    
    async def rename_callback(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
        """Обрабатывает запросы на переименование файлов."""
        query = update.callback_query
        if not query:
            return BROWSING
        
        # Извлекаем путь и режим из callback_data
        callback_data = query.data
        if ":start:" in callback_data:
            # Начало процесса переименования
            file_path = callback_data.split("fm:rename:start:")[1]
            file_name = os.path.basename(file_path)
            file_dir = os.path.dirname(file_path)
            
            # Сохраняем информацию о переименовании в контексте пользователя
            if not context.user_data:
                context.user_data = {}
            context.user_data['renaming'] = {
                'file_path': file_path,
                'file_dir': file_dir
            }
            
            await query.answer()
            await query.edit_message_text(
                f"✏️ <b>Переименование файла</b>\n\n"
                f"Текущее имя: <code>{html.escape(file_name)}</code>\n\n"
                f"Пожалуйста, отправьте новое имя для файла:",
                reply_markup=InlineKeyboardMarkup([
                    [InlineKeyboardButton("❌ Отмена", callback_data=f"fm:browse:{file_dir}")]
                ]),
                parse_mode=ParseMode.HTML
            )
            return RENAMING
            
        return BROWSING
        
    async def handle_rename(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
        """Обрабатывает ввод нового имени файла."""
        if not context.user_data or 'renaming' not in context.user_data:
            await update.message.reply_text(
                "❌ Ошибка: информация о переименовании файла отсутствует."
            )
            return BROWSING
            
        file_path = context.user_data['renaming'].get('file_path')
        file_dir = context.user_data['renaming'].get('file_dir')
        old_name = os.path.basename(file_path)
        new_name = update.message.text.strip()
        
        # Проверяем корректность имени файла
        if not new_name or '/' in new_name or '\\' in new_name or new_name in ['.', '..']:
            await update.message.reply_text(
                "❌ Некорректное имя файла. Пожалуйста, введите корректное имя без специальных символов."
            )
            return RENAMING
            
        # Сообщение о начале операции
        status_message = await update.message.reply_text(
            f"⏳ Переименование {old_name} в {new_name}..."
        )
        
        # Переименовываем файл
        success = self.synology_api.rename_file(file_path, new_name)
        
        if success:
            await status_message.edit_text(
                f"✅ Файл {old_name} успешно переименован в {new_name}"
            )
            
            # Очищаем данные о переименовании
            if 'renaming' in context.user_data:
                del context.user_data['renaming']
                
            # Устанавливаем путь к директории и отображаем её содержимое
            user_id = update.effective_user.id
            self.set_user_path(user_id, file_dir)
            await self.display_directory_content(update, context)
            return BROWSING
        else:
            await status_message.edit_text(
                f"❌ Не удалось переименовать файл {old_name}. Проверьте права доступа и допустимость имени."
            )
            return RENAMING
    
    async def create_folder_callback(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
        """Обрабатывает запросы на создание папок."""
        query = update.callback_query
        if not query or not query.data:
            return BROWSING
        
        path = query.data.split("fm:mkdir:")[1]
        
        # Сохраняем информацию о создании папки в контексте пользователя
        if not context.user_data:
            context.user_data = {}
        context.user_data['creating_folder'] = {
            'path': path
        }
        
        await query.answer()
        await query.edit_message_text(
            f"📁 <b>Создание новой папки</b>\n\n"
            f"Путь: <code>{html.escape(path)}</code>\n\n"
            f"Пожалуйста, введите имя для новой папки:",
            reply_markup=InlineKeyboardMarkup([
                [InlineKeyboardButton("❌ Отмена", callback_data=f"fm:browse:{path}")]
            ]),
            parse_mode=ParseMode.HTML
        )
        
        return CREATING_FOLDER
        
    async def handle_create_folder(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
        """Обрабатывает создание новой папки."""
        if not update.message:
            return CREATING_FOLDER
            
        if not context.user_data or not context.user_data.get('creating_folder'):
            await update.message.reply_text(
                "❌ Ошибка: информация о создаваемой папке отсутствует."
            )
            return BROWSING
        
        parent_path = context.user_data['creating_folder'].get('path')
        folder_name = update.message.text.strip()
        
        # Проверяем корректность имени папки
        if not folder_name or '/' in folder_name or '\\' in folder_name or folder_name in ['.', '..']:
            await update.message.reply_text(
                "❌ Некорректное имя папки. Пожалуйста, введите корректное имя без специальных символов."
            )
            return CREATING_FOLDER
        
        # Сообщение о начале операции
        status_message = await update.message.reply_text(
            f"⏳ Создание папки {folder_name}..."
        )
        
        # Создаем папку
        success = self.synology_api.create_folder(parent_path, folder_name)
        
        if success:
            await status_message.edit_text(
                f"✅ Папка {folder_name} успешно создана в {parent_path}"
            )
            
            # Отображаем обновленное содержимое директории
            user_id = update.effective_user.id
            self.set_user_path(user_id, parent_path)
            await self.display_directory_content(update, context)
            return BROWSING
        else:
            await status_message.edit_text(
                f"❌ Не удалось создать папку {folder_name}. Проверьте права доступа и допустимость имени."
            )
            return CREATING_FOLDER
    
    async def navigation_callback(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
        """Обрабатывает навигационные запросы (пагинация, обновление, закрытие)."""
        query = update.callback_query
        if not query or not query.data:
            return BROWSING
        
        callback_data = query.data
        user_id = update.effective_user.id if update.effective_user else 0
        
        if callback_data.startswith("fm:nav:prev:"):
            # Предыдущая страница
            path = callback_data[len("fm:nav:prev:"):]
            pagination = self.get_user_pagination(user_id)
            page = (pagination['page'] - 1) % pagination['total_pages']
            self.set_user_pagination(user_id, page, pagination['total_pages'])
            self.set_user_path(user_id, path)
            await self.display_directory_content(update, context)
            
        elif callback_data.startswith("fm:nav:next:"):
            # Следующая страница
            path = callback_data[len("fm:nav:next:"):]
            pagination = self.get_user_pagination(user_id)
            page = (pagination['page'] + 1) % pagination['total_pages']
            self.set_user_pagination(user_id, page, pagination['total_pages'])
            self.set_user_path(user_id, path)
            await self.display_directory_content(update, context)
            
        elif callback_data.startswith("fm:nav:refresh:"):
            # Обновить текущую директорию
            path = callback_data[len("fm:nav:refresh:"):]
            self.set_user_path(user_id, path)
            await self.display_directory_content(update, context)
            
        elif callback_data == "fm:nav:close":
            # Закрыть файловый менеджер
            await query.answer("Файловый менеджер закрыт")
            await query.delete_message()
            return ConversationHandler.END
        
        return BROWSING
    
    def get_human_readable_size(self, size_bytes: int) -> str:
        """Преобразует размер в байтах в человекочитаемый формат."""
        if size_bytes == 0:
            return "0 B"
        
        size_names = ["B", "KB", "MB", "GB", "TB", "PB"]
        i = 0
        size_float = float(size_bytes)
        while size_float >= 1024 and i < len(size_names) - 1:
            size_float /= 1024.0
            i += 1
        
        return f"{size_float:.2f} {size_names[i]}"

# Функция для создания ConversationHandler для файлового менеджера
async def cancel_conversation(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
    """Обработчик отмены диалога."""
    if update.message:
        await update.message.reply_text("Операция отменена.")
    return ConversationHandler.END

def create_file_manager_handler(synology_api: SynologyAPI) -> ConversationHandler:
    """Создает и возвращает ConversationHandler для файлового менеджера."""
    file_manager = FileManagerAgent(synology_api)
    
    return ConversationHandler(
        entry_points=[CommandHandler("files", file_manager.start_file_manager)],
        states={
            BROWSING: [
                CallbackQueryHandler(file_manager.browse_callback, pattern="^fm:browse:"),
                CallbackQueryHandler(file_manager.download_callback, pattern="^fm:download:"),
                CallbackQueryHandler(file_manager.upload_callback, pattern="^fm:upload:"),
                CallbackQueryHandler(file_manager.delete_callback, pattern="^fm:delete:"),
                CallbackQueryHandler(file_manager.rename_callback, pattern="^fm:rename:"),
                CallbackQueryHandler(file_manager.create_folder_callback, pattern="^fm:mkdir:"),
                CallbackQueryHandler(file_manager.navigation_callback, pattern="^fm:nav:")
            ],
            UPLOADING: [
                MessageHandler(filters.ATTACHMENT & ~filters.COMMAND, file_manager.handle_file_upload),
                CallbackQueryHandler(file_manager.browse_callback, pattern="^fm:browse:")
            ],
            RENAMING: [
                MessageHandler(filters.TEXT & ~filters.COMMAND, file_manager.handle_rename),
                CallbackQueryHandler(file_manager.browse_callback, pattern="^fm:browse:")
            ],
            DELETING: [
                CallbackQueryHandler(file_manager.delete_callback, pattern="^fm:delete:"),
                CallbackQueryHandler(file_manager.browse_callback, pattern="^fm:browse:")
            ],
            CREATING_FOLDER: [
                MessageHandler(filters.TEXT & ~filters.COMMAND, file_manager.handle_create_folder),
                CallbackQueryHandler(file_manager.browse_callback, pattern="^fm:browse:")
            ]
        },
        fallbacks=[
            CommandHandler("cancel", cancel_conversation),
            CallbackQueryHandler(file_manager.navigation_callback, pattern="^fm:nav:close")
        ],
        name="file_manager",
        persistent=False
    )
