"""
Alert System Type Definitions
Defines types and data structures for the smart alert system
"""

from dataclasses import dataclass, field
from typing import Optional, Literal, Callable, List, Any
from datetime import datetime
from hyperliquid_monitor_plus.core_types import Trade, TradeSide

AlertLevel = Literal["INFO", "WARNING", "CRITICAL"]
AlertType = Literal["VOLUME", "COIN", "SIDE", "CUSTOM"]


@dataclass
class AlertCondition:
    """
    Defines a condition that triggers an alert
    """
    # Alert metadata
    name: str
    alert_type: AlertType
    level: AlertLevel = "INFO"
    enabled: bool = True
    
    # Volume-based conditions (for VOLUME type)
    min_volume_usd: Optional[float] = None
    max_volume_usd: Optional[float] = None
    
    # Coin-based conditions (for COIN type)
    coins: Optional[List[str]] = None  # e.g., ["BTC", "ETH"]
    
    # Side-based conditions (for SIDE type)
    sides: Optional[List[TradeSide]] = None  # e.g., ["BUY"] or ["SELL"] or both
    
    # Address filtering
    addresses: Optional[List[str]] = None  # If None, applies to all addresses
    
    # Custom condition function (for CUSTOM type)
    custom_filter: Optional[Callable[[Trade], bool]] = None
    
    # Alert message customization
    message_template: Optional[str] = None
    
    # Metadata
    created_at: datetime = field(default_factory=datetime.now)
    triggered_count: int = 0
    
    def __post_init__(self):
        """Validate alert condition after initialization"""
        if self.alert_type == "VOLUME" and self.min_volume_usd is None and self.max_volume_usd is None:
            raise ValueError("VOLUME alert requires at least min_volume_usd or max_volume_usd")
        
        if self.alert_type == "COIN" and not self.coins:
            raise ValueError("COIN alert requires a list of coins")
        
        if self.alert_type == "SIDE" and not self.sides:
            raise ValueError("SIDE alert requires a list of sides")
        
        if self.alert_type == "CUSTOM" and self.custom_filter is None:
            raise ValueError("CUSTOM alert requires a custom_filter function")
        
        # Normalize coin symbols to uppercase
        if self.coins:
            self.coins = [coin.upper() for coin in self.coins]
        
        # Normalize addresses to lowercase
        if self.addresses:
            self.addresses = [addr.lower() for addr in self.addresses]


@dataclass
class Alert:
    """
    Represents a triggered alert with trade information
    """
    condition_name: str
    alert_type: AlertType
    level: AlertLevel
    trade: Trade
    message: str
    timestamp: datetime = field(default_factory=datetime.now)
    
    def __str__(self) -> str:
        """Human-readable alert representation"""
        return (
            f"[{self.level}] {self.condition_name}\n"
            f"  {self.message}\n"
            f"  Trade: {self.trade.coin} {self.trade.side} "
            f"${self.trade.size * self.trade.price:.2f} @ ${self.trade.price:.2f}\n"
            f"  Time: {self.timestamp.strftime('%Y-%m-%d %H:%M:%S')}"
        )
    
    def to_dict(self) -> dict:
        """Convert alert to dictionary for serialization"""
        return {
            "condition_name": self.condition_name,
            "alert_type": self.alert_type,
            "level": self.level,
            "message": self.message,
            "timestamp": self.timestamp.isoformat(),
            "trade": {
                "coin": self.trade.coin,
                "side": self.trade.side,
                "size": self.trade.size,
                "price": self.trade.price,
                "volume_usd": self.trade.size * self.trade.price,
                "address": self.trade.address,
                "timestamp": self.trade.timestamp.isoformat()
            }
        }


# Type alias for alert callbacks
AlertCallback = Callable[[Alert], None]

# Additional Type alias for alert results
AlertResult = dict
