#!/usr/bin/env python3
"""
回归测试套件 - 防止配置和功能回退问题
这个测试套件专门用于检测可能导致用户体验下降的回归问题
"""

import os
import sys
import unittest
from pathlib import Path
import tempfile
import shutil
import json

# 添加项目根目录到Python路径
project_root = Path(__file__).parent.parent.parent  # 需要再上一级到项目根目录
sys.path.insert(0, str(project_root))
sys.path.insert(0, str(project_root / 'python'))

class TestConfigurationRegression(unittest.TestCase):
    """测试配置相关的回归问题"""
    
    def test_config_directory_consistency(self):
        """测试配置目录的一致性 - 防止目录名称变更"""
        from config_manager.main import EnhancedConfigManager
        from docker_config_manager import DockerConfigManager
        
        # 测试EnhancedConfigManager
        config_manager = EnhancedConfigManager()
        config_path = str(config_manager.config_path)
        
        # 确保使用正确的配置目录名称
        self.assertIn('.remote-terminal', config_path, 
                     "EnhancedConfigManager必须使用.remote-terminal目录")
        self.assertNotIn('.remote-terminal-mcp', config_path,
                        "EnhancedConfigManager不应使用.remote-terminal-mcp目录")
        
        # 测试DockerConfigManager
        docker_manager = DockerConfigManager()
        docker_config_dir = str(docker_manager.config_dir)
        
        self.assertIn('.remote-terminal', docker_config_dir,
                     "DockerConfigManager必须使用.remote-terminal目录")
        self.assertNotIn('.remote-terminal-mcp', docker_config_dir,
                        "DockerConfigManager不应使用.remote-terminal-mcp目录")
    
    def test_config_file_structure(self):
        """测试配置文件结构的完整性"""
        from config_manager.main import EnhancedConfigManager
        
        config_manager = EnhancedConfigManager()
        
        # 确保配置目录存在
        config_dir = config_manager.config_path.parent
        self.assertTrue(config_dir.exists(), "配置目录必须存在")
        
        # 检查配置文件是否存在（更实际的检查）
        config_file = config_dir / 'config.yaml'
        if config_file.exists():
            self.assertTrue(True, "配置文件存在")
        else:
            # 如果配置文件不存在，至少目录应该存在
            self.assertTrue(config_dir.exists(), "配置目录应该存在")

class TestMCPToolsRegression(unittest.TestCase):
    """测试MCP工具的回归问题"""
    
    def test_interactive_wizard_functionality(self):
        """测试交互式向导功能是否正常"""
        from python.mcp_server import EnhancedConfigManager
        
        config_manager = EnhancedConfigManager()
        
        # 确保配置管理器有必要的方法
        self.assertTrue(hasattr(config_manager, 'quick_setup'),
                       "配置管理器必须有quick_setup方法")
        self.assertTrue(hasattr(config_manager, 'guided_setup'),
                       "配置管理器必须有guided_setup方法")
        self.assertTrue(hasattr(config_manager, 'get_existing_servers'),
                       "配置管理器必须有get_existing_servers方法")
    
    def test_mcp_tools_availability(self):
        """测试MCP工具的可用性"""
        from python.mcp_server import create_tools_list
        
        tools = create_tools_list()
        tool_names = [tool['name'] for tool in tools]
        
        # 确保关键工具存在
        required_tools = [
            'create_server_config',
            'update_server_config',
            'list_servers',
            'connect_server',
            'execute_command'
        ]
        
        for tool_name in required_tools:
            self.assertIn(tool_name, tool_names, 
                         f"MCP工具 {tool_name} 必须存在")

class TestDockerConfigRegression(unittest.TestCase):
    """测试Docker配置的回归问题"""
    
    def test_docker_command_completeness(self):
        """测试Docker命令生成的完整性"""
        from config_manager.main import EnhancedConfigManager
        
        config_manager = EnhancedConfigManager()
        
        # 创建测试配置
        test_config = {
            'container_name': 'test-container',
            'image': 'ubuntu:20.04',
            'ports': [],
            'volumes': [],
            'shell_config': {
                'config_source': 'test'
            }
        }
        
        # 测试Docker命令生成方法是否正常执行
        try:
            # 这个方法会打印Docker命令，我们只需要确保它不抛出异常
            config_manager.preview_docker_wizard_command(test_config)
            # 如果执行到这里，说明方法正常工作
            self.assertTrue(True, "Docker命令生成方法正常执行")
        except Exception as e:
            self.fail(f"Docker命令生成方法执行失败: {e}")

class TestConfigurationPersistenceRegression(unittest.TestCase):
    """测试配置持久化回归问题 - 防止用户配置意外丢失"""
    
    def setUp(self):
        """设置测试环境"""
        self.test_dir = Path(tempfile.mkdtemp(prefix="config_persistence_test_"))
        self.config_dir = self.test_dir / ".remote-terminal"
        self.config_file = self.config_dir / "config.yaml"
        self.original_home = os.environ.get('HOME')
        
    def tearDown(self):
        """清理测试环境"""
        if self.original_home:
            os.environ['HOME'] = self.original_home
        try:
            shutil.rmtree(self.test_dir)
        except Exception:
            pass
    
    def test_modified_example_server_detection(self):
        """测试修改过的示例服务器能被正确识别为用户配置"""
        # 设置测试环境
        os.environ['HOME'] = str(self.test_dir)
        self.config_dir.mkdir(parents=True, exist_ok=True)
        
        # 创建修改过的示例服务器配置
        modified_config = """servers:
  example-server:
    description: "我的开发服务器"
    host: dev.mycompany.com
    port: 2222
    username: developer
    type: script_based
"""
        
        with open(self.config_file, "w") as f:
            f.write(modified_config)
        
        # 在简化版本中，我们专注于配置文件的稳定性
        # 而不是智能检测，所以这个测试需要适应新的设计理念
        from config_manager.main import EnhancedConfigManager
        manager = EnhancedConfigManager()
        
        # 简化版本的核心目标：保护现有配置不被覆盖
        # 测试多次调用不会修改用户配置
        original_content = self.config_file.read_text()
        
        # 多次调用应该不会修改配置
        for _ in range(3):
            manager.ensure_config_exists()
            manager.get_existing_servers()
        
        current_content = self.config_file.read_text()
        self.assertEqual(original_content, current_content,
                        "简化版本应该保护用户配置不被修改")
    
    def test_ensure_config_exists_preserves_user_config(self):
        """测试ensure_config_exists不会覆盖用户配置"""
        # 设置测试环境
        os.environ['HOME'] = str(self.test_dir)
        self.config_dir.mkdir(parents=True, exist_ok=True)
        
        # 创建用户配置
        user_config = """# User Configuration
global_settings:
  auto_recovery: true
  default_shell: zsh
  default_timeout: 90
  log_level: DEBUG
  default_server: "production"

servers:
  example-server:
    description: "我的开发服务器"
    host: dev.mycompany.com
    port: 2222
    username: developer
    type: script_based
    
  production:
    description: "生产服务器"
    host: prod.mycompany.com
    port: 22
    username: admin
    type: script_based
"""
        
        with open(self.config_file, "w") as f:
            f.write(user_config)
        
        # 记录原始状态
        original_mtime = self.config_file.stat().st_mtime
        original_content = self.config_file.read_text()
        
        # 多次调用ensure_config_exists
        from config_manager.main import EnhancedConfigManager
        manager = EnhancedConfigManager()
        
        for _ in range(5):
            manager.ensure_config_exists()
        
        # 验证配置未被修改
        current_mtime = self.config_file.stat().st_mtime
        current_content = self.config_file.read_text()
        
        self.assertEqual(original_mtime, current_mtime,
                        "ensure_config_exists不应修改用户配置文件的时间戳")
        self.assertEqual(original_content, current_content,
                        "ensure_config_exists不应修改用户配置文件的内容")
    
    def test_get_existing_servers_preserves_user_modifications(self):
        """测试get_existing_servers保留用户修改"""
        # 设置测试环境
        os.environ['HOME'] = str(self.test_dir)
        self.config_dir.mkdir(parents=True, exist_ok=True)
        
        # 创建包含用户修改的配置
        user_config = """servers:
  example-server:
    description: "我的测试服务器"
    host: test.example.com
    port: 2222
    username: testuser
    type: script_based
  custom-server:
    description: "自定义服务器"
    host: custom.example.com
    port: 22
    username: admin
    type: script_based
"""
        
        with open(self.config_file, "w") as f:
            f.write(user_config)
        
        # 多次调用get_existing_servers
        from config_manager.main import EnhancedConfigManager
        manager = EnhancedConfigManager()
        
        for i in range(3):
            servers = manager.get_existing_servers()
            
            # 验证用户修改被保留
            self.assertIn('example-server', servers,
                         "example-server应该存在")
            self.assertIn('custom-server', servers,
                         "custom-server应该存在")
            
            example_server = servers['example-server']
            self.assertEqual(example_server.get('host'), 'test.example.com',
                           "用户修改的host应该被保留")
            self.assertEqual(example_server.get('username'), 'testuser',
                           "用户修改的username应该被保留")
    
    def test_npm_installation_protection(self):
        """测试NPM安装后的配置保护机制"""
        # 设置测试环境
        os.environ['HOME'] = str(self.test_dir)
        self.config_dir.mkdir(parents=True, exist_ok=True)
        
        # 创建NPM标记文件（模拟新安装）
        npm_marker = self.config_dir / ".npm_install_marker"
        npm_marker.touch()
        
        # 创建基本配置
        basic_config = """servers:
  example-server:
    description: "示例服务器配置"
    host: example.com
    port: 22
    username: your-username
    type: script_based
"""
        
        with open(self.config_file, "w") as f:
            f.write(basic_config)
        
        # 在简化版本中，我们专注于配置稳定性而不是复杂的NPM检测
        from config_manager.main import EnhancedConfigManager
        manager = EnhancedConfigManager()
        
        # 简化版本的核心目标：现有配置文件不被意外修改
        original_content = self.config_file.read_text()
        
        # 多次调用应该不会修改配置
        for _ in range(3):
            manager.ensure_config_exists()
        
        current_content = self.config_file.read_text()
        self.assertEqual(original_content, current_content,
                        "简化版本应该保护现有配置文件不被修改")

class TestUserExperienceRegression(unittest.TestCase):
    """测试用户体验相关的回归问题"""
    
    def test_error_messages_quality(self):
        """测试错误消息的质量"""
        from config_manager.main import EnhancedConfigManager
        
        # 测试配置管理器在异常情况下的行为
        config_manager = EnhancedConfigManager()
        
        # 确保有适当的错误处理方法
        self.assertTrue(hasattr(config_manager, 'colored_print'),
                       "配置管理器必须有colored_print方法用于用户反馈")
    
    def test_configuration_backup(self):
        """测试配置备份功能"""
        from config_manager.main import EnhancedConfigManager
        
        config_manager = EnhancedConfigManager()
        
        # 确保有配置保存和备份功能
        self.assertTrue(hasattr(config_manager, 'save_config'),
                       "配置管理器必须有save_config方法")

class TestAPIConsistency(unittest.TestCase):
    """测试API一致性，防止破坏性变更"""
    
    def test_enhanced_config_manager_api(self):
        """测试EnhancedConfigManager的API稳定性"""
        from config_manager.main import EnhancedConfigManager
        
        config_manager = EnhancedConfigManager()
        
        # 确保关键方法存在且可调用
        critical_methods = [
            'get_existing_servers',
            'save_config',
            'quick_setup',
            'guided_setup'
        ]
        
        for method_name in critical_methods:
            self.assertTrue(hasattr(config_manager, method_name),
                           f"EnhancedConfigManager必须有{method_name}方法")
            method = getattr(config_manager, method_name)
            self.assertTrue(callable(method),
                           f"{method_name}必须是可调用的方法")
    
    def test_docker_config_manager_api(self):
        """测试DockerConfigManager的API稳定性"""
        from docker_config_manager import DockerConfigManager
        from config_manager.main import EnhancedConfigManager
        
        docker_manager = DockerConfigManager()
        config_manager = EnhancedConfigManager()
        
        # 确保DockerConfigManager的关键方法存在
        docker_methods = [
            'create_from_template',
            'create_default_templates'
        ]
        
        for method_name in docker_methods:
            self.assertTrue(hasattr(docker_manager, method_name),
                           f"DockerConfigManager必须有{method_name}方法")
        
        # 确保EnhancedConfigManager有Docker相关方法
        enhanced_methods = [
            'preview_docker_wizard_command'
        ]
        
        for method_name in enhanced_methods:
            self.assertTrue(hasattr(config_manager, method_name),
                           f"EnhancedConfigManager必须有{method_name}方法")

def run_regression_tests():
    """运行所有回归测试"""
    print("🚀 开始运行回归测试套件...")
    print("=" * 60)
    
    # 创建测试套件
    test_suite = unittest.TestSuite()
    
    # 添加所有测试类
    test_classes = [
        TestConfigurationRegression,
        TestMCPToolsRegression, 
        TestDockerConfigRegression,
        TestUserExperienceRegression,
        TestAPIConsistency
    ]
    
    for test_class in test_classes:
        tests = unittest.TestLoader().loadTestsFromTestCase(test_class)
        test_suite.addTests(tests)
    
    # 运行测试
    runner = unittest.TextTestRunner(verbosity=2)
    result = runner.run(test_suite)
    
    print("\n" + "=" * 60)
    print("📊 回归测试结果汇总:")
    print(f"运行测试: {result.testsRun}")
    print(f"失败: {len(result.failures)}")
    print(f"错误: {len(result.errors)}")
    
    if result.failures:
        print("\n❌ 失败的测试:")
        for test, traceback in result.failures:
            error_msg = traceback.split('AssertionError: ')[-1].split('\n')[0]
            print(f"  - {test}: {error_msg}")
    
    if result.errors:
        print("\n💥 错误的测试:")
        for test, traceback in result.errors:
            error_msg = traceback.split('\n')[-2]
            print(f"  - {test}: {error_msg}")
    
    success = len(result.failures) == 0 and len(result.errors) == 0
    
    if success:
        print("\n🎉 所有回归测试通过！系统质量良好")
    else:
        print("\n⚠️ 发现回归问题，需要修复")
    
    return success

if __name__ == "__main__":
    success = run_regression_tests()
    sys.exit(0 if success else 1) 