"""
配置管理测试
测试新的 Pydantic 配置系统
"""
import sys
from pathlib import Path

# 添加项目根目录到路径
sys.path.insert(0, str(Path(__file__).parent.parent))

from src.config import (
    Settings,
    ConfigManager,
    get_config_manager,
    reload_config,
    PathConfig,
    LLMConfig,
    EmbeddingConfig,
    RetrievalConfig,
    VectorStoreConfig,
)


def test_path_config():
    """测试路径配置"""
    print("=" * 60)
    print("测试1: 路径配置")
    print("=" * 60)
    
    config = PathConfig()
    
    assert config.base_dir.exists(), "项目根目录应该存在"
    assert config.storage_root is not None, "存储根目录应该有默认值"
    assert config.vector_storage_dir is not None, "向量存储目录应该有默认值"
    
    print(f"✅ 项目根目录: {config.base_dir}")
    print(f"✅ 存储根目录: {config.storage_root}")
    print(f"✅ 向量存储目录: {config.vector_storage_dir}")
    print(f"✅ BM25存储目录: {config.bm25_storage_dir}")
    
    print("\n✅ 路径配置测试通过！\n")


def test_llm_config():
    """测试 LLM 配置"""
    print("=" * 60)
    print("测试2: LLM 配置")
    print("=" * 60)
    
    from pydantic import SecretStr
    
    config = LLMConfig(
        api_key=SecretStr("test-api-key"),
        model="deepseek-chat",
        temperature=0.5
    )
    
    assert config.model == "deepseek-chat"
    assert config.temperature == 0.5
    assert config.api_key.get_secret_value() == "test-api-key"
    
    print(f"✅ 模型: {config.model}")
    print(f"✅ 温度: {config.temperature}")
    print(f"✅ API Key (隐藏): {config.api_key}")
    
    # 测试温度验证
    try:
        invalid_config = LLMConfig(temperature=3.0)
        print("❌ 应该抛出验证错误")
    except ValueError as e:
        print(f"✅ 温度验证正常: 拒绝无效值 3.0")
    
    print("\n✅ LLM 配置测试通过！\n")


def test_retrieval_config():
    """测试检索配置"""
    print("=" * 60)
    print("测试3: 检索配置")
    print("=" * 60)
    
    config = RetrievalConfig(
        mode="hybrid",
        top_k=5,
        chunk_size=1024,
        chunk_overlap=200
    )
    
    assert config.mode == "hybrid"
    assert config.top_k == 5
    assert config.chunk_size == 1024
    assert config.chunk_overlap == 200
    
    print(f"✅ 检索模式: {config.mode}")
    print(f"✅ Top K: {config.top_k}")
    print(f"✅ 分块大小: {config.chunk_size}")
    print(f"✅ 分块重叠: {config.chunk_overlap}")
    
    # 测试分块重叠验证
    try:
        invalid_config = RetrievalConfig(chunk_size=500, chunk_overlap=600)
        print("❌ 应该抛出验证错误")
    except ValueError as e:
        print(f"✅ 分块重叠验证正常: 拒绝重叠大于分块大小")
    
    print("\n✅ 检索配置测试通过！\n")


def test_settings():
    """测试主设置类"""
    print("=" * 60)
    print("测试4: Settings 主设置类")
    print("=" * 60)
    
    settings = Settings()
    
    print(f"✅ 检索模式: {settings.retrieval_mode}")
    print(f"✅ Top K: {settings.default_top_k}")
    print(f"✅ 使用 Qdrant: {settings.use_qdrant}")
    print(f"✅ 日志级别: {settings.log_level}")
    
    # 测试分组配置转换
    grouped = settings.to_grouped_config()
    assert "paths" in grouped
    assert "llm" in grouped
    assert "embedding" in grouped
    assert "retrieval" in grouped
    assert "vector_store" in grouped
    
    print(f"✅ 分组配置转换成功")
    
    print("\n✅ Settings 测试通过！\n")


def test_config_manager():
    """测试配置管理器"""
    print("=" * 60)
    print("测试5: ConfigManager 配置管理器")
    print("=" * 60)
    
    manager = get_config_manager()
    
    # 测试单例
    manager2 = get_config_manager()
    assert manager is manager2, "ConfigManager 应该是单例"
    print("✅ 单例模式正常")
    
    # 测试分组访问
    assert manager.paths is not None
    assert manager.llm is not None
    assert manager.embedding is not None
    assert manager.retrieval is not None
    assert manager.vector_store is not None
    
    print(f"✅ 路径配置访问正常")
    print(f"✅ LLM 配置访问正常")
    print(f"✅ Embedding 配置访问正常")
    print(f"✅ 检索配置访问正常")
    print(f"✅ 向量存储配置访问正常")
    
    # 测试配置验证
    errors = manager.validate()
    print(f"✅ 配置验证完成, 错误数: {len(errors)}")
    if errors:
        for error in errors:
            print(f"   ⚠️  {error}")
    
    # 测试配置显示
    display = manager.display()
    assert "索引存储路径" in display
    assert "LLM 模型" in display
    print(f"✅ 配置显示正常")
    
    print("\n✅ ConfigManager 测试通过！\n")


def test_hot_reload():
    """测试热重载"""
    print("=" * 60)
    print("测试6: 配置热重载")
    print("=" * 60)
    
    manager = get_config_manager()
    
    # 记录当前加载时间
    last_load_time = manager._last_load_time
    
    # 执行热重载
    reload_config()
    
    # 验证加载时间更新
    assert manager._last_load_time >= last_load_time, "加载时间应该更新"
    print(f"✅ 热重载完成")
    print(f"   原加载时间: {last_load_time}")
    print(f"   新加载时间: {manager._last_load_time}")
    
    print("\n✅ 热重载测试通过！\n")


def test_get_config_manager():
    """测试 get_config_manager 函数"""
    print("=" * 60)
    print("测试7: get_config_manager 使用方式")
    print("=" * 60)
    
    # 获取配置管理器
    config = get_config_manager()
    
    # 测试分组访问（新的标准访问方式）
    print(f"✅ config.llm.model: {config.llm.model}")
    print(f"✅ config.retrieval.mode: {config.retrieval.mode}")
    print(f"✅ config.retrieval.chunk_size: {config.retrieval.chunk_size}")
    print(f"✅ config.paths.knowledge_dir: {config.paths.knowledge_dir}")
    print(f"✅ config.paths.vector_storage_dir: {config.paths.vector_storage_dir}")
    
    # 测试 get_api_key() 方法
    llm_api_key = config.llm.get_api_key()
    embedding_api_key = config.embedding.get_api_key()
    print(f"✅ config.llm.get_api_key() 正常 (有值: {bool(llm_api_key)})")
    print(f"✅ config.embedding.get_api_key() 正常 (有值: {bool(embedding_api_key)})")
    
    # 测试便捷属性
    print(f"✅ config.paths.log_file: {config.paths.log_file}")
    print(f"✅ config.vector_store.use_qdrant: {config.vector_store.use_qdrant}")
    
    # 测试方法
    config_info = config.display()
    assert isinstance(config_info, dict)
    print(f"✅ config.display() 正常")
    
    config.ensure_directories()
    print(f"✅ config.ensure_directories() 正常")
    
    print("\n✅ get_config_manager 使用测试通过！\n")


def run_all_tests():
    """运行所有测试"""
    print("\n" + "=" * 60)
    print("开始运行配置管理测试")
    print("=" * 60 + "\n")
    
    try:
        test_path_config()
        test_llm_config()
        test_retrieval_config()
        test_settings()
        test_config_manager()
        test_hot_reload()
        test_get_config_manager()
        
        print("=" * 60)
        print("🎉 所有测试通过！")
        print("=" * 60)
        
    except AssertionError as e:
        print(f"\n❌ 测试失败: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)
    except Exception as e:
        print(f"\n⚠️  测试出现异常: {e}")
        import traceback
        traceback.print_exc()


if __name__ == "__main__":
    run_all_tests()
