"""
存储提供者
负责根据配置创建和管理存储策略，支持存储后端热切换
"""
from typing import Optional, Dict
from loguru import logger

from src.config import ConfigManager, get_config_manager
from src.types import StorageConfig, StorageBackend
from src.events import EventBus, StorageEvent
from .base import StorageStrategy
from .local_strategy import LocalStorageStrategy
from .qdrant_strategy import QdrantStorageStrategy


class StorageProvider:
    """
    存储提供者（单例模式）
    
    职责：
    - 根据配置创建合适的存储策略
    - 支持运行时切换存储后端
    - 管理存储策略的生命周期
    """
    
    _instance: Optional["StorageProvider"] = 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.config_manager: Optional[ConfigManager] = None
        self.current_strategy: Optional[StorageStrategy] = None
        self._strategy_cache: Dict[str, StorageStrategy] = {}
        self.event_bus = EventBus.get_instance()
        self._initialized = True
        logger.debug("存储提供者已初始化")
    
    @classmethod
    def get_instance(cls) -> "StorageProvider":
        """获取单例实例"""
        return cls()
    
    def setup(self, config_manager: Optional[ConfigManager] = None) -> None:
        """
        设置配置管理器
        
        Args:
            config_manager: 配置管理器实例
        """
        self.config_manager = config_manager or get_config_manager()
        logger.debug("存储提供者配置已设置")
    
    def _create_storage_config(self) -> StorageConfig:
        """
        从配置管理器创建存储配置
        
        Returns:
            存储配置对象
        """
        if not self.config_manager:
            self.setup()
        
        vs_config = self.config_manager.vector_store
        paths_config = self.config_manager.paths
        
        if vs_config.use_qdrant:
            return StorageConfig.for_qdrant(
                collection_name=vs_config.qdrant_collection_name,
                url=vs_config.qdrant_url,
                api_key=vs_config.get_api_key(),
                host=vs_config.qdrant_host,
                port=vs_config.qdrant_port
            )
        else:
            return StorageConfig.for_local(
                persist_dir=str(paths_config.vector_storage_dir)
            )
    
    def get_strategy(self, backend: Optional[StorageBackend] = None) -> StorageStrategy:
        """
        获取存储策略
        
        Args:
            backend: 存储后端类型（可选，不指定则使用配置中的默认值）
            
        Returns:
            存储策略实例
        """
        # 如果未指定后端，使用配置中的默认值
        if backend is None:
            storage_config = self._create_storage_config()
            backend = storage_config.backend
        else:
            # 根据指定的后端创建配置
            if not self.config_manager:
                self.setup()
            
            paths_config = self.config_manager.paths
            vs_config = self.config_manager.vector_store
            
            if backend == StorageBackend.LOCAL:
                storage_config = StorageConfig.for_local(
                    persist_dir=str(paths_config.vector_storage_dir)
                )
            elif backend == StorageBackend.QDRANT:
                storage_config = StorageConfig.for_qdrant(
                    collection_name=vs_config.qdrant_collection_name,
                    url=vs_config.qdrant_url,
                    api_key=vs_config.get_api_key(),
                    host=vs_config.qdrant_host,
                    port=vs_config.qdrant_port
                )
            else:
                raise ValueError(f"不支持的存储后端: {backend}")
        
        # 检查缓存
        cache_key = backend.value
        if cache_key in self._strategy_cache:
            return self._strategy_cache[cache_key]
        
        # 创建新策略
        strategy = self._create_strategy(storage_config)
        self._strategy_cache[cache_key] = strategy
        
        # 如果这是第一次创建策略，设置为当前策略
        if self.current_strategy is None:
            self.current_strategy = strategy
        
        return strategy
    
    def _create_strategy(self, config: StorageConfig) -> StorageStrategy:
        """
        根据配置创建存储策略
        
        Args:
            config: 存储配置
            
        Returns:
            存储策略实例
        """
        if config.backend == StorageBackend.LOCAL:
            strategy = LocalStorageStrategy(config)
        elif config.backend == StorageBackend.QDRANT:
            strategy = QdrantStorageStrategy(config)
        else:
            raise ValueError(f"不支持的存储后端: {config.backend}")
        
        logger.info(f"创建存储策略: {config.backend.value}")
        return strategy
    
    def switch_backend(self, backend: StorageBackend) -> bool:
        """
        切换存储后端
        
        Args:
            backend: 目标存储后端
            
        Returns:
            是否切换成功
        """
        try:
            old_backend = self.current_strategy.backend_name if self.current_strategy else "none"
            
            logger.info(f"切换存储后端: {old_backend} -> {backend.value}")
            
            # 获取新策略
            new_strategy = self.get_strategy(backend)
            
            # 初始化新策略
            init_result = new_strategy.initialize()
            if not init_result.success:
                logger.error(f"初始化新存储后端失败: {init_result.error}")
                return False
            
            # 更新当前策略
            self.current_strategy = new_strategy
            
            # 发布后端切换事件
            self.event_bus.publish(
                StorageEvent.switched(
                    from_backend=old_backend,
                    to_backend=backend.value,
                    source="StorageProvider"
                )
            )
            
            logger.info(f"✅ 存储后端已切换到: {backend.value}")
            return True
            
        except Exception as e:
            logger.error(f"切换存储后端失败: {e}")
            return False
    
    def get_current_strategy(self) -> Optional[StorageStrategy]:
        """
        获取当前存储策略
        
        Returns:
            当前存储策略或None
        """
        if self.current_strategy is None:
            # 自动创建默认策略
            self.current_strategy = self.get_strategy()
        return self.current_strategy
    
    def clear_cache(self) -> None:
        """清空策略缓存"""
        self._strategy_cache.clear()
        self.current_strategy = None
        logger.debug("存储策略缓存已清空")
    
    def reset(self) -> None:
        """重置存储提供者（主要用于测试）"""
        self.clear_cache()
        self.config_manager = None
        logger.debug("存储提供者已重置")
