"""
Type Adapters for Hyperliquid Monitor Plus

This module provides type conversion utilities to handle incompatibilities 
between hyperliquid-python-sdk and custom library types.
Uses lazy imports to avoid circular dependencies.
"""

from typing import Union, Literal, Optional, TYPE_CHECKING
import logging
import functools

logger = logging.getLogger(__name__)

# Type definitions that work even without SDK
TradeSide = Literal["BUY", "SELL"]

# SDK Side: "A" | "B" 
# Library TradeSide: "BUY" | "SELL"

@functools.lru_cache(maxsize=32)
def _get_sdk_side_type():
    """Lazy import of SDK Side type with caching for performance"""
    try:
        if TYPE_CHECKING:
            from hyperliquid.utils.types import Side as SdkSide
        else:
            from hyperliquid.utils.types import Side as SdkSide
            return SdkSide, True
    except ImportError:
        logger.debug("SDK not available, using string fallback")
        return str, False

def side_to_trade_side(side) -> TradeSide:
    """
    Convert SDK Side to Library TradeSide
    
    Args:
        side: SDK side value ("A" or "B") or any string if SDK not available
    
    Returns:
        TradeSide: Library trade side ("BUY" or "SELL")
    
    Raises:
        ValueError: If side is not "A" or "B"
    """
    # Handle both SDK and non-SDK side values
    if hasattr(side, 'value'):
        # Handle SDK enum/object
        side_val = str(side.value)
    else:
        # Handle string directly or any other type
        side_val = str(side)
    
    if side_val == "A":
        return "SELL"
    elif side_val == "B":
        return "BUY"
    else:
        raise ValueError(f"Invalid side value: {side_val}. Must be 'A' or 'B'")

def trade_side_to_side(trade_side: TradeSide) -> str:
    """
    Convert Library TradeSide to SDK Side
    
    Args:
        trade_side: Library trade side ("BUY" or "SELL")
    
    Returns:
        str: SDK side value ("A" or "B")
    
    Raises:
        ValueError: If trade_side is not "BUY" or "SELL"
    """
    if trade_side == "BUY":
        return "B"
    elif trade_side == "SELL":
        return "A"
    else:
        raise ValueError(f"Invalid trade_side value: {trade_side}. Must be 'BUY' or 'SELL'")

def is_buy_side(side: Union[str, TradeSide]) -> bool:
    """
    Check if a side represents a buy order
    
    Args:
        side: Any side type (SDK or Library)
    
    Returns:
        bool: True if buy, False if sell
    """
    return str(side) in ["B", "BUY"]

def is_sell_side(side: Union[str, TradeSide]) -> bool:
    """
    Check if a side represents a sell order
    
    Args:
        side: Any side type (SDK or Library)
    
    Returns:
        bool: True if sell, False if buy
    """
    return str(side) in ["A", "SELL"]

# Additional conversion helpers
def convert_trade_side_to_sdk(side: TradeSide) -> str:
    """
    Alias for trade_side_to_side for clarity
    """
    return trade_side_to_side(side)

def convert_sdk_side_to_trade(side) -> TradeSide:
    """
    Alias for side_to_trade_side for clarity
    """
    return side_to_trade_side(side)

def normalize_side(side) -> TradeSide:
    """
    Normalize any side value to Library TradeSide format
    
    Args:
        side: Any side format (SDK "A"/"B" or Library "BUY"/"SELL")
    
    Returns:
        TradeSide: Normalized library side
    """
    try:
        # Try to convert as SDK side first
        return side_to_trade_side(side)
    except ValueError:
        # If that fails, try to convert as trade side
        if side in ["BUY", "SELL"]:
            return side
        else:
            raise ValueError(f"Cannot normalize side value: {side}")

def validate_side_fast(side) -> bool:
    """
    Fast side validation without exceptions for performance-critical code
    
    Args:
        side: Any side value to validate
        
    Returns:
        bool: True if valid side, False otherwise
    """
    return str(side) in ["A", "B", "BUY", "SELL"]