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

"""
Модуль для разрешения проблем с API Synology и автоматического выбора совместимых версий
"""

import logging
import requests
from typing import Dict, Any, Optional, List, Tuple

logger = logging.getLogger(__name__)

class ApiVersionResolver:
    """Класс для определения совместимых версий API и правильных методов"""
    
    def __init__(self, base_url: str, session: requests.Session, timeout: tuple = (10, 20)):
        """Инициализация класса ApiVersionResolver
        
        Args:
            base_url: Базовый URL API Synology NAS (например, http://192.168.0.102:5000/webapi)
            session: Сессия requests для повторного использования соединений
            timeout: Таймауты для запросов (connect_timeout, read_timeout)
        """
        self.base_url = base_url
        self.session = session
        self.timeout = timeout
        self.api_info_cache = {}
        
    def get_api_info(self, api_name: str) -> Dict[str, Any]:
        """Получает информацию об API из SYNO.API.Info
        
        Args:
            api_name: Имя API для запроса (например, SYNO.DSM.Info)
            
        Returns:
            Dict с информацией об API или пустой словарь в случае ошибки
        """
        # Проверяем наличие данных в кэше
        if api_name in self.api_info_cache:
            return self.api_info_cache[api_name]
            
        try:
            # Запрос информации об API
            api_info_url = f"{self.base_url}/entry.cgi"
            api_info_params = {
                "api": "SYNO.API.Info",
                "version": "1",
                "method": "query",
                "query": api_name
            }
            
            logger.debug(f"Querying API info for {api_name}")
            response = self.session.get(
                api_info_url,
                params=api_info_params,
                timeout=self.timeout,
                verify=False
            )
            
            if response.status_code != 200:
                logger.warning(f"API info request failed with status {response.status_code}")
                return {}
                
            data = response.json()
            if not data.get("success"):
                logger.warning(f"API info request unsuccessful for {api_name}")
                return {}
                
            # Извлекаем информацию о запрошенном API
            api_info = data.get("data", {}).get(api_name, {})
            if not api_info:
                logger.warning(f"API {api_name} not found in API info response")
                return {}
                
            # Кэшируем результат
            self.api_info_cache[api_name] = api_info
            logger.debug(f"API info for {api_name}: {api_info}")
            return api_info
            
        except Exception as e:
            logger.error(f"Error querying API info for {api_name}: {str(e)}")
            return {}
            
    def resolve_api_path(self, api_name: str) -> str:
        """Определяет путь для API
        
        Args:
            api_name: Имя API
            
        Returns:
            Путь к API или 'entry.cgi' по умолчанию
        """
        api_info = self.get_api_info(api_name)
        return api_info.get("path", "entry.cgi")
        
    def resolve_api_version(self, api_name: str, requested_version: int) -> int:
        """Определяет совместимую версию API
        
        Args:
            api_name: Имя API
            requested_version: Запрошенная версия API
            
        Returns:
            Совместимая версия API, которая будет работать
        """
        api_info = self.get_api_info(api_name)
        if not api_info:
            # Если нет информации, возвращаем запрошенную версию
            return requested_version
            
        min_version = api_info.get("minVersion", 1)
        max_version = api_info.get("maxVersion", requested_version)
        
        # Проверка, поддерживается ли запрошенная версия
        if requested_version < min_version:
            logger.warning(f"API version {requested_version} for {api_name} is below minimum {min_version}, using {min_version}")
            return min_version
        elif requested_version > max_version:
            logger.warning(f"API version {requested_version} for {api_name} exceeds maximum {max_version}, using {max_version}")
            return max_version
            
        return requested_version
        
    def resolve_api_method(self, api_name: str) -> Dict[str, str]:
        """Определяет доступные методы для API
        
        Args:
            api_name: Имя API
            
        Returns:
            Словарь с типами методов и их правильными именами для данного API
        """
        # Возможные методы для разных типов API
        api_methods = {
            # Методы для информации о системе
            "SYNO.DSM.Info": {"info": "getinfo", "get": "getinfo"},
            "SYNO.Core.System": {"info": "info", "get": "info"},
            "SYNO.Core.System.Status": {"info": "get", "get": "get"},
            "SYNO.Core.System.Info": {"info": "get", "get": "get"},
            
            # Методы для управления питанием
            "SYNO.Core.Hardware.PowerRecovery": {
                "restart": "setPowerOnState", 
                "reboot": "setPowerOnState",
                "shutdown": "setPowerOnState",
                "poweroff": "setPowerOnState"
            },
            "SYNO.Core.System.Power": {
                "restart": "restart", 
                "reboot": "restart",
                "shutdown": "shutdown",
                "poweroff": "shutdown"
            },
            "SYNO.DSM.Power": {
                "restart": "reboot", 
                "reboot": "reboot",
                "shutdown": "shutdown",
                "poweroff": "shutdown"
            },
            "SYNO.Core.Hardware.NeedReboot": {
                "restart": "reboot", 
                "reboot": "reboot"
            }
        }
        
        return api_methods.get(api_name, {})
        
    def get_api_special_params(self, api_name: str, method: str) -> Dict[str, Any]:
        """Возвращает специальные параметры, которые требуются для определенного API
        
        Args:
            api_name: Имя API
            method: Метод API
            
        Returns:
            Словарь с параметрами для метода или пустой словарь
        """
        # Специфические параметры для определенных API
        special_params = {
            # Параметры для управления питанием
            "SYNO.Core.Hardware.PowerRecovery": {
                "setPowerOnState": {
                    "restart": {"reboot": "true"},
                    "reboot": {"reboot": "true"},
                    "shutdown": {"state": "powerbtn"},
                    "poweroff": {"state": "powerbtn"}
                }
            },
            # Другие специальные параметры для других API
        }
        
        api_params = special_params.get(api_name, {})
        method_params = api_params.get(method, {})
        
        # Если это метод управления питанием, возвращаем соответствующие параметры
        if isinstance(method_params, dict) and method in method_params:
            return method_params[method]
            
        return method_params
        
    def find_compatible_api_for_function(self, function_type: str) -> List[Tuple[str, str, int]]:
        """Находит совместимые API для определенного типа функций
        
        Args:
            function_type: Тип функции ('info', 'power', 'status', etc.)
            
        Returns:
            Список кортежей (api_name, method, version) в порядке приоритета
        """
        # Определяем API для каждого типа функции
        function_apis = {
            "info": [
                ("SYNO.DSM.Info", "getinfo", 2),
                ("SYNO.Core.System", "info", 1),
                ("SYNO.Core.System.Status", "get", 1),
                ("SYNO.Core.System.Info", "get", 1)
            ],
            "power_restart": [
                ("SYNO.Core.Hardware.PowerRecovery", "setPowerOnState", 1),
                ("SYNO.Core.Hardware.NeedReboot", "reboot", 1),
                ("SYNO.Core.System.Power", "restart", 1),
                ("SYNO.DSM.Power", "reboot", 1),
                ("SYNO.Core.System", "reboot", 3)
            ],
            "power_shutdown": [
                ("SYNO.Core.Hardware.PowerRecovery", "setPowerOnState", 1),
                ("SYNO.Core.System.Power", "shutdown", 1),
                ("SYNO.DSM.Power", "shutdown", 1),
                ("SYNO.Core.System", "shutdown", 3)
            ]
        }
        
        return function_apis.get(function_type, [])
