"""
依赖注入容器
提供单例管理和依赖解析功能
"""
from typing import TypeVar, Generic, Callable, Dict, Any, Optional, Type
from threading import Lock
from loguru import logger

T = TypeVar('T')


class Singleton(Generic[T]):
    """单例包装器，线程安全"""
    
    def __init__(self, factory: Callable[..., T]):
        self._factory = factory
        self._instance: Optional[T] = None
        self._lock = Lock()
    
    def get(self, **kwargs) -> T:
        """获取单例实例"""
        if self._instance is None:
            with self._lock:
                if self._instance is None:
                    self._instance = self._factory(**kwargs)
        return self._instance
    
    def reset(self):
        """重置单例实例（用于测试）"""
        with self._lock:
            self._instance = None


class Factory(Generic[T]):
    """工厂包装器，每次调用创建新实例"""
    
    def __init__(self, factory: Callable[..., T]):
        self._factory = factory
    
    def get(self, **kwargs) -> T:
        """获取新实例"""
        return self._factory(**kwargs)


class Container:
    """
    依赖注入容器
    
    支持以下功能：
    - 单例注册和获取
    - 工厂注册和获取
    - 依赖解析
    - 配置注入
    
    使用示例:
        container = Container()
        container.register_singleton("config", lambda: get_config_manager())
        container.register_factory("service", lambda c: RAGService(c.get("config")))
        
        config = container.get("config")
        service = container.get("service")
    """
    
    def __init__(self):
        self._singletons: Dict[str, Singleton] = {}
        self._factories: Dict[str, Factory] = {}
        self._instances: Dict[str, Any] = {}  # 直接注册的实例
        self._lock = Lock()
        self._initialized = False
    
    def register_singleton(self, name: str, factory: Callable[..., Any]) -> "Container":
        """
        注册单例服务
        
        Args:
            name: 服务名称
            factory: 创建实例的工厂函数
        
        Returns:
            self，支持链式调用
        """
        with self._lock:
            self._singletons[name] = Singleton(factory)
            logger.debug(f"注册单例服务: {name}")
        return self
    
    def register_factory(self, name: str, factory: Callable[..., Any]) -> "Container":
        """
        注册工厂服务（每次获取创建新实例）
        
        Args:
            name: 服务名称
            factory: 创建实例的工厂函数
        
        Returns:
            self，支持链式调用
        """
        with self._lock:
            self._factories[name] = Factory(factory)
            logger.debug(f"注册工厂服务: {name}")
        return self
    
    def register_instance(self, name: str, instance: Any) -> "Container":
        """
        直接注册实例
        
        Args:
            name: 服务名称
            instance: 已创建的实例
        
        Returns:
            self，支持链式调用
        """
        with self._lock:
            self._instances[name] = instance
            logger.debug(f"注册实例: {name}")
        return self
    
    def get(self, name: str, **kwargs) -> Any:
        """
        获取服务实例
        
        Args:
            name: 服务名称
            **kwargs: 传递给工厂函数的参数
        
        Returns:
            服务实例
        
        Raises:
            KeyError: 服务未注册
        """
        # 优先查找直接注册的实例
        if name in self._instances:
            return self._instances[name]
        
        # 查找单例
        if name in self._singletons:
            return self._singletons[name].get(**kwargs)
        
        # 查找工厂
        if name in self._factories:
            return self._factories[name].get(**kwargs)
        
        raise KeyError(f"服务未注册: {name}")
    
    def has(self, name: str) -> bool:
        """
        检查服务是否已注册
        
        Args:
            name: 服务名称
        
        Returns:
            是否已注册
        """
        return (
            name in self._instances or 
            name in self._singletons or 
            name in self._factories
        )
    
    def reset(self, name: Optional[str] = None):
        """
        重置服务实例（用于测试）
        
        Args:
            name: 服务名称，如果为None则重置所有
        """
        with self._lock:
            if name is None:
                # 重置所有单例
                for singleton in self._singletons.values():
                    singleton.reset()
                self._instances.clear()
                self._initialized = False
                logger.debug("重置所有服务")
            elif name in self._singletons:
                self._singletons[name].reset()
                logger.debug(f"重置单例服务: {name}")
            elif name in self._instances:
                del self._instances[name]
                logger.debug(f"移除实例: {name}")
    
    def initialize(self):
        """
        初始化容器（确保所有服务已准备好）
        """
        if self._initialized:
            return
        
        with self._lock:
            if not self._initialized:
                logger.info("初始化依赖注入容器")
                self._initialized = True
    
    @property
    def is_initialized(self) -> bool:
        """容器是否已初始化"""
        return self._initialized


# 全局容器实例
_container: Optional[Container] = None
_container_lock = Lock()


def get_container() -> Container:
    """
    获取全局容器实例
    
    Returns:
        Container: 全局容器实例
    """
    global _container
    
    if _container is None:
        with _container_lock:
            if _container is None:
                _container = Container()
                _setup_default_services(_container)
    
    return _container


def reset_container():
    """重置全局容器（用于测试）"""
    global _container
    
    with _container_lock:
        if _container is not None:
            _container.reset()
            _container = None


def _setup_default_services(container: Container):
    """
    设置默认服务
    
    Args:
        container: 容器实例
    """
    from src.config import get_config_manager
    
    # 注册配置（单例）
    container.register_singleton(
        "config",
        lambda: get_config_manager()
    )
    
    # 注册 RAGService（单例，懒加载）
    def create_rag_service():
        from src.services import RAGService
        config = container.get("config")
        return RAGService(config=config)
    
    container.register_singleton("rag_service", create_rag_service)
    
    # 注册 RAGSystem（单例，懒加载）
    def create_rag_system():
        from src.core import RAGSystem
        config = container.get("config")
        return RAGSystem(config=config)
    
    container.register_singleton("rag_system", create_rag_system)
    
    logger.debug("默认服务注册完成")
