"""
事件总线实现
提供发布-订阅模式的事件系统，用于组件间解耦通信
"""
from typing import Dict, List, Callable, Any, Optional
from enum import Enum
from dataclasses import dataclass, field
from datetime import datetime
from loguru import logger


class EventType(Enum):
    """事件类型枚举"""
    # 索引构建相关
    INDEX_BUILD_STARTED = "index_build_started"
    INDEX_BUILD_COMPLETED = "index_build_completed"
    INDEX_BUILD_FAILED = "index_build_failed"
    
    # 索引加载相关
    INDEX_LOAD_STARTED = "index_load_started"
    INDEX_LOAD_COMPLETED = "index_load_completed"
    INDEX_LOAD_FAILED = "index_load_failed"
    
    # 存储相关
    STORAGE_PERSISTED = "storage_persisted"
    STORAGE_DELETED = "storage_deleted"
    STORAGE_SWITCHED = "storage_switched"
    
    # 查询相关
    QUERY_STARTED = "query_started"
    QUERY_COMPLETED = "query_completed"
    QUERY_FAILED = "query_failed"
    
    # 文件监控相关
    FILE_CREATED = "file_created"
    FILE_MODIFIED = "file_modified"
    FILE_DELETED = "file_deleted"
    FILE_MOVED = "file_moved"
    FILE_WATCHER_STARTED = "file_watcher_started"
    FILE_WATCHER_STOPPED = "file_watcher_stopped"
    FILE_WATCHER_ERROR = "file_watcher_error"


@dataclass
class Event:
    """事件基类"""
    event_type: EventType
    data: Dict[str, Any] = field(default_factory=dict)
    timestamp: datetime = field(default_factory=datetime.now)
    source: Optional[str] = None
    
    def __post_init__(self):
        """确保timestamp是datetime对象"""
        if not isinstance(self.timestamp, datetime):
            self.timestamp = datetime.now()


class EventBus:
    """
    事件总线（单例模式）
    
    提供发布-订阅机制，允许组件间解耦通信：
    - 发布者发布事件时无需知道订阅者
    - 订阅者注册感兴趣的事件类型
    - 支持异步事件处理
    """
    
    _instance: Optional["EventBus"] = None
    
    def __new__(cls):
        """实现单例模式"""
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._initialized = False
        return cls._instance
    
    def __init__(self):
        """初始化事件总线"""
        if self._initialized:
            return
        
        self._subscribers: Dict[EventType, List[Callable]] = {}
        self._event_history: List[Event] = []
        self._max_history = 100  # 保留最近100个事件
        self._initialized = True
        logger.debug("事件总线已初始化")
    
    @classmethod
    def get_instance(cls) -> "EventBus":
        """获取单例实例"""
        return cls()
    
    def subscribe(self, event_type: EventType, callback: Callable[[Event], None]) -> None:
        """
        订阅事件
        
        Args:
            event_type: 事件类型
            callback: 回调函数，接收Event对象作为参数
        """
        if event_type not in self._subscribers:
            self._subscribers[event_type] = []
        
        if callback not in self._subscribers[event_type]:
            self._subscribers[event_type].append(callback)
            logger.debug(f"订阅事件: {event_type.value}")
    
    def unsubscribe(self, event_type: EventType, callback: Callable[[Event], None]) -> None:
        """
        取消订阅事件
        
        Args:
            event_type: 事件类型
            callback: 回调函数
        """
        if event_type in self._subscribers and callback in self._subscribers[event_type]:
            self._subscribers[event_type].remove(callback)
            logger.debug(f"取消订阅事件: {event_type.value}")
    
    def publish(self, event: Event) -> None:
        """
        发布事件
        
        Args:
            event: 事件对象
        """
        # 记录事件历史
        self._event_history.append(event)
        if len(self._event_history) > self._max_history:
            self._event_history.pop(0)
        
        logger.debug(
            f"发布事件: {event.event_type.value} "
            f"[源: {event.source or 'unknown'}]"
        )
        
        # 通知所有订阅者
        if event.event_type in self._subscribers:
            for callback in self._subscribers[event.event_type]:
                try:
                    callback(event)
                except Exception as e:
                    logger.error(
                        f"事件处理器执行失败 [{event.event_type.value}]: {e}"
                    )
    
    def get_history(self, event_type: Optional[EventType] = None, limit: int = 10) -> List[Event]:
        """
        获取事件历史
        
        Args:
            event_type: 事件类型过滤（可选）
            limit: 返回数量限制
            
        Returns:
            事件列表
        """
        history = self._event_history
        if event_type:
            history = [e for e in history if e.event_type == event_type]
        return history[-limit:]
    
    def clear_history(self) -> None:
        """清空事件历史"""
        self._event_history.clear()
        logger.debug("事件历史已清空")
    
    def get_subscribers_count(self, event_type: EventType) -> int:
        """
        获取指定事件类型的订阅者数量
        
        Args:
            event_type: 事件类型
            
        Returns:
            订阅者数量
        """
        return len(self._subscribers.get(event_type, []))
    
    def reset(self) -> None:
        """重置事件总线（主要用于测试）"""
        self._subscribers.clear()
        self._event_history.clear()
        logger.debug("事件总线已重置")
