"""
Alert Filtering System
Implements filters to check if a trade matches alert conditions
"""

from typing import Optional
from hyperliquid_monitor_plus.core_types import Trade
from hyperliquid_monitor_plus.alerts.types import AlertCondition, Alert


class TradeFilter:
    """
    Filters trades based on alert conditions
    Thread-safe and stateless
    """
    
    @staticmethod
    def matches_condition(trade: Trade, condition: AlertCondition) -> bool:
        """
        Check if a trade matches an alert condition
        
        Args:
            trade: The trade to check
            condition: The alert condition to match against
            
        Returns:
            True if trade matches the condition, False otherwise
        """
        # Skip disabled conditions
        if not condition.enabled:
            return False
        
        # Check address filter
        if condition.addresses:
            if trade.address.lower() not in condition.addresses:
                return False
        
        # Apply type-specific filters
        if condition.alert_type == "VOLUME":
            return TradeFilter._check_volume(trade, condition)
        elif condition.alert_type == "COIN":
            return TradeFilter._check_coin(trade, condition)
        elif condition.alert_type == "SIDE":
            return TradeFilter._check_side(trade, condition)
        elif condition.alert_type == "CUSTOM":
            return TradeFilter._check_custom(trade, condition)
        
        return False
    
    @staticmethod
    def _check_volume(trade: Trade, condition: AlertCondition) -> bool:
        """Check if trade volume matches condition"""
        volume_usd = trade.size * trade.price
        
        if condition.min_volume_usd is not None and volume_usd < condition.min_volume_usd:
            return False
        
        if condition.max_volume_usd is not None and volume_usd > condition.max_volume_usd:
            return False
        
        return True
    
    @staticmethod
    def _check_coin(trade: Trade, condition: AlertCondition) -> bool:
        """Check if trade coin matches condition"""
        if not condition.coins:
            return False
        
        return trade.coin.upper() in condition.coins
    
    @staticmethod
    def _check_side(trade: Trade, condition: AlertCondition) -> bool:
        """Check if trade side matches condition"""
        if not condition.sides:
            return False
        
        return trade.side in condition.sides
    
    @staticmethod
    def _check_custom(trade: Trade, condition: AlertCondition) -> bool:
        """Check custom filter function"""
        if not condition.custom_filter:
            return False
        
        try:
            return condition.custom_filter(trade)
        except Exception:
            # If custom filter fails, don't trigger alert
            return False
    
    @staticmethod
    def create_alert(trade: Trade, condition: AlertCondition) -> Alert:
        """
        Create an Alert object from a trade and condition
        
        Args:
            trade: The trade that triggered the alert
            condition: The condition that was matched
            
        Returns:
            Alert object
        """
        # Generate message
        message = TradeFilter._generate_message(trade, condition)
        
        return Alert(
            condition_name=condition.name,
            alert_type=condition.alert_type,
            level=condition.level,
            trade=trade,
            message=message
        )
    
    @staticmethod
    def _generate_message(trade: Trade, condition: AlertCondition) -> str:
        """Generate alert message"""
        # Use custom template if provided
        if condition.message_template:
            try:
                return condition.message_template.format(
                    coin=trade.coin,
                    side=trade.side,
                    size=trade.size,
                    price=trade.price,
                    volume_usd=trade.size * trade.price,
                    address=trade.address,
                    fee=trade.fee or 0,
                    closed_pnl=trade.closed_pnl or 0
                )
            except (KeyError, ValueError):
                # Fall back to default if template formatting fails
                pass
        
        # Default message based on alert type
        volume_usd = trade.size * trade.price
        
        if condition.alert_type == "VOLUME":
            return (
                f"Large {trade.side} detected: {trade.coin} "
                f"${volume_usd:,.2f} ({trade.size} @ ${trade.price:,.2f})"
            )
        elif condition.alert_type == "COIN":
            return (
                f"{trade.coin} {trade.side}: {trade.size} @ ${trade.price:,.2f} "
                f"(${volume_usd:,.2f})"
            )
        elif condition.alert_type == "SIDE":
            return (
                f"{trade.side} signal: {trade.coin} {trade.size} @ ${trade.price:,.2f} "
                f"(${volume_usd:,.2f})"
            )
        else:  # CUSTOM
            return (
                f"Custom alert triggered: {trade.coin} {trade.side} "
                f"${volume_usd:,.2f}"
            )


class AlertFilter:
    """
    Higher-level alert filtering system
    Extends TradeFilter with advanced alert-specific filtering
    """
    
    @staticmethod
    def should_alert(trade: Trade, conditions: list[AlertCondition]) -> bool:
        """
        Determine if a trade should trigger any alert
        
        Args:
            trade: The trade to check
            conditions: List of alert conditions to check against
            
        Returns:
            True if any condition matches, False otherwise
        """
        return any(TradeFilter.matches_condition(trade, condition) for condition in conditions)
    
    @staticmethod
    def filter_alerts(trade: Trade, conditions: list[AlertCondition]) -> list[AlertCondition]:
        """
        Filter which alert conditions match a trade
        
        Args:
            trade: The trade to check
            conditions: List of alert conditions to check
            
        Returns:
            List of matching alert conditions
        """
        return [condition for condition in conditions if TradeFilter.matches_condition(trade, condition)]


# Export the AlertFilter class for compatibility
__all__ = ['TradeFilter', 'AlertFilter']
