"""
Alert Manager
Central manager for handling alerts and conditions
"""

import threading
import logging
from typing import List, Optional, Dict
from datetime import datetime

from hyperliquid_monitor_plus.core_types import Trade
from hyperliquid_monitor_plus.alerts.types import AlertCondition, Alert, AlertCallback
from hyperliquid_monitor_plus.alerts.filters import TradeFilter

logger = logging.getLogger(__name__)


class AlertManager:
    """
    Manages alert conditions and triggers alerts when conditions are met
    Thread-safe for use with WebSocket callbacks
    """
    
    def __init__(self, alert_callback: Optional[AlertCallback] = None):
        """
        Initialize the alert manager
        
        Args:
            alert_callback: Optional callback function that will be called when an alert is triggered
        """
        self._conditions: Dict[str, AlertCondition] = {}
        self._alert_callback = alert_callback
        self._lock = threading.Lock()
        self._alerts_history: List[Alert] = []
        self._max_history = 1000  # Keep last 1000 alerts
        
    def add_condition(self, condition: AlertCondition) -> None:
        """
        Add an alert condition
        
        Args:
            condition: The alert condition to add
            
        Raises:
            ValueError: If a condition with the same name already exists
        """
        with self._lock:
            if condition.name in self._conditions:
                raise ValueError(f"Alert condition '{condition.name}' already exists")
            
            self._conditions[condition.name] = condition
            logger.info(f"Added alert condition: {condition.name} (type: {condition.alert_type}, level: {condition.level})")
    
    def remove_condition(self, name: str) -> bool:
        """
        Remove an alert condition by name
        
        Args:
            name: Name of the condition to remove
            
        Returns:
            True if condition was removed, False if not found
        """
        with self._lock:
            if name in self._conditions:
                del self._conditions[name]
                logger.info(f"Removed alert condition: {name}")
                return True
            return False
    
    def update_condition(self, name: str, **kwargs) -> bool:
        """
        Update an existing alert condition
        
        Args:
            name: Name of the condition to update
            **kwargs: Fields to update
            
        Returns:
            True if condition was updated, False if not found
        """
        with self._lock:
            if name not in self._conditions:
                return False
            
            condition = self._conditions[name]
            
            # Update allowed fields
            allowed_fields = {'enabled', 'level', 'min_volume_usd', 'max_volume_usd', 
                            'coins', 'sides', 'addresses', 'message_template'}
            
            for key, value in kwargs.items():
                if key in allowed_fields:
                    setattr(condition, key, value)
            
            logger.info(f"Updated alert condition: {name}")
            return True
    
    def enable_condition(self, name: str) -> bool:
        """Enable a condition"""
        return self.update_condition(name, enabled=True)
    
    def disable_condition(self, name: str) -> bool:
        """Disable a condition"""
        return self.update_condition(name, enabled=False)
    
    def get_condition(self, name: str) -> Optional[AlertCondition]:
        """Get a condition by name"""
        with self._lock:
            return self._conditions.get(name)
    
    def list_conditions(self) -> List[AlertCondition]:
        """Get all conditions"""
        with self._lock:
            return list(self._conditions.values())
    
    def check_trade(self, trade: Trade) -> List[Alert]:
        """
        Check a trade against all conditions and trigger alerts
        This is the main method called by the monitor
        
        Args:
            trade: The trade to check
            
        Returns:
            List of triggered alerts
        """
        triggered_alerts = []
        
        with self._lock:
            conditions = list(self._conditions.values())
        
        # Check each condition
        for condition in conditions:
            if not condition.enabled:
                continue
            
            if TradeFilter.matches_condition(trade, condition):
                # Create alert
                alert = TradeFilter.create_alert(trade, condition)
                triggered_alerts.append(alert)
                
                # Update trigger count
                with self._lock:
                    condition.triggered_count += 1
                
                # Add to history
                self._add_to_history(alert)
                
                # Call callback if provided
                if self._alert_callback:
                    try:
                        self._alert_callback(alert)
                    except Exception as e:
                        logger.error(f"Error in alert callback: {e}", exc_info=True)
        
        return triggered_alerts
    
    def _add_to_history(self, alert: Alert) -> None:
        """Add alert to history (thread-safe)"""
        with self._lock:
            self._alerts_history.append(alert)
            
            # Trim history if needed
            if len(self._alerts_history) > self._max_history:
                self._alerts_history = self._alerts_history[-self._max_history:]
    
    def get_history(self, limit: Optional[int] = None) -> List[Alert]:
        """
        Get alert history
        
        Args:
            limit: Maximum number of alerts to return (most recent first)
            
        Returns:
            List of alerts
        """
        with self._lock:
            history = list(reversed(self._alerts_history))
            if limit:
                return history[:limit]
            return history
    
    def get_statistics(self) -> Dict:
        """
        Get statistics about alerts
        
        Returns:
            Dictionary with statistics
        """
        with self._lock:
            total_conditions = len(self._conditions)
            enabled_conditions = sum(1 for c in self._conditions.values() if c.enabled)
            total_triggered = sum(c.triggered_count for c in self._conditions.values())
            
            # Group by type
            by_type = {}
            for condition in self._conditions.values():
                alert_type = condition.alert_type
                if alert_type not in by_type:
                    by_type[alert_type] = {"count": 0, "triggered": 0}
                by_type[alert_type]["count"] += 1
                by_type[alert_type]["triggered"] += condition.triggered_count
            
            return {
                "total_conditions": total_conditions,
                "enabled_conditions": enabled_conditions,
                "disabled_conditions": total_conditions - enabled_conditions,
                "total_triggered": total_triggered,
                "total_alerts_in_history": len(self._alerts_history),
                "by_type": by_type
            }
    
    def clear_history(self) -> None:
        """Clear alert history"""
        with self._lock:
            self._alerts_history.clear()
            logger.info("Alert history cleared")
    
    def clear_all_conditions(self) -> None:
        """Remove all conditions"""
        with self._lock:
            self._conditions.clear()
            logger.info("All alert conditions cleared")
