"""
交易中断和紧急处理算法
============

提供多级紧急风险处置：
- 级别1：预警提示（不干预，只通知）
- 级别2：限制开仓（只允许平仓，不允许开仓）
- 级别3：逐步减仓（按比例逐步降低仓位）
- 级别4：紧急清仓（全部平仓，立即停止交易）
- 级别5：系统停机（整个交易系统停止运行）
"""
from typing import Dict, List, Optional, Callable, Tuple
from datetime import datetime
from dataclasses import dataclass
from enum import Enum
from risk_monitor import RiskAlert, AlertLevel, RealTimeRiskMonitor
from risk_calculator import RiskMetrics


class EmergencyLevel(Enum):
    """紧急级别"""
    NORMAL = "正常"
    ALERT = "预警"
    RESTRICT = "限制开仓"
    REDUCE = "逐步减仓"
    EMERGENCY = "紧急清仓"
    SHUTDOWN = "系统停机"


@dataclass
class EmergencyAction:
    """紧急行动"""
    action_id: str
    level: EmergencyLevel
    trigger_alert: RiskAlert
    timestamp: datetime
    description: str
    executed: bool = False
    result: str = ""
    
    def to_dict(self) -> Dict:
        return {
            'action_id': self.action_id,
            'level': self.level.value,
            'trigger_alert': self.trigger_alert.to_dict() if self.trigger_alert else None,
            'timestamp': self.timestamp.isoformat(),
            'description': self.description,
            'executed': self.executed,
            'result': self.result
        }


class EmergencyConfig:
    """紧急处理配置"""
    
    def __init__(self,
               critical_alerts_trigger_restrict: int = 1,
               reduce_position_pct: float = 0.3,
               max_reduce_steps: int = 3,
               critical_trigger_emergency: bool = True):
        """初始化"""
        self.critical_alerts_trigger_restrict = critical_alerts_trigger_restrict
        self.reduce_position_pct = reduce_position_pct
        self.max_reduce_steps = max_reduce_steps
        self.critical_trigger_emergency = critical_trigger_emergency


class EmergencyHandler:
    """紧急风险处理器"""
    
    def __init__(self, 
                 config: Optional[EmergencyConfig] = None,
                 monitor: Optional[RealTimeRiskMonitor] = None):
        """初始化"""
        self.config = config or EmergencyConfig()
        self.monitor = monitor
        
        # 行动历史
        self.action_history: List[EmergencyAction] = []
        # 当前紧急级别
        self.current_level: EmergencyLevel = EmergencyLevel.NORMAL
        # 减仓步数
        self.reduce_steps: int = 0
        # 回调
        self.on_emergency_action: Optional[Callable[[EmergencyAction], None]] = None
        
        # 行动计数
        self._action_counter = 0
    
    def _generate_action_id(self) -> str:
        """生成行动ID"""
        self._action_counter += 1
        ts = datetime.now().strftime("%Y%m%d%H%M%S")
        return f"ACTION-{ts}-{self._action_counter:04d}"
    
    def assess_emergency_level(self) -> EmergencyLevel:
        """评估当前紧急级别"""
        if not self.monitor:
            return EmergencyLevel.NORMAL
        
        unhandled = self.monitor.get_unhandled_alerts()
        critical_count = sum(1 for a in unhandled if a.level == AlertLevel.CRITICAL)
        
        if self.monitor.has_emergency_alerts():
            return EmergencyLevel.SHUTDOWN
        
        if critical_count >= 2:
            if self.config.critical_trigger_emergency:
                return EmergencyLevel.EMERGENCY
            else:
                return EmergencyLevel.REDUCE
        
        if critical_count >= self.config.critical_alerts_trigger_restrict:
            return EmergencyLevel.RESTRICT
        
        if self.monitor.get_unhandled_alerts():
            return EmergencyLevel.ALERT
        
        return EmergencyLevel.NORMAL
    
    def create_action(self, level: EmergencyLevel, trigger: RiskAlert) -> EmergencyAction:
        """创建紧急行动"""
        descriptions = {
            EmergencyLevel.NORMAL: "系统正常运行",
            EmergencyLevel.ALERT: "风险预警，持续监控",
            EmergencyLevel.RESTRICT: "限制新开仓，只允许平仓",
            EmergencyLevel.REDUCE: f"逐步减仓，每次减{self.config.reduce_position_pct:.1%}",
            EmergencyLevel.EMERGENCY: "紧急清仓，全部平仓",
            EmergencyLevel.SHUTDOWN: "系统紧急停机"
        }
        
        action = EmergencyAction(
            action_id=self._generate_action_id(),
            level=level,
            trigger_alert=trigger,
            timestamp=datetime.now(),
            description=descriptions.get(level, "未知级别")
        )
        
        return action
    
    def execute_action(self, action: EmergencyAction, 
                     liquidate_func: Optional[Callable[[], Tuple[bool, str]]] = None) -> bool:
        """执行紧急行动"""
        self.current_level = action.level
        
        if action.level == EmergencyLevel.NORMAL:
            action.executed = True
            action.result = "正常状态，无需操作"
            return True
        
        if action.level == EmergencyLevel.ALERT:
            action.executed = True
            action.result = "已发出预警，持续监控"
            return True
        
        if action.level == EmergencyLevel.RESTRICT:
            action.executed = True
            action.result = "已限制新开仓，只允许平仓"
            self.reduce_steps = 0
            return True
        
        if action.level == EmergencyLevel.REDUCE:
            if self.reduce_steps >= self.config.max_reduce_steps:
                # 减仓次数已到，升级紧急清仓
                action.level = EmergencyLevel.EMERGENCY
            
            self.reduce_steps += 1
            if liquidate_func and action.level == EmergencyLevel.REDUCE:
                success, msg = liquidate_func()
                action.executed = success
                action.result = f"第{self.reduce_steps}次减仓完成: {msg}"
                return success
            return True
        
        if action.level == EmergencyLevel.EMERGENCY:
            if liquidate_func:
                success, msg = liquidate_func()
                action.executed = success
                action.result = f"紧急清仓完成: {msg}"
                return success
            return False
        
        if action.level == EmergencyLevel.SHUTDOWN:
            action.executed = True
            action.result = "系统已紧急停机，等待人工处理"
            return True
        
        return False
    
    def check_and_handle(self, 
                       liquidate_func: Optional[Callable[[], Tuple[bool, str]]] = None) -> List[EmergencyAction]:
        """检查并处理紧急情况"""
        if not self.monitor:
            return []
        
        new_actions = []
        unhandled = self.monitor.get_unhandled_alerts()
        
        for alert in unhandled:
            if alert.level == AlertLevel.CRITICAL:
                level = self.assess_emergency_level()
                if level != EmergencyLevel.NORMAL and level != self.current_level:
                    action = self.create_action(level, alert)
                    self.execute_action(action, liquidate_func)
                    new_actions.append(action)
                    self.action_history.append(action)
                    
                    if self.on_emergency_action:
                        self.on_emergency_action(action)
        
        return new_actions
    
    def get_current_level(self) -> EmergencyLevel:
        """获取当前紧急级别"""
        return self.current_level
    
    def get_action_history(self) -> List[EmergencyAction]:
        """获取行动历史"""
        return self.action_history
    
    def get_unexecuted_actions(self) -> List[EmergencyAction]:
        """获取未执行行动"""
        return [a for a in self.action_history if not a.executed]
    
    def clear_all_alerts(self) -> None:
        """清除所有预警（风险解除后调用）"""
        if self.monitor:
            for alert in self.monitor.get_unhandled_alerts():
                self.monitor.mark_handled(alert.alert_id)
        
        self.current_level = EmergencyLevel.NORMAL
        self.reduce_steps = 0
    
    def can_open_position(self) -> bool:
        """检查是否允许开新仓"""
        allowed_levels = [EmergencyLevel.NORMAL, EmergencyLevel.ALERT]
        return self.current_level in allowed_levels
    
    def can_close_position(self) -> bool:
        """检查是否允许平仓（任何时候都允许平仓）"""
        return True
    
    def need_emergency_liquidate(self) -> bool:
        """检查是否需要紧急清仓"""
        return self.current_level in [EmergencyLevel.EMERGENCY, EmergencyLevel.SHUTDOWN]
    
    def is_system_running(self) -> bool:
        """检查系统是否正常运行"""
        return self.current_level != EmergencyLevel.SHUTDOWN
