"""事件管理器。

本模块提供事件管理器，作为 kernel/event 总线的上层封装。
负责将 EventHandler 组件注册到 EventBus 并管理其生命周期。

支持系统事件（EventType 枚举）和插件自定义事件（字符串）。
"""

from __future__ import annotations

import asyncio
from collections.abc import Awaitable
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple
from uuid import uuid4

if TYPE_CHECKING:
    from src.core.components.base.plugin import BasePlugin

from src.kernel.logger import get_logger
from src.kernel.event import get_event_bus, EventDecision
from src.kernel.concurrency import get_task_manager

from src.core.components.base.event_handler import BaseEventHandler
from src.core.components.types import EventType

logger = get_logger("event_manager")

TemporaryEventHandler = Callable[
    [str, Dict[str, Any]],
    tuple[EventDecision, Dict[str, Any]]
    | Awaitable[tuple[EventDecision, Dict[str, Any]]],
]


class EventManager:
    """事件管理器。

    作为 kernel/event 总线的上层封装，负责管理 EventHandler 组件的注册和订阅。
    处理器按权重排序执行，支持消息拦截功能。

    支持系统事件（EventType 枚举）和插件自定义事件（字符串）。
    EventType 只是为常见系统事件提供便捷，插件可以自由定义和使用自己的事件名称。

    Attributes:
        _event_bus: 底层事件总线实例
        _handler_map: 处理器映射，处理器签名 -> 处理器实例
        _handler_wrappers: 处理器包装函数映射（用于取消订阅）
        _lock: 用于线程安全操作的异步锁

    Examples:
        >>> manager = EventManager()
        >>> await manager.build_subscription_map()
        >>> # 发布系统事件
        >>> await manager.publish_event(EventType.ON_MESSAGE_RECEIVED, {"message": "Hello"})
        >>> # 发布自定义事件
        >>> await manager.publish_event("my_plugin:custom_event", {"data": "value"})
    """

    def __init__(self) -> None:
        """初始化事件管理器。"""
        self._event_bus = get_event_bus()
        self._handler_map: Dict[str, BaseEventHandler] = {}
        self._handler_wrappers: Dict[str, List[Callable[[], None]]] = (
            {}
        )  # signature -> unsubscribe functions
        self._temporary_wrappers: Dict[str, List[Callable[[], None]]] = {}
        self._temporary_handlers: Dict[str, TemporaryEventHandler] = {}
        self._lock = asyncio.Lock()

        logger.info("事件管理器初始化完成")

    async def register_plugin_handlers(
        self, plugin_name: str, plugin_instance: "BasePlugin | None" = None
    ) -> int:
        """注册指定插件的所有事件处理器。

        Args:
            plugin_name: 插件名称

        Returns:
            int: 成功注册的事件处理器数量
        """
        from src.core.components.registry import get_global_registry
        from src.core.components.types import ComponentType

        registry = get_global_registry()
        event_handler_classes = registry.get_by_plugin_and_type(
            plugin_name, ComponentType.EVENT_HANDLER
        )

        if not event_handler_classes:
            return 0

        registered_count = 0
        for component_name, handler_cls in event_handler_classes.items():
            signature = f"{plugin_name}:event_handler:{component_name}"
            handler = self._instantiate_handler(
                signature, handler_cls, plugin_instance=plugin_instance
            )
            if handler is None:
                continue

            await self.register_handler(signature, handler)
            registered_count += 1

        if registered_count:
            logger.info(
                f"插件 '{plugin_name}' 的事件处理器注册完成，共 {registered_count} 个"
            )

        return registered_count

    async def unregister_plugin_handlers(self, plugin_name: str) -> int:
        """注销指定插件的所有事件处理器。

        Args:
            plugin_name: 插件名称

        Returns:
            int: 成功注销的事件处理器数量
        """
        async with self._lock:
            prefix = f"{plugin_name}:"
            signatures = [
                signature
                for signature in self._handler_map.keys()
                if signature.startswith(prefix)
            ]

            for signature in signatures:
                self._unregister_handler_locked(signature)

        if signatures:
            logger.info(
                f"插件 '{plugin_name}' 的事件处理器已注销，共 {len(signatures)} 个"
            )

        return len(signatures)

    async def build_subscription_map(self) -> None:
        """构建事件订阅映射表。

        遍历所有已注册的事件处理器，根据它们的订阅信息注册到 EventBus。
        处理器按权重降序排序，权重高的优先执行。

        Examples:
            >>> await manager.build_subscription_map()
        """
        async with self._lock:
            # 清空现有映射表
            await self._clear_all_subscriptions()

            # 从全局注册表获取所有事件处理器组件
            from src.core.components.registry import get_global_registry
            from src.core.components.types import ComponentType

            registry = get_global_registry()

            # 获取所有 EVENT_HANDLER 类型的组件
            event_handler_classes: Dict[str, type[BaseEventHandler]] = (
                registry.get_by_type(ComponentType.EVENT_HANDLER)
            )

            for signature, handler_cls in event_handler_classes.items():
                handler = self._instantiate_handler(signature, handler_cls)
                if handler is None:
                    continue

                self._register_handler_locked(signature, handler)

            logger.info(
                f"订阅映射表构建完成，共处理 {len(self._handler_map)} 个 " f"事件处理器"
            )

    def _instantiate_handler(
        self,
        signature: str,
        handler_cls: type[BaseEventHandler],
        plugin_instance: "BasePlugin | None" = None,
    ) -> BaseEventHandler | None:
        """根据组件签名实例化事件处理器。"""
        from src.core.components.types import parse_signature
        from src.core.managers import get_plugin_manager

        try:
            sig = parse_signature(signature)
            plugin_name = sig["plugin_name"]

            resolved_plugin = plugin_instance or get_plugin_manager().get_plugin(plugin_name)
            if not resolved_plugin:
                logger.warning(f"未找到插件实例: {plugin_name}")
                return None

            handler = handler_cls(resolved_plugin)
            handler.signature = signature
            return handler
        except Exception as e:
            logger.error(f"实例化事件处理器 {signature} 失败: {e}")
            return None

    def _register_handler_locked(
        self, signature: str, handler: BaseEventHandler
    ) -> None:
        """在已持有锁时注册处理器。"""
        if signature in self._handler_wrappers:
            self._unregister_handler_locked(signature)

        self._handler_map[signature] = handler

        subscribed_events = handler.get_subscribed_events()
        wrappers: list[Callable[[], None]] = []
        for event in subscribed_events:
            event_name = event.value if isinstance(event, EventType) else str(event)
            unsubscribe = self._event_bus.subscribe(
                event_name,
                self._make_safe_wrapper(handler, signature),
                priority=handler.weight,
            )
            wrappers.append(unsubscribe)

        self._handler_wrappers[signature] = wrappers
        logger.debug(f"已注册事件处理器: {signature}")

    def _unregister_handler_locked(self, signature: str) -> None:
        """在已持有锁时注销处理器。"""
        if signature in self._handler_wrappers:
            for unsubscribe in self._handler_wrappers[signature]:
                unsubscribe()
            del self._handler_wrappers[signature]

        self._handler_map.pop(signature, None)
        logger.debug(f"已注销事件处理器: {signature}")

    def _coerce_event_name(self, event: EventType | str) -> str:
        """将事件类型统一转换为事件名称字符串。"""

        return event.value if isinstance(event, EventType) else str(event)

    async def create_temporary_handler(
        self,
        event_names: List[EventType | str],
        handle_func: TemporaryEventHandler,
        priority: int = 0,
    ) -> str:
        """创建运行时临时事件监听器。

        临时监听器在任一次执行返回 ``EventDecision.SUCCESS`` 或
        ``EventDecision.STOP`` 后会被自动清理；返回 ``PASS`` 时会继续保留。

        Args:
            event_names: 订阅的事件列表，至少包含一个事件名。
            handle_func: 临时事件处理回调。
            priority: 监听器优先级。

        Returns:
            str: 临时监听器 ID，可用于手动注销。
        """

        normalized_events = [
            self._coerce_event_name(event)
            for event in event_names
            if self._coerce_event_name(event).strip()
        ]
        if not normalized_events:
            raise ValueError("event_names 至少需要包含一个有效事件")
        if not callable(handle_func):
            raise ValueError("handle_func 必须是可调用对象")

        temporary_id = f"temporary:{uuid4()}"
        async with self._lock:
            wrappers: list[Callable[[], None]] = []
            wrapper = self._make_temporary_wrapper(temporary_id, handle_func)
            for event_name in normalized_events:
                unsubscribe = self._event_bus.subscribe(
                    event_name,
                    wrapper,
                    priority=priority,
                )
                wrappers.append(unsubscribe)

            self._temporary_handlers[temporary_id] = handle_func
            self._temporary_wrappers[temporary_id] = wrappers

        logger.debug(
            f"已创建临时事件监听器: {temporary_id}, "
            f"events={normalized_events}, priority={priority}"
        )
        return temporary_id

    async def unregister_temporary_handler(self, temporary_id: str) -> bool:
        """注销临时事件监听器。"""

        async with self._lock:
            return self._unregister_temporary_handler_locked(temporary_id)

    def _unregister_temporary_handler_locked(self, temporary_id: str) -> bool:
        """在已持有锁时注销临时监听器。"""

        wrappers = self._temporary_wrappers.pop(temporary_id, None)
        if wrappers is None:
            return False

        for unsubscribe in wrappers:
            unsubscribe()
        self._temporary_handlers.pop(temporary_id, None)
        logger.debug(f"已注销临时事件监听器: {temporary_id}")
        return True

    def _make_temporary_wrapper(
        self,
        temporary_id: str,
        handle_func: TemporaryEventHandler,
    ) -> Callable[[str, Dict[str, Any]], Any]:
        """为临时监听器创建自动清理包装。"""

        async def safe_execute(
            event_name: str, params: Dict[str, Any]
        ) -> tuple[EventDecision, Dict[str, Any]]:
            try:
                result = handle_func(event_name, params)
                if asyncio.iscoroutine(result) or isinstance(result, Awaitable):
                    awaited_result = await result
                    decision, next_params = awaited_result
                else:
                    decision, next_params = result
            except Exception as e:
                logger.error(f"临时事件监听器 {temporary_id} 执行失败: {e}")
                return (EventDecision.PASS, params)

            if decision != EventDecision.PASS:
                async with self._lock:
                    self._unregister_temporary_handler_locked(temporary_id)
            return (decision, next_params)

        return safe_execute

    def _make_safe_wrapper(
        self, handler: BaseEventHandler, signature: str
    ) -> Callable[[str, Dict[str, Any]], Any]:
        """为事件处理器创建异常防护包装，直接透传 EventBus 协议。

        handler.execute 与 EventBus 订阅者协议完全一致：接受 (event_name, params)
        并返回 (EventDecision, params)。本方法仅添加异常捕获，不做任何语义转换。

        Args:
            handler: 事件处理器实例
            signature: 处理器签名（用于日志）

        Returns:
            符合 EventBus 协议的异常安全包装函数
        """

        async def safe_execute(
            event_name: str, params: Dict[str, Any]
        ) -> tuple[EventDecision, Dict[str, Any]]:
            try:
                return await handler.execute(event_name, params)
            except Exception as e:
                logger.error(f"事件处理器 {signature} 执行失败: {e}")
                return (EventDecision.PASS, params)

        return safe_execute

    async def publish_event(
        self, event: EventType | str, kwargs: Optional[Dict[str, Any]] = None
    ) -> Dict[str, Any]:
        """发布事件给订阅者。

        支持系统事件（EventType 枚举）和自定义事件（字符串）。

        Args:
            event: 事件类型（EventType 枚举或自定义字符串）
            kwargs: 事件参数字典

        Returns:
            Dict[str, Any]: 发布结果，包含最终决策和参数

        Examples:
            >>> # 发布系统事件
            >>> result = await manager.publish_event(
            ...     EventType.ON_MESSAGE_RECEIVED,
            ...     {"message": "Hello", "sender": "user1"}
            ... )
            >>> # 发布自定义事件
            >>> result = await manager.publish_event(
            ...     "my_plugin:user_action",
            ...     {"action": "click", "target": "button"}
            ... )
        """
        if kwargs is None:
            kwargs = {}

        logger.debug(f"发布事件: {event}")

        # 通过 EventBus 发布事件
        # 注意：不能使用 str(event)，Python 3.11 中 str(StrEnum.member) 返回
        # "EnumName.member" 而非 value，会导致与直接用枚举订阅的 key 不匹配
        event_name = self._coerce_event_name(event)
        decision, final_params = await self._event_bus.publish(event_name, kwargs)

        logger.debug(f"事件 {event} 发布完成，最终决策: {decision}")

        return {"decision": decision, "params": final_params}

    async def register_handler(self, signature: str, handler: BaseEventHandler) -> None:
        """注册单个事件处理器。

        Args:
            signature: 处理器签名
            handler: 事件处理器实例

        Examples:
            >>> await manager.register_handler("my_plugin:event_handler:log", handler)
        """
        async with self._lock:
            self._register_handler_locked(signature, handler)

    def unregister_handler(self, signature: str) -> None:
        """注销单个事件处理器。

        Args:
            signature: 处理器签名

        Examples:
            >>> manager.unregister_handler("my_plugin:event_handler:log")
        """

        async def _unregister() -> None:
            async with self._lock:
                if signature in self._handler_map:
                    self._unregister_handler_locked(signature)

        get_task_manager().create_task(_unregister())

    def get_handlers_for_event(
        self, event: EventType | str
    ) -> List[Tuple[BaseEventHandler, str]]:
        """获取指定事件的所有处理器。

        Args:
            event: 事件类型（EventType 枚举或字符串）

        Returns:
            List[Tuple[BaseEventHandler, str]]: 处理器列表，包含处理器实例和签名

        Examples:
            >>> handlers = manager.get_handlers_for_event(EventType.ON_MESSAGE_RECEIVED)
            >>> custom_handlers = manager.get_handlers_for_event("my_plugin:custom_event")
        """
        # 将事件转换为字符串（支持 EventType 枚举和自定义字符串）
        event_name = event.value if isinstance(event, EventType) else str(event)

        # 从已注册的处理器中查找订阅了该事件的处理器
        result = []
        for signature, handler in self._handler_map.items():
            subscribed_events = handler.get_subscribed_events()
            # 检查是否订阅了该事件（支持 EventType 和字符串）
            if any(
                (e.value if isinstance(e, EventType) else str(e)) == event_name
                for e in subscribed_events
            ):
                result.append((handler, signature))

        # 按权重排序
        result.sort(key=lambda x: x[0].weight, reverse=True)
        return result

    def get_handler(self, signature: str) -> Optional[BaseEventHandler]:
        """获取指定签名的事件处理器。

        Args:
            signature: 处理器签名

        Returns:
            Optional[BaseEventHandler]: 处理器实例，不存在返回 None

        Examples:
            >>> handler = manager.get_handler("my_plugin:event_handler:log")
        """
        return self._handler_map.get(signature)

    def get_all_handlers(self) -> Dict[str, BaseEventHandler]:
        """获取所有事件处理器。

        Returns:
            Dict[str, BaseEventHandler]: 处理器映射表

        Examples:
            >>> handlers = manager.get_all_handlers()
        """
        return self._handler_map.copy()

    async def _clear_all_subscriptions(self) -> None:
        """清除所有订阅（内部使用）。"""
        # 取消所有订阅
        for signature in list(self._handler_wrappers.keys()):
            for unsubscribe in self._handler_wrappers[signature]:
                unsubscribe()
        for temporary_id in list(self._temporary_wrappers.keys()):
            for unsubscribe in self._temporary_wrappers[temporary_id]:
                unsubscribe()

        # 清空映射表
        self._handler_map.clear()
        self._handler_wrappers.clear()
        self._temporary_handlers.clear()
        self._temporary_wrappers.clear()

        logger.debug("已清除所有事件处理器订阅")

    def get_event_stats(self) -> Dict[str, int]:
        """获取事件统计信息。

        Returns:
            Dict[str, int]: 统计信息，包含处理器数量和事件类型数量

        Examples:
            >>> stats = manager.get_event_stats()
            >>> print(stats["handler_count"])  # 处理器总数
            >>> print(stats["event_type_count"])  # 事件类型总数
        """
        return {
            "handler_count": len(self._handler_map),
            "temporary_handler_count": len(self._temporary_handlers),
            "event_type_count": self._event_bus.event_count,
            "total_subscriptions": self._event_bus.handler_count,
        }


# 全局单例
_event_manager: Optional[EventManager] = None


def get_event_manager() -> EventManager:
    """获取全局事件管理器实例（懒加载）。

    Returns:
        EventManager: 全局事件管理器实例

    Examples:
        >>> from src.core.managers import get_event_manager
        >>> manager = get_event_manager()
    """
    global _event_manager
    if _event_manager is None:
        _event_manager = EventManager()
    return _event_manager


def reset_event_manager() -> None:
    """重置全局事件管理器。

    主要用于测试场景，确保测试之间不会相互影响。
    """
    global _event_manager
    _event_manager = None


def initialize_event_manager() -> None:
    """初始化事件管理器。

    主要用于在应用启动时提前创建全局事件管理器实例。
    正常运行路径下，插件事件处理器会在单插件加载成功后立即完成注册。
    """
    get_event_manager()


async def on_all_plugins_loaded(
    _: str, params: Dict[str, Any]
) -> Tuple[EventDecision, Dict[str, Any]]:
    """所有插件加载完毕后，构建事件订阅映射。

    Args:
        event_name: 事件名称
        params: 事件参数字典

    Returns:
        tuple[EventDecision, dict]: (事件决策, 事件参数)
    """
    logger.info("开始构建事件订阅映射...")

    # 构建订阅映射
    manager = get_event_manager()
    try:
        await manager.build_subscription_map()
        logger.info("✅ 事件订阅映射构建完成")
    except Exception as e:
        logger.error(f"❌ 构建事件订阅映射时发生异常: {e}")
        return (EventDecision.PASS, params)

    return (EventDecision.SUCCESS, params)
