"""Alert rule engine."""

from decimal import Decimal
from typing import Dict, Optional, Callable, List
from datetime import datetime
from sqlalchemy.orm import Session
from src.core.database import get_database, Alert
from src.core.logger import get_logger
from .channels import AlertChannel

logger = get_logger(__name__)


class AlertEngine:
    """Alert rule engine."""
    
    def __init__(self):
        """Initialize alert engine."""
        self.db = get_database()
        self.logger = get_logger(__name__)
        self.channel = AlertChannel()
        self._active_alerts: Dict[int, Dict] = {}
    
    def evaluate_price_alert(
        self,
        alert_id: int,
        symbol: str,
        current_price: Decimal
    ) -> bool:
        """Evaluate price alert.
        
        Args:
            alert_id: Alert ID
            symbol: Trading symbol
            current_price: Current price
            
        Returns:
            True if alert should trigger
        """
        session = self.db.get_session()
        try:
            alert = session.query(Alert).filter_by(id=alert_id).first()
            if not alert or not alert.enabled:
                return False
            
            condition = alert.condition
            alert_type = condition.get('type')
            threshold = Decimal(str(condition.get('threshold', 0)))
            operator = condition.get('operator', '>')  # >, <, >=, <=
            
            if alert_type == 'price_above':
                return current_price > threshold
            elif alert_type == 'price_below':
                return current_price < threshold
            elif alert_type == 'price_change':
                # Would need previous price
                return False
            
            return False
        finally:
            session.close()
    
    def evaluate_indicator_alert(
        self,
        alert_id: int,
        indicator_value: float
    ) -> bool:
        """Evaluate indicator alert.
        
        Args:
            alert_id: Alert ID
            indicator_value: Current indicator value
            
        Returns:
            True if alert should trigger
        """
        session = self.db.get_session()
        try:
            alert = session.query(Alert).filter_by(id=alert_id).first()
            if not alert or not alert.enabled:
                return False
            
            condition = alert.condition
            threshold = float(condition.get('threshold', 0))
            operator = condition.get('operator', '>')
            
            if operator == '>':
                return indicator_value > threshold
            elif operator == '<':
                return indicator_value < threshold
            elif operator == 'crosses_above':
                # Would need previous value
                return False
            elif operator == 'crosses_below':
                # Would need previous value
                return False
            
            return False
        finally:
            session.close()
    
    def trigger_alert(self, alert_id: int, message: str):
        """Trigger an alert.
        
        Args:
            alert_id: Alert ID
            message: Alert message
        """
        session = self.db.get_session()
        try:
            alert = session.query(Alert).filter_by(id=alert_id).first()
            if not alert:
                return
            
            alert.triggered = True
            alert.triggered_at = datetime.utcnow()
            session.commit()
            
            # Send notification
            self.channel.send(alert.alert_type, message)
            logger.info(f"Alert {alert_id} triggered: {message}")
        except Exception as e:
            session.rollback()
            logger.error(f"Failed to trigger alert {alert_id}: {e}")
        finally:
            session.close()


# Global alert engine
_alert_engine: Optional[AlertEngine] = None


def get_alert_engine() -> AlertEngine:
    """Get global alert engine instance."""
    global _alert_engine
    if _alert_engine is None:
        _alert_engine = AlertEngine()
    return _alert_engine

