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

"""
Обработчики команд для телеграм-бота
"""

import logging
import socket
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import ContextTypes

from src.config.config import (
    ADMIN_USER_IDS, SYNOLOGY_HOST, SYNOLOGY_PORT, SYNOLOGY_MAC
)
from src.api.synology import SynologyAPI
from src.utils.admin_utils import admin_required

logger = logging.getLogger(__name__)

# Инициализация API Synology
synology_api = SynologyAPI()

from src.utils.admin_utils import admin_required

@admin_required
async def status_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Обработчик команды /status"""
    message = await update.message.reply_text("⏳ Проверяю статус Synology NAS...")
    
    is_online = synology_api.is_online()
    
    if is_online:
        try:
            # Если NAS включен, попробуем получить дополнительную информацию
            system_info = synology_api.get_system_status()
            
            if system_info and system_info.get("status") != "error":
                model = system_info.get("model", "Неизвестная модель")
                version = system_info.get("version_string", system_info.get("version", "Неизвестная версия"))
                uptime_seconds = system_info.get("up_time", system_info.get("uptime", 0))
                
                # Преобразование времени работы в удобочитаемый формат
                days, remainder = divmod(int(uptime_seconds), 86400)
                hours, remainder = divmod(remainder, 3600)
                minutes, seconds = divmod(remainder, 60)
                uptime_str = f"{days}д {hours}ч {minutes}м {seconds}с"
                
                await message.edit_text(
                    f"✅ <b>Synology NAS онлайн</b>\n\n"
                    f"<b>Модель:</b> {model}\n"
                    f"<b>Версия DSM:</b> {version}\n"
                    f"<b>Время работы:</b> {uptime_str}",
                    parse_mode="HTML"
                )
            else:
                # Обработка возможной ошибки API
                error_info = ""
                if system_info and system_info.get("status") == "error":
                    error_code = system_info.get("error_code", "неизвестно")
                    error_info = f"\n<i>Код ошибки API: {error_code}</i>"
                
                # Проверяем порт и сеть
                network_info = ""
                try:
                    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    s.settimeout(1)
                    result = s.connect_ex((SYNOLOGY_HOST, SYNOLOGY_PORT))
                    s.close()
                    if result == 0:
                        network_info = f"\n\n<b>Сетевая информация:</b>\nIP: {SYNOLOGY_HOST}\nПорт {SYNOLOGY_PORT}: <b>открыт</b>"
                    else:
                        network_info = f"\n\n<b>Сетевая информация:</b>\nIP: {SYNOLOGY_HOST}\nПорт {SYNOLOGY_PORT}: <b>закрыт</b> (код {result})"
                except Exception as e:
                    network_info = f"\n\n<b>Сетевая информация:</b>\nIP: {SYNOLOGY_HOST}\nОшибка проверки порта: {str(e)}"
                    
                await message.edit_text(
                    f"✅ <b>Synology NAS онлайн</b>\n\n"
                    f"Устройство доступно по сети, но детальная информация через API недоступна. "
                    f"Возможно, необходимо проверить учетные данные или права доступа."
                    f"{error_info}"
                    f"{network_info}",
                    parse_mode="HTML"
                )
        except Exception as e:
            await message.edit_text(
                f"✅ <b>Synology NAS онлайн</b>\n\n"
                f"<b>Ошибка при получении информации:</b> {str(e)[:100]}...\n\n"
                f"<b>Сетевая информация:</b>\nIP: {SYNOLOGY_HOST}\nПорт: {SYNOLOGY_PORT}",
                parse_mode="HTML"
            )
    else:
        # Устройство не в сети, проверим соседние порты для диагностики
        port_scan_info = ""
        try:
            for test_port in [SYNOLOGY_PORT-1, SYNOLOGY_PORT, SYNOLOGY_PORT+1, 5000, 5001]:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.settimeout(1)
                result = s.connect_ex((SYNOLOGY_HOST, test_port))
                s.close()
                status = "открыт" if result == 0 else "закрыт"
                port_scan_info += f"Порт {test_port}: <b>{status}</b>\n"
                
            # Добавим информацию о MAC-адресе для WoL
            mac_info = f"MAC: {SYNOLOGY_MAC}" if SYNOLOGY_MAC else "MAC-адрес не настроен"
                
            await message.edit_text(
                f"❌ <b>Synology NAS оффлайн</b>\n\n"
                f"<b>Информация о сети:</b>\n"
                f"IP: {SYNOLOGY_HOST}\n"
                f"{port_scan_info}\n"
                f"{mac_info}\n\n"
                f"Используйте /power для отправки Wake-on-LAN пакета",
                parse_mode="HTML"
            )
        except Exception as e:
            await message.edit_text(
                f"❌ <b>Synology NAS оффлайн</b>\n\n"
                f"<b>Ошибка при сканировании портов:</b> {str(e)[:100]}...\n\n"
                f"Используйте /power для отправки Wake-on-LAN пакета",
                parse_mode="HTML"
            )

async def power_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Обработчик команды /power"""
    user_id = update.effective_user.id
    
    if user_id not in ADMIN_USER_IDS:
        await update.message.reply_text("У вас нет доступа к этому боту.")
        return
    
    is_online = synology_api.is_online()
    
    keyboard = []
    
    # Кнопка включения
    if not is_online:
        keyboard.append([InlineKeyboardButton("🟢 Включить", callback_data="power_on")])
    else:
        keyboard.append([InlineKeyboardButton("🟢 Включить (уже включено)", callback_data="power_on_no_op")])
        
    # Кнопка выключения
    if is_online:
        keyboard.append([InlineKeyboardButton("🔴 Выключить", callback_data="power_off")])
    else:
        keyboard.append([InlineKeyboardButton("🔴 Выключить (уже выключено)", callback_data="power_off_no_op")])
        
    # Кнопка перезагрузки
    if is_online:
        keyboard.append([InlineKeyboardButton("🔄 Перезагрузить", callback_data="reboot")])
    else:
        keyboard.append([InlineKeyboardButton("🔄 Перезагрузить (недоступно)", callback_data="reboot_no_op")])
        
    # Кнопка отмены
    keyboard.append([InlineKeyboardButton("❌ Отмена", callback_data="cancel")])
    
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    status_text = "✅ Онлайн" if is_online else "❌ Оффлайн"
    
    await update.message.reply_text(
        f"<b>Управление питанием Synology NAS</b>\n\n"
        f"<b>Текущий статус:</b> {status_text}\n\n"
        f"Выберите действие:",
        reply_markup=reply_markup,
        parse_mode="HTML"
    )

async def power_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Обработчик callback-запросов для кнопок управления питанием"""
    query = update.callback_query
    await query.answer()
    
    user_id = query.from_user.id
    if user_id not in ADMIN_USER_IDS:
        return
    
    action = query.data
    
    if action == "cancel":
        await query.edit_message_text("❌ Действие отменено")
        return
    
    # Обработка неактивных кнопок
    if action in ["power_on_no_op", "power_off_no_op", "reboot_no_op"]:
        if action == "power_on_no_op":
            await query.edit_message_text("ℹ️ Synology NAS уже включен")
        elif action == "power_off_no_op":
            await query.edit_message_text("ℹ️ Synology NAS уже выключен")
        else:
            await query.edit_message_text("ℹ️ Невозможно перезагрузить выключенное устройство")
        return
    
    # Обработка основных действий
    if action == "power_on":
        await query.edit_message_text("⏳ Отправка сигнала включения Synology NAS...")
        
        if await context.application.create_task(
            handle_power_on(query.message.chat_id, context)
        ):
            # Функция вернула True, успешное включение
            pass
        else:
            # Функция вернула False, ошибка включения
            await context.bot.send_message(
                chat_id=query.message.chat_id,
                text="❌ Ошибка при включении Synology NAS. Проверьте настройки Wake-on-LAN."
            )
            
    elif action == "power_off":
        await query.edit_message_text("⏳ Отправка команды выключения Synology NAS...")
        
        try:
            success = await handle_power_off(query.message.chat_id, context)
            # Если handle_power_off уже отправил сообщение об успехе или ошибке, 
            # дополнительных сообщений не требуется
        except Exception as e:
            logger.error(f"Exception in power_off callback: {str(e)}")
            await context.bot.send_message(
                chat_id=query.message.chat_id,
                text="❌ Ошибка при выключении Synology NAS. Проверьте соединение и учетные данные."
            )
            
    elif action == "reboot":
        await query.edit_message_text("⏳ Отправка команды перезагрузки Synology NAS...")
        
        if await context.application.create_task(
            handle_reboot(query.message.chat_id, context)
        ):
            # Функция вернула True, успешная перезагрузка
            pass
        else:
            # Функция вернула False, ошибка перезагрузки
            await context.bot.send_message(
                chat_id=query.message.chat_id,
                text="❌ Ошибка при перезагрузке Synology NAS. Проверьте соединение и учетные данные."
            )

async def handle_power_on(chat_id: int, context: ContextTypes.DEFAULT_TYPE) -> bool:
    """Асинхронная функция для включения NAS"""
    try:
        # Отправка запроса на включение
        success = synology_api.power_on()
        
        if success:
            await context.bot.send_message(
                chat_id=chat_id,
                text="✅ Synology NAS успешно включен и доступен"
            )
            return True
        else:
            return False
    except Exception as e:
        logger.error(f"Error during power on: {str(e)}")
        return False

async def handle_power_off(chat_id: int, context: ContextTypes.DEFAULT_TYPE) -> bool:
    """Асинхронная функция для выключения NAS"""
    try:
        # Проверка доступности NAS
        if not synology_api.is_online():
            await context.bot.send_message(
                chat_id=chat_id,
                text="⚠️ Synology NAS не в сети. Невозможно отправить команду выключения."
            )
            return False
        
        # Отправка запроса на выключение
        success = synology_api.power_off()
        
        if success:
            await context.bot.send_message(
                chat_id=chat_id,
                text="✅ Команда выключения успешно отправлена. Synology NAS выключается..."
            )
            return True
        else:
            await context.bot.send_message(
                chat_id=chat_id,
                text="⚠️ Ошибка при отправке команды выключения. Пожалуйста, проверьте журналы для получения дополнительной информации."
            )
            return False
    except Exception as e:
        error_msg = str(e)
        logger.error(f"Error during power off: {error_msg}")
        await context.bot.send_message(
            chat_id=chat_id,
            text=f"❌ Ошибка при выключении: {error_msg[:100]}..."
        )
        return False

async def handle_reboot(chat_id: int, context: ContextTypes.DEFAULT_TYPE) -> bool:
    """Асинхронная функция для перезагрузки NAS"""
    try:
        # Отправка запроса на перезагрузку
        success = synology_api.reboot_system()
        
        if success:
            await context.bot.send_message(
                chat_id=chat_id,
                text="✅ Команда перезагрузки успешно отправлена. Synology NAS перезагружается..."
            )
            
            # Ждем некоторое время перед проверкой статуса
            await context.bot.send_message(
                chat_id=chat_id,
                text="⏳ Ожидание перезагрузки системы..."
            )
            
            # Создаем задачу для ожидания загрузки
            wait_successful = synology_api.wait_for_boot()
            
            if wait_successful:
                await context.bot.send_message(
                    chat_id=chat_id,
                    text="✅ Synology NAS успешно перезагружен и снова онлайн"
                )
            else:
                await context.bot.send_message(
                    chat_id=chat_id,
                    text="⚠️ Превышено время ожидания перезагрузки. Проверьте статус вручную."
                )
            
            return True
        else:
            return False
    except Exception as e:
        logger.error(f"Error during reboot: {str(e)}")
        return False
