import threading
from collections.abc import Callable
from typing import TypeVar, Dict, Any, Optional

from ctf_kit_core.application.context.class_proxy import ClassProxy

T = TypeVar('T')

class ApplicationContext:
    """
    应用上下文
    提供全局函数和类的注册与获取功能
    支持通过ClassProxy增强IDE提示体验
    """
    _function_map: Dict[str, Callable] = {}
    _module_map: Dict[str, Callable] = {}
    _class_map: Dict[str, type] = {}
    _docs: Dict[str, Dict[str, Any]] = {}  # 存储类的文档信息
    _singleton_instances: Dict[str, Any] = {}  # 单例实例缓存
    _lock = threading.Lock()

    @classmethod
    def get_registered_classes(cls) -> list[str]:
        """
        获取所有已注册的类名称
        :return 已注册的类名称列表
        """
        with cls._lock:
            return list(cls._class_map.keys())

    @classmethod
    def get_registered_functions(cls) -> list[str]:
        """
        获取所有已注册的函数名称
        :return 已注册的函数名称列表
        """
        with cls._lock:
            return list(cls._function_map.keys())
    @classmethod
    def register_module(cls, module_name:str, module, doc: Optional[Dict[str, Any]] = None) -> None:
        """
        注册模块到应用上下文
        :param module_name: 模块名称
        :param module: 模块
        :param doc: 模块的文档信息（可选）
        :return: None
        """
        with cls._lock:
            cls._module_map[module_name] = module
            if doc is not None:
                cls._docs['module_'+module_name] = doc

    @classmethod
    def get_module(cls, module_name:str, is_ok_none=False) -> Callable:
        """
        获取已注册的模块
        :param module_name: 模块名称
        :param is_ok_none: 是否允许返回None
        :return: 模块
        """
        with cls._lock:
            module = cls._module_map.get(module_name)
        if not is_ok_none and module is None:
            raise ValueError(f"Module {module} not registered")
        return module

    @classmethod
    def get_module_documentation(cls, module_name: str) -> Optional[Dict[str, Any]]:
        """
        获取模块的文档信息
        :param module_name: 模块名称
        :return: 模块的文档信息，如果没有则返回None
        """
        with cls._lock:
            return cls._docs.get('module_'+module_name)

    @classmethod
    def register_function(cls, func_name:str, func, doc: Optional[Dict[str, Any]] = None) -> None:
        """
        注册函数到应用上下文
        :param func_name: 函数名称
        :param func: 函数
        :param doc: 函数的文档信息（可选）
        :return: None
        """
        with cls._lock:
            cls._function_map[func_name] = func
            if doc is not None:
                cls._docs['func_'+func_name] = doc

    @classmethod
    def get_function(cls, func_name:str, is_ok_none=False) -> Callable:
        """
        获取已注册的函数
        :param func_name: 函数名称
        :param is_ok_none: 是否允许返回None
        :return: 函数
        """
        with cls._lock:
            func = cls._function_map.get(func_name)
        if not is_ok_none and func is None:
            raise ValueError(f"Function {func} not registered")
        return func
    @classmethod
    def get_function_documentation(cls, func_name: str) -> Optional[Dict[str, Any]]:
        """
        获取函数的文档信息
        :param func_name: 函数名称
        :return: 函数的文档信息，如果没有则返回None
        """
        with cls._lock:
            return cls._docs.get('func_'+func_name)


    @classmethod
    def register_class(cls, class_name: str, class_type: type, doc: Optional[Dict[str, Any]] = None) -> None:
        """
        注册类到应用上下文
        :param class_name: 类名称
        :param class_type: 要注册的类类型
        :param doc: 类的文档信息（可选）
        :return: None
        """
        with cls._lock:
            cls._class_map[class_name] = class_type
            if doc is not None:
                cls._docs['class_'+class_name] = doc

    @classmethod
    def get_class_type(cls, class_name: str, is_ok_none: bool = False) -> type[T]:
        """
        从应用上下文获取已注册的类类型
        :param class_name: 类名称
        :param is_ok_none: 是否允许返回None
        :return: 注册的类类型
        :raise ValueError: 当类未注册且is_ok_none为False时
        """
        with cls._lock:
            class_type = cls._class_map.get(class_name)
        if not is_ok_none and class_type is None:
            raise ValueError(f"Class {class_name} not registered")
        return class_type

    @classmethod
    def get_class_instance(cls, class_name: str, *args, **kwargs) -> T:
        """
        获取类的新实例
        :param class_name: 类名称
        :param args: 传递给构造函数的位置参数
        :param kwargs: 传递给构造函数的关键字参数
        :return: 类的新实例
        """
        return cls.get_class_type(class_name, is_ok_none=False)(*args, **kwargs)

    @classmethod
    def get_class_proxy(cls, class_name: str, *args, **kwargs) -> ClassProxy:
        """
        获取类代理对象，增强IDE提示功能
        :param class_name: 类名称
        :param args: 传递给构造函数的位置参数
        :param kwargs: 传递给构造函数的关键字参数
        :return: 类代理对象
        """
        class_type = cls.get_class_type(class_name)
        return ClassProxy(class_type, *args, **kwargs)

    @classmethod
    def get_class_documentation(cls, class_name: str) -> Optional[Dict[str, Any]]:
        """
        获取类的文档信息
        :param class_name: 类名称
        :return: 类的文档信息，如果没有则返回None
        """
        with cls._lock:
            return cls._docs.get('class_'+class_name)

    @classmethod
    def get_singleton_instance(cls, class_name: str, *args, **kwargs) -> T:
        """
        获取单例实例
        :param class_name: 类名称
        :param args: 构造函数位置参数
        :param kwargs: 构造函数关键字参数
        :return: 单例实例
        """
        # 先检查缓存，避免不必要的锁竞争
        with cls._lock:
            if class_name in cls._singleton_instances:
                return cls._singleton_instances[class_name]
        
        # 创建新实例（在锁外进行，避免死锁）
        new_instance = cls.get_class_instance(class_name, *args, **kwargs)
        
        # 再次检查并设置缓存
        with cls._lock:
            if class_name not in cls._singleton_instances:
                cls._singleton_instances[class_name] = new_instance
            return cls._singleton_instances[class_name]
    
    @classmethod
    def clear_singleton_cache(cls) -> None:
        """清除所有单例实例缓存"""
        with cls._lock:
            cls._singleton_instances.clear()


