"""
SDK Adapter for Hyperliquid Monitor Plus - Version Compatible

This module provides a compatibility layer to handle different SDK versions
and avoid direct imports that could cause version conflicts.
"""

import warnings
from typing import Optional, Any, Dict
import logging

logger = logging.getLogger(__name__)

# Global SDK instance cache
_sdk_cache: Dict[str, Any] = {}
_sdk_version: Optional[str] = None
_sdk_available = False

# Export SDK_AVAILABLE for compatibility  
SDK_AVAILABLE = False  # Set to False by default, will be updated during initialization

def _detect_sdk_version() -> str:
    """
    Detect the available SDK version and return version string.
    
    Returns:
        str: SDK version ("v1", "v2", or "unknown")
    """
    global _sdk_version, _sdk_available
    
    if _sdk_version is not None:
        return _sdk_version
    
    # Try to import SDK v2 (newer)
    try:
        from hyperliquid import info as info_module_v2
        _sdk_version = "v2"
        _sdk_available = True
        logger.debug("Detected Hyperliquid SDK v2")
        return "v2"
    except ImportError:
        pass
    
    # Try to import SDK v1 (older)
    try:
        from hyperliquid.info import Info
        _sdk_version = "v1"
        _sdk_available = True
        logger.debug("Detected Hyperliquid SDK v1")
        return "v1"
    except ImportError:
        pass
    
    # No SDK found
    _sdk_version = "unknown"
    _sdk_available = False
    logger.debug("Hyperliquid SDK not found - functionality will be limited")
    return "unknown"


class HyperliquidSDKAdapter:
    """
    Version-aware adapter for Hyperliquid SDK functionality.
    Automatically handles different SDK versions.
    """
    
    def __init__(self, use_testnet: bool = False, custom_api_url: Optional[str] = None, timeout: Optional[float] = None):
        """
        Initialize the SDK adapter with version detection.
        
        Args:
            use_testnet: If True, use testnet API URL
            custom_api_url: Custom API URL to use instead of default
            timeout: Request timeout in seconds
        """
        self.use_testnet = use_testnet
        self.custom_api_url = custom_api_url
        self.timeout = timeout
        self._info = None
        self._api = None
        
        # Detect SDK version
        self.sdk_version = _detect_sdk_version()
        if self.sdk_version == "unknown":
            warnings.warn("Hyperliquid SDK not available. Some features may not work.", UserWarning)
    
    @property
    def info(self):
        """Get or create Info instance (lazy import)"""
        if self._info is None and _sdk_available:
            try:
                if self.sdk_version == "v2":
                    # Try new v2 API first
                    if self.custom_api_url:
                        self._info = self._info_v2(url=self.custom_api_url, timeout=self.timeout)
                    elif self.use_testnet:
                        self._info = self._info_v2(url="https://api.hyperliquid.xyz/info/testnet", timeout=self.timeout)
                    else:
                        self._info = self._info_v2(timeout=self.timeout)
                else:
                    # Fall back to v1 API
                    if self.custom_api_url:
                        self._info = self._info_v1(base_url=self.custom_api_url, timeout=self.timeout)
                    elif self.use_testnet:
                        self._info = self._info_v1(base_url="https://api.hyperliquid.xyz/info/testnet", timeout=self.timeout)
                    else:
                        self._info = self._info_v1(timeout=self.timeout)
                        
            except Exception as e:
                logger.error(f"Failed to initialize Info: {e}")
                raise RuntimeError(f"Could not initialize Hyperliquid SDK: {e}")
        
        return self._info
    
    def _info_v2(self, url: Optional[str] = None, timeout: Optional[float] = None):
        """Create Info instance using v2 API"""
        try:
            # v2 might have different constructor signature
            if url and timeout:
                return self._create_info_v2(url=url, timeout=timeout)
            elif url:
                return self._create_info_v2(url=url)
            elif timeout:
                return self._create_info_v2(timeout=timeout)
            else:
                return self._create_info_v2()
        except Exception as e:
            logger.warning(f"v2 API failed, trying v1: {e}")
            return self._info_v1(base_url=url, timeout=timeout)
    
    def _create_info_v2(self, **kwargs):
        """Create Info instance using v2 import path"""
        try:
            from hyperliquid import info as info_module
            if hasattr(info_module, 'Info'):
                return info_module.Info(**kwargs)
            elif 'url' in kwargs:
                return info_module.Info(base_url=kwargs['url'], timeout=kwargs.get('timeout'))
            else:
                return info_module.Info(**kwargs)
        except AttributeError:
            # Module exists but no Info class - try different approach
            raise ImportError("v2 API structure not recognized")
    
    def _info_v1(self, base_url: Optional[str] = None, timeout: Optional[float] = None):
        """Create Info instance using v1 API"""
        try:
            from hyperliquid.info import Info
            
            # v1 constructor signature
            if base_url:
                if timeout:
                    return Info(base_url=base_url, timeout=timeout)
                else:
                    return Info(base_url=base_url)
            else:
                if timeout:
                    return Info(timeout=timeout)
                else:
                    return Info()
                    
        except Exception as e:
            logger.error(f"v1 API also failed: {e}")
            raise RuntimeError(f"Could not initialize any SDK version: {e}")
    
    @property
    def api(self):
        """Get or create API instance for advanced operations"""
        if self._api is None and _sdk_available:
            try:
                if self.sdk_version == "v2":
                    from hyperliquid.api import API as API_v2
                    base_url = self.custom_api_url or ("https://api.hyperliquid.xyz/info/testnet" if self.use_testnet else "https://api.hyperliquid.xyz/info")
                    self._api = API_v2(base_url=base_url, timeout=self.timeout)
                else:
                    from hyperliquid.api import API as API_v1
                    base_url = self.custom_api_url or ("https://api.hyperliquid.xyz/info/testnet" if self.use_testnet else "https://api.hyperliquid.xyz/info")
                    self._api = API_v1(base_url=base_url, timeout=self.timeout)
            except Exception as e:
                logger.error(f"Failed to initialize API: {e}")
                raise RuntimeError(f"Could not initialize API: {e}")
        
        return self._api


def get_info(use_testnet: bool = False, custom_api_url: Optional[str] = None, timeout: Optional[float] = None):
    """
    Get Info instance with specified parameters and version compatibility.
    
    Args:
        use_testnet: If True, use testnet API URL
        custom_api_url: Custom API URL to use instead of default
        timeout: Request timeout in seconds
        
    Returns:
        Info: Hyperliquid Info instance
        
    Raises:
        RuntimeError: If SDK is not available or initialization fails
    """
    adapter = HyperliquidSDKAdapter(
        use_testnet=use_testnet, 
        custom_api_url=custom_api_url, 
        timeout=timeout
    )
    return adapter.info


def get_api(use_testnet: bool = False, custom_api_url: Optional[str] = None, timeout: Optional[float] = None):
    """
    Get API instance for advanced operations.
    
    Args:
        use_testnet: If True, use testnet API URL
        custom_api_url: Custom API URL to use instead of default
        timeout: Request timeout in seconds
        
    Returns:
        API: Hyperliquid API instance
    """
    adapter = HyperliquidSDKAdapter(
        use_testnet=use_testnet, 
        custom_api_url=custom_api_url, 
        timeout=timeout
    )
    return adapter.api


def get_api_url(use_testnet: bool = False, custom_api_url: Optional[str] = None) -> str:
    """
    Get API URL constant with fallback support.
    
    Args:
        use_testnet: If True, use testnet API URL
        custom_api_url: Custom API URL to use instead of default
        
    Returns:
        str: API URL constant
    """
    if custom_api_url:
        return custom_api_url
    elif use_testnet:
        return "https://api.hyperliquid.xyz/info/testnet"
    else:
        return "https://api.hyperliquid.xyz/info"


def get_constants():
    """
    Get constants module with fallback support.
    
    Returns:
        module: hyperliquid.utils.constants or fallback constants
    """
    try:
        from hyperliquid.utils import constants
        return constants
    except ImportError:
        # Fallback constants with multiple format support
        class constants:
            # Try different URL formats
            MAINNET_API_URL = "https://api.hyperliquid.xyz/info"
            MAINNET_BASE_URL = "https://api.hyperliquid.xyz"
            TESTNET_API_URL = "https://api.hyperliquid.xyz/info/testnet"
            TESTNET_BASE_URL = "https://api.hyperliquid.xyz"
            
            # Additional constants that might be needed
            WS_BASE_URL = "wss://api.hyperliquid.xyz"
            WS_TESTNET_URL = "wss://api.hyperliquid.xyz"
        
        logger.debug("Using fallback constants (SDK not available)")
        return constants


def get_sdk_version() -> str:
    """
    Get the detected SDK version.
    
    Returns:
        str: SDK version ("v1", "v2", or "unknown")
    """
    return _detect_sdk_version()


def check_sdk_availability() -> Dict[str, Any]:
    """
    Check SDK availability and version information.
    
    Returns:
        Dict with SDK status and version info
    """
    version = _detect_sdk_version()
    return {
        "available": _sdk_available,
        "version": version,
        "ready": _sdk_available and version != "unknown"
    }