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

"""
Модуль для взаимодействия с API Synology NAS
"""

import requests
from requests.adapters import HTTPAdapter
import json
import logging
import time
import urllib3
from urllib3.util import Retry
from typing import Dict, Any, Optional, List
import socket
import struct
from time import sleep

from src.config.config import (
    SYNOLOGY_HOST, 
    SYNOLOGY_PORT,
    SYNOLOGY_USERNAME,
    SYNOLOGY_PASSWORD,
    SYNOLOGY_SECURE,
    SYNOLOGY_TIMEOUT,
    SYNOLOGY_MAC,
    WOL_PORT
)

# Отключение предупреждений о небезопасных SSL-соединениях
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

logger = logging.getLogger(__name__)

class SynologyAPI:
    """Класс для взаимодействия с API Synology NAS"""
    
    def __init__(self):
        """Инициализация класса SynologyAPI"""
        logger.info("Creating API with auto-retry and connection pool")
        logger.debug(f"Connection details: Host={SYNOLOGY_HOST}, Port={SYNOLOGY_PORT}, Secure={SYNOLOGY_SECURE}")
        
        self.protocol = "https" if SYNOLOGY_SECURE else "http"
        self.base_url = f"{self.protocol}://{SYNOLOGY_HOST}:{SYNOLOGY_PORT}/webapi"
        self.sid = None
        self.session = requests.Session()
        
        # Настройка SSL
        if self.protocol == "https":
            logger.debug("SSL enabled, disabling certificate verification for internal network")
            self.session.verify = False  # Отключаем проверку SSL для внутренней сети
        
        # Добавляем повторные попытки для HTTP-запросов
        retry_strategy = Retry(
            total=5,  # Увеличиваем количество попыток
            status_forcelist=[429, 500, 502, 503, 504, 404],
            allowed_methods=["GET", "POST"],
            backoff_factor=1.5,  # Увеличиваем задержку между попытками
            respect_retry_after_header=True
        )
        adapter = HTTPAdapter(
            max_retries=retry_strategy, 
            pool_connections=3, 
            pool_maxsize=10
        )
        self.session.mount("http://", adapter)
        self.session.mount("https://", adapter)
        
        # Таймауты будут указаны в запросах
        self.default_timeout = (SYNOLOGY_TIMEOUT, SYNOLOGY_TIMEOUT*2)
        logger.debug(f"Setting default request timeout: {self.default_timeout}")
        
        # Кэш для хранения результатов запросов
        self._cache = {}
        self._cache_ttl = {}
        self._last_online_check = 0
        self._last_online_status = False
        self._online_check_interval = 30  # Интервал для кэширования проверок онлайн-статуса
        
        # Время последней успешной аутентификации и срок действия сессии
        self._last_auth_time = 0
        self._auth_expiry = 3600  # По умолчанию 1 час
        
    def login(self) -> bool:
        """Авторизация в API Synology NAS"""
        # Проверяем, действительна ли текущая сессия
        current_time = time.time()
        if self.sid and (current_time - self._last_auth_time) < self._auth_expiry:
            logger.debug("Using existing session, still valid")
            return True
            
        logger.info("Attempting to authenticate with Synology NAS...")
        logger.debug(f"Base URL: {self.base_url}")
        
        # Проверяем доступность NAS перед запросом с помощью прямой TCP-проверки
        # Избегаем вызова is_online(), чтобы не создавать рекурсию
        online_status = self._check_tcp_connection()
        if not online_status:
            logger.error("Cannot login: Synology NAS is not reachable")
            return False
            
        try:
            # Проверка информации API для определения доступных версий API
            api_info_url = f"{self.base_url}/entry.cgi"
            api_info_params = {
                "api": "SYNO.API.Info",
                "version": "1",
                "method": "query",
                "query": "SYNO.API.Auth"
            }
            
            logger.debug("Querying API info to determine optimal auth version")
            try:
                api_info_response = self.session.get(
                    api_info_url,
                    params=api_info_params,
                    timeout=self.default_timeout,
                    verify=False
                )
                
                if api_info_response.status_code == 200:
                    api_info_data = api_info_response.json()
                    if api_info_data.get("success"):
                        auth_info = api_info_data.get("data", {}).get("SYNO.API.Auth", {})
                        max_version = auth_info.get("maxVersion", 3)
                        min_version = auth_info.get("minVersion", 1)
                        auth_path = auth_info.get("path", "auth.cgi")
                        logger.debug(f"Auth API versions: min={min_version}, max={max_version}, path={auth_path}")
                        
                        # Используем максимально поддерживаемую версию, но не выше 6
                        auth_version = min(max_version, 6)
                    else:
                        logger.warning("Failed to query API info, using default auth version 3")
                        auth_version = 3
                        auth_path = "auth.cgi"
                else:
                    logger.warning(f"API info request failed with status {api_info_response.status_code}, using default auth version 3")
                    auth_version = 3
                    auth_path = "auth.cgi"
            except Exception as e:
                logger.warning(f"Error querying API info: {str(e)}, using default auth version 3")
                auth_version = 3
                auth_path = "auth.cgi"
                
            # Основной запрос авторизации
            url = f"{self.base_url}/{auth_path}"
            params = {
                "api": "SYNO.API.Auth",
                "version": str(auth_version),
                "method": "login",
                "account": SYNOLOGY_USERNAME,
                "passwd": SYNOLOGY_PASSWORD,
                "session": "SynologyPowerControlBot",
                "format": "cookie"
            }
            
            # Для версии 6+ используем немного другой формат
            if auth_version >= 6:
                params["enable_syno_token"] = "yes"
            
            logger.debug(f"Sending auth request to {url} with API version {auth_version}")
            start_time = time.time()
            response = self.session.get(
                url, 
                params=params, 
                timeout=self.default_timeout, 
                verify=False
            )
            elapsed_time = time.time() - start_time
            logger.debug(f"Auth request completed in {elapsed_time:.2f}s with status code {response.status_code}")
            
            # Подробная информация для отладки
            logger.debug(f"Auth response: {response.text[:500]}")
            
            # Проверка статуса HTTP
            if response.status_code != 200:
                logger.error(f"HTTP error: {response.status_code}")
                logger.debug(f"Response content: {response.text[:200]}")
                return False
                
            try:
                data = response.json()
            except json.JSONDecodeError:
                logger.error("Failed to decode JSON response")
                logger.debug(f"Response content: {response.text[:200]}")
                return False
            
            if data.get("success"):
                self.sid = data.get("data", {}).get("sid")
                self._last_auth_time = current_time
                logger.info("Successfully logged in to Synology NAS")
                logger.debug(f"Session ID obtained: {self.sid[:5] if self.sid else 'None'}...")  # Показываем только начало SID для безопасности
                return True
            else:
                error_code = data.get("error", {}).get("code", -1)
                logger.error(f"Failed to log in to Synology NAS: Error code {error_code}")
                
                # Дополнительная диагностика
                if error_code == 400:
                    logger.error("Authentication error: Invalid credentials")
                elif error_code == 401:
                    logger.error("Authentication error: Account disabled")
                elif error_code == 402:
                    logger.error("Authentication error: Permission denied")
                elif error_code == 403:
                    logger.error("Authentication error: 2-factor authentication required")
                elif error_code == 404:
                    logger.error("Authentication error: Failed to authenticate with 2-factor authentication")
                
                return False
                
        except requests.exceptions.Timeout:
            logger.error(f"Connection timeout after {SYNOLOGY_TIMEOUT} seconds")
            return False
        except requests.exceptions.ConnectionError as e:
            logger.error(f"Connection error: {str(e)}")
            logger.debug(f"Connection details: {self.protocol}://{SYNOLOGY_HOST}:{SYNOLOGY_PORT}")
            return False
        except requests.RequestException as e:
            logger.error(f"Request error: {str(e)}")
            return False
        except Exception as e:
            logger.error(f"Unexpected error during login: {str(e)}", exc_info=True)
            return False
    
    def logout(self) -> bool:
        """Выход из API Synology NAS"""
        if not self.sid:
            return True
            
        try:
            url = f"{self.base_url}/auth.cgi"
            params = {
                "api": "SYNO.API.Auth",
                "version": "1",
                "method": "logout",
                "session": "SynologyPowerControlBot",
                "_sid": self.sid
            }
            
            response = self.session.get(url, params=params, timeout=SYNOLOGY_TIMEOUT, verify=False)
            data = response.json()
            
            if data.get("success"):
                self.sid = None
                logger.info("Successfully logged out from Synology NAS")
                return True
            else:
                error_code = data.get("error", {}).get("code", -1)
                logger.error(f"Failed to log out from Synology NAS: Error code {error_code}")
                return False
                
        except requests.RequestException as e:
            logger.error(f"Connection error: {str(e)}")
            return False
    
    def _make_api_request(self, api_name: str, method: str, version: int = 1, 
                         params: Optional[Dict[str, Any]] = None, retry_auth: bool = True) -> Optional[Dict[str, Any]]:
        """Обобщенный метод для выполнения API запросов с обработкой ошибок"""
        # Проверка наличия авторизации
        if not self.sid and not self.login():
            logger.error(f"Not authenticated for API request: {api_name}.{method}")
            return None
            
        # Проверка информации API для определения пути и поддерживаемой версии
        api_info_url = f"{self.base_url}/entry.cgi"
        api_info_params = {
            "api": "SYNO.API.Info",
            "version": "1",
            "method": "query",
            "query": api_name
        }
        
        api_path = "entry.cgi"
        try:
            logger.debug(f"Querying API info for {api_name}")
            api_info_response = self.session.get(
                api_info_url,
                params=api_info_params,
                timeout=self.default_timeout,
                verify=False
            )
            
            if api_info_response.status_code == 200:
                api_info_data = api_info_response.json()
                if api_info_data.get("success"):
                    api_info = api_info_data.get("data", {}).get(api_name, {})
                    if api_info:
                        max_version = api_info.get("maxVersion", version)
                        min_version = api_info.get("minVersion", version)
                        api_path = api_info.get("path", "entry.cgi")
                        
                        # Проверка, поддерживается ли запрошенная версия
                        if version < min_version:
                            logger.warning(f"API version {version} for {api_name} is below minimum {min_version}, using {min_version}")
                            version = min_version
                        elif version > max_version:
                            logger.warning(f"API version {version} for {api_name} exceeds maximum {max_version}, using {max_version}")
                            version = max_version
                            
                        logger.debug(f"Using API path: {api_path}, version: {version}")
                    else:
                        logger.warning(f"API {api_name} not found in API info, using defaults")
        except Exception as e:
            logger.warning(f"Error querying API info for {api_name}: {str(e)}, using defaults")
            
        # Подготовка базовых параметров запроса
        base_params = {
            "api": api_name,
            "version": str(version),
            "method": method,
            "sid": self.sid
        }
        
        # Добавление дополнительных параметров, если они заданы
        if params:
            base_params.update(params)
        
        url = f"{self.base_url}/{api_path}"
        logger.debug(f"API request: {api_name}.{method} v{version} to {url}")
        logger.debug(f"Full request params: {base_params}")
        
        try:
            start_time = time.time()
            response = self.session.get(
                url, 
                params=base_params, 
                timeout=self.default_timeout, 
                verify=False
            )
            elapsed_time = time.time() - start_time
            logger.debug(f"API request completed in {elapsed_time:.2f}s with status {response.status_code}")
            
            # Подробное логирование для отладки
            logger.debug(f"Response: {response.text[:500]}")
            
            # Проверка статуса HTTP
            if response.status_code != 200:
                logger.error(f"HTTP error: {response.status_code} for {api_name}.{method}")
                return None
                
            try:
                data = response.json()
            except json.JSONDecodeError:
                logger.error(f"Failed to decode JSON response for {api_name}.{method}")
                logger.debug(f"Response content: {response.text[:200]}")
                return None
                
            if data.get("success"):
                logger.info(f"API request successful for {api_name}.{method}")
                return data.get("data", {})
            else:
                error_code = data.get("error", {}).get("code", -1)
                error_desc = self._get_error_description(error_code)
                logger.error(f"API error for {api_name}.{method}: {error_code} - {error_desc}")
                
                # Ошибки доступа или прав часто встречаются, но они не критичные
                # Например, ошибка 102 означает, что нет прав, но NAS доступен
                if error_code in [102, 103, 104, 105]:
                    logger.warning(f"Permission-related error for {api_name}.{method}: {error_code}")
                    # Возвращаем пустой словарь вместо None,
                    # чтобы вызывающий код мог понять, что запрос выполнен
                    return {}
                
                # Если ошибка связана с авторизацией и нам разрешено повторить попытку
                if error_code in [106, 107, 119] and retry_auth:
                    logger.info("Session may have expired, re-authenticating...")
                    self.sid = None  # Сбрасываем SID
                    if self.login():
                        logger.info("Re-authenticated, retrying API request...")
                        # Рекурсивный вызов, но без повторной авторизации во избежание зацикливания
                        return self._make_api_request(api_name, method, version, params, False)
                    
                return None
                
        except requests.exceptions.Timeout:
            logger.error(f"Request timeout for {api_name}.{method}")
            return None
        except requests.exceptions.ConnectionError as e:
            logger.error(f"Connection error for {api_name}.{method}: {str(e)}")
            return None
        except Exception as e:
            logger.error(f"Unexpected error during {api_name}.{method}: {str(e)}")
            return None
    
    def get_system_status(self) -> Dict[str, Any]:
        """Получение статуса системы"""
        # Проверяем доступность системы
        if not self.is_online():
            logger.info("Device is offline, skipping API request")
            return {"status": "offline"}
            
        # Проверяем, есть ли кэшированный результат
        cache_key = "system_status"
        current_time = time.time()
        if cache_key in self._cache and current_time - self._cache_ttl.get(cache_key, 0) < 60:
            logger.debug("Using cached system status")
            return self._cache[cache_key]
            
        # Делаем API запрос
        result = self._make_api_request("SYNO.DSM.Info", "getinfo")
        
        if result:
            # Формируем расширенный ответ с дополнительной информацией
            system_info = {
                "status": "online",
                "hostname": result.get("hostname", "unknown"),
                "model": result.get("model", "unknown"),
                "version": result.get("version", "unknown"),
                "uptime": result.get("uptime", 0),
                "time": current_time,
                "is_online": True
            }
            
            # Сохраняем в кэше
            self._cache[cache_key] = system_info
            self._cache_ttl[cache_key] = current_time
            
            return system_info
        else:
            # Если запрос не удался, но система онлайн
            return {
                "status": "error", 
                "error": "Failed to fetch system information",
                "is_online": True,
                "time": current_time
            }
    
    def shutdown_system(self) -> bool:
        """Выключение системы"""
        # Проверяем, включено ли устройство перед попыткой его выключить
        if not self.is_online(force_check=True):
            logger.info("Synology NAS is already offline, no need to shut down")
            return True
            
        logger.info("Attempting to shutdown Synology NAS...")
        
        # Правильный API-вызов для выключения согласно официальной документации DSM API
        result = self._make_api_request("SYNO.Core.System.Power", "shutdown", version=1)
        if result is not None:
            logger.info("Successfully initiated system shutdown using SYNO.Core.System.Power")
            
            # Даем системе время начать процесс выключения
            logger.info("Waiting for shutdown to initialize...")
            sleep(5)
            
            # Проверяем статус
            if not self.is_online(force_check=True):
                logger.info("System is now offline. Shutdown confirmed successful.")
                return True
            else:
                logger.info("System still appears to be online, but shutdown may be in progress.")
                return True
        
        # Запасной вариант с устаревшим API
        logger.info("First shutdown method failed, trying alternative API...")
        result = self._make_api_request("SYNO.Core.System", "shutdown", version=3)
        if result is not None:
            logger.info("Successfully initiated system shutdown using SYNO.Core.System")
            
            # Даем системе время начать процесс выключения
            logger.info("Waiting for shutdown to initialize...")
            sleep(5)
            
            # Проверяем статус
            if not self.is_online(force_check=True):
                logger.info("System is now offline. Shutdown confirmed successful.")
                return True
            else:
                logger.info("System still appears to be online, but shutdown may be in progress.")
                return True
        
        # Если оба метода не сработали, но система стала недоступна
        if not self.is_online(force_check=True):
            logger.info("System appears to be shutting down despite API errors")
            return True
            
        logger.error("Failed to shutdown system after trying multiple APIs")
        return False
    
    def reboot_system(self) -> bool:
        """Перезагрузка системы"""
        # Проверяем, включена ли система
        if not self.is_online(force_check=True):
            logger.error("Cannot reboot: System is offline")
            return False
        
        logger.info("Attempting to reboot Synology NAS...")
        
        # Правильный API-вызов для перезагрузки согласно официальной документации DSM API
        result = self._make_api_request("SYNO.Core.System.Power", "restart", version=1)
        
        if result is not None:
            logger.info("Successfully initiated system reboot using SYNO.Core.System.Power")
            
            # Даем системе время начать процесс перезагрузки
            logger.info("Waiting for reboot to initialize...")
            sleep(5)
            
            # Ждем, пока система станет недоступна (признак перезагрузки)
            reboot_started = False
            for i in range(12):  # Проверяем в течение 60 секунд (12 * 5сек)
                if not self.is_online(force_check=True):
                    logger.info(f"System went offline after {i*5} seconds, reboot in progress")
                    reboot_started = True
                    break
                logger.debug(f"System still online, waiting... ({i+1}/12)")
                sleep(5)
                
            if reboot_started:
                # Ждем, пока система снова станет доступна
                logger.info("Waiting for system to come back online...")
                return self.wait_for_boot(max_attempts=30, delay=10)
            else:
                logger.warning("System did not go offline after reboot command")
                return False
        
        # Запасной вариант, если первый метод не сработал
        logger.info("First reboot method failed, trying alternative API...")
        result = self._make_api_request("SYNO.Core.System", "reboot", version=3)
        if result is not None:
            logger.info("Successfully initiated system reboot using SYNO.Core.System")
            
            # Даем системе время начать процесс перезагрузки
            logger.info("Waiting for reboot to initialize...")
            sleep(5)
            
            # Ждем, пока система станет недоступна (признак перезагрузки)
            reboot_started = False
            for i in range(12):  # Проверяем в течение 60 секунд (12 * 5сек)
                if not self.is_online(force_check=True):
                    logger.info(f"System went offline after {i*5} seconds, reboot in progress")
                    reboot_started = True
                    break
                logger.debug(f"System still online, waiting... ({i+1}/12)")
                sleep(5)
                
            if reboot_started:
                # Ждем, пока система снова станет доступна
                logger.info("Waiting for system to come back online...")
                return self.wait_for_boot(max_attempts=30, delay=10)
            else:
                logger.warning("System did not go offline after reboot command")
                return False
        
        logger.error("Failed to reboot system after trying multiple APIs")
        return False
    
    def _get_error_description(self, error_code: int) -> str:
        """Получение описания ошибки по коду"""
        error_descriptions = {
            100: "Unknown error",
            101: "Invalid parameter",
            102: "API does not exist",
            103: "Method does not exist",
            104: "Version does not support",
            105: "Permission denied",
            106: "Session timeout",
            107: "Session interrupted by duplicate login",
            400: "Invalid credentials",
            401: "Account disabled",
            402: "Permission denied",
            403: "2FA required",
            404: "Failed to authenticate with 2FA"
        }
        return error_descriptions.get(error_code, "Unknown error code")
        
    def _check_tcp_connection(self) -> bool:
        """Проверка базового TCP-соединения с Synology NAS"""
        try:
            socket_obj = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            socket_obj.settimeout(SYNOLOGY_TIMEOUT)
            result = socket_obj.connect_ex((SYNOLOGY_HOST, SYNOLOGY_PORT))
            socket_obj.close()
            
            return result == 0
        except socket.error as e:
            logger.error(f"Socket error during connection check: {str(e)}")
            return False
        except Exception as e:
            logger.error(f"Unexpected error during connection check: {str(e)}")
            return False
            
    def is_online(self, force_check=False) -> bool:
        """Проверка онлайн-статуса Synology NAS"""
        # Используем кэшированное значение, если доступно и не устарело
        current_time = time.time()
        if not force_check and (current_time - self._last_online_check) < self._online_check_interval:
            logger.debug(f"Using cached online status: {self._last_online_status}")
            return self._last_online_status
            
        logger.info("Checking if NAS is online...")
        
        # Проверяем TCP-соединение
        online_status = self._check_tcp_connection()
        logger.info(f"Detected Synology NAS online status: {online_status}")
        
        # Если TCP-соединение успешно и у нас есть действующий SID,
        # попробуем более детальную проверку через API
        if online_status and self.sid:
            logger.info("Trying to fetch more detailed online status through API...")
            try:
                url = f"{self.base_url}/entry.cgi"
                params = {
                    "api": "SYNO.DSM.Info",
                    "version": "1",
                    "method": "getinfo",
                    "sid": self.sid
                }
                
                response = self.session.get(
                    url, 
                    params=params, 
                    timeout=self.default_timeout, 
                    verify=False
                )
                
                if response.status_code == 200:
                    data = response.json()
                    if data.get("success"):
                        logger.info("API request successful for getinfo")
                        logger.info("Synology NAS is online with API access")
                    else:
                        logger.warning("API response indicates an error, but NAS is reachable")
                        logger.debug(f"API error: {data.get('error', {}).get('code', -1)}")
                else:
                    logger.warning(f"API returned status code {response.status_code}")
            except Exception as e:
                logger.warning(f"API check failed, but TCP connection succeeded: {str(e)}")
        
        # Обновляем кэшированное значение
        self._last_online_check = current_time
        self._last_online_status = online_status
        
        return online_status
    
    def wake_on_lan(self) -> bool:
        """Отправка Wake-on-LAN пакета для включения Synology NAS"""
        if not SYNOLOGY_MAC:
            logger.error("MAC address not configured")
            return False
            
        try:
            # Преобразование MAC-адреса в байты
            mac_address = SYNOLOGY_MAC.replace(':', '').replace('-', '')
            if len(mac_address) != 12:
                logger.error(f"Invalid MAC address format: {SYNOLOGY_MAC}")
                return False
                
            try:
                mac_bytes = bytes.fromhex(mac_address)
            except ValueError as e:
                logger.error(f"Failed to parse MAC address: {str(e)}")
                logger.error(f"MAC address must contain only hex characters: {SYNOLOGY_MAC}")
                return False
            
            # Создание Magic Packet
            magic_packet = b'\xff' * 6 + mac_bytes * 16
            
            # Отправка пакета на конкретный адрес
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
                sock.sendto(magic_packet, (SYNOLOGY_HOST, WOL_PORT))
                sock.close()
                logger.info(f"Wake-on-LAN packet sent to {SYNOLOGY_MAC} at {SYNOLOGY_HOST}:{WOL_PORT}")
            except Exception as e:
                logger.error(f"Error sending directed WoL packet: {str(e)}")
                return False
                
            # Для надежности отправляем также широковещательный пакет
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
                
                # Используем стандартный широковещательный адрес
                broadcast_addr = "255.255.255.255"
                sock.sendto(magic_packet, (broadcast_addr, WOL_PORT))
                sock.close()
                logger.info(f"Wake-on-LAN broadcast packet sent to {broadcast_addr}:{WOL_PORT}")
            except Exception as e:
                logger.warning(f"Error sending broadcast WoL packet (non-critical): {str(e)}")
                # Не считаем ошибкой, т.к. основной пакет уже отправлен
                
            return True
            
        except Exception as e:
            logger.error(f"Unexpected error in wake_on_lan: {str(e)}")
            return False
            
    def wait_for_boot(self, max_attempts: int = 30, delay: int = 10) -> bool:
        """Ожидание загрузки Synology NAS"""
        logger.info(f"Waiting for Synology NAS to boot (timeout: {max_attempts * delay}s)...")
        
        for attempt in range(max_attempts):
            # Принудительно проверяем статус без использования кэша
            if self.is_online(force_check=True):
                logger.info(f"Synology NAS is online after {attempt + 1} attempts ({(attempt + 1) * delay}s)")
                
                # Проверяем, что не только сеть доступна, но и API загрузился
                api_ready = False
                logger.info("Waiting for API services to initialize...")
                
                for api_check in range(5):  # Даем еще до 50 секунд для загрузки API
                    if self.sid or self.login():
                        api_ready = True
                        logger.info(f"API services are ready after {api_check + 1} attempts")
                        break
                    logger.debug(f"API not ready yet, waiting... ({api_check + 1}/5)")
                    sleep(10)
                
                if not api_ready:
                    logger.warning("System is online but API services may not be fully initialized")
                    
                # Дадим дополнительное время для полной загрузки всех сервисов
                sleep(delay)
                return True
                
            sleep(delay)
            logger.info(f"Waiting for boot... Attempt {attempt + 1}/{max_attempts}")
            
        logger.error(f"Synology NAS didn't come online after {max_attempts * delay} seconds")
        return False
        
    def power_on(self) -> bool:
        """Включение Synology NAS"""
        # Принудительная проверка статуса
        if self.is_online(force_check=True):
            logger.info("Synology NAS is already online")
            return True
        
        logger.info("Powering on Synology NAS via Wake-on-LAN...")
        
        # Проверяем, настроен ли MAC-адрес
        if not SYNOLOGY_MAC:
            logger.error("Cannot power on: MAC address not configured in settings")
            return False
            
        # Пробуем отправить несколько WoL пакетов для надежности
        success = False
        for attempt in range(3):
            logger.debug(f"Sending WoL packet, attempt {attempt + 1}/3")
            if self.wake_on_lan():
                success = True
                break
            sleep(1)
            
        if not success:
            logger.error("Failed to send Wake-on-LAN packets")
            return False
        
        # Ожидание загрузки
        logger.info("WoL packets sent successfully, waiting for system to boot...")
        boot_result = self.wait_for_boot(max_attempts=30, delay=10)
        
        if boot_result:
            # Проверяем доступность API после загрузки
            system_status = self.get_system_status()
            if system_status.get("status") == "online":
                logger.info("System booted successfully with API access")
                return True
            else:
                logger.warning("System appears to be online but API may not be fully ready")
                return True
        else:
            logger.error("System did not come online after WoL")
            return False
        
    def power_off(self) -> bool:
        """Выключение Synology NAS"""
        if not self.is_online(force_check=True):
            logger.info("Synology NAS is already offline")
            return True
        
        logger.info("Powering off Synology NAS...")
        result = self.shutdown_system()
        
        if result:
            # Дополнительная проверка, что система действительно выключилась
            logger.info("Verifying system is offline...")
            for attempt in range(12):  # Проверяем в течение 2 минут (12 * 10 сек)
                if not self.is_online(force_check=True):
                    logger.info(f"System confirmed offline after {attempt * 10} seconds")
                    return True
                logger.debug(f"System still shutting down, checking again... ({attempt + 1}/12)")
                sleep(10)
                
            logger.warning("System still appears to be online after shutdown command")
            return False
        else:
            logger.error("Failed to initiate shutdown")
            return False
        
    # Заглушки для расширенных методов
    def get_shared_folders(self) -> List[Dict[str, Any]]:
        """Получение списка общих папок (заглушка)"""
        logger.warning("Function get_shared_folders() is not implemented yet")
        return []
        
    def get_system_load(self) -> Dict[str, Any]:
        """Получение информации о загрузке системы (заглушка)"""
        logger.warning("Function get_system_load() is not implemented yet")
        return {}
        
    def get_storage_status(self) -> Dict[str, Any]:
        """Получение подробной информации о хранилище (заглушка)"""
        logger.warning("Function get_storage_status() is not implemented yet")
        
        # Аутентифицируемся перед запросом данных
        if not self.sid and not self.login():
            logger.error("Failed to authenticate for storage status request")
            return {"error": "authentication_failed"}
            
        try:
            # Здесь будет реализация после добавления соответствующего API
            url = f"{self.base_url}/entry.cgi"
            params = {
                "api": "SYNO.Storage.CGI.Storage",
                "version": "1",
                "method": "load_info",
                "sid": self.sid
            }
            
            # В текущей версии просто возвращаем заглушку
            return {
                "volumes": [],
                "disks": [],
                "total_size": 0,
                "total_used": 0,
                "error": "not_implemented"
            }
        except Exception as e:
            logger.error(f"Error in get_storage_status: {str(e)}")
            return {"error": str(e)}
        
    def get_security_status(self) -> Dict[str, Any]:
        """Получение информации о состоянии безопасности (заглушка)"""
        logger.warning("Function get_security_status() is not implemented yet")
        
        # Аутентифицируемся перед запросом данных
        if not self.sid and not self.login():
            logger.error("Failed to authenticate for security status request")
            return {"success": False, "error": "authentication_failed"}
            
        try:
            # Здесь будет реализация после добавления соответствующего API
            url = f"{self.base_url}/entry.cgi"
            params = {
                "api": "SYNO.Core.SecurityScan.Status",
                "version": "1",
                "method": "get",
                "sid": self.sid
            }
            
            # В текущей версии просто возвращаем заглушку
            return {
                "success": False,
                "status": "not_implemented",
                "last_check": None,
                "is_secure": False,
                "error": "not_implemented"
            }
        except Exception as e:
            logger.error(f"Error in get_security_status: {str(e)}")
            return {"success": False, "error": str(e)}
