#  @line_count 250
"""测试生成引擎模块"""
import json
import re
from typing import List, Dict, Any, Optional, Callable
from .json_parser import JSONParser
from .api_client import APIClient
from .prompt_manager import PromptManager


class TestGenerator:
    """测试项和测试用例生成器"""
    
    def __init__(self, json_path: str, api_client: Optional[APIClient] = None, 
                 prompt_manager: Optional[PromptManager] = None):
        """
        初始化测试生成器
        
        Args:
            json_path: JSON文档路径
            api_client: API客户端实例
            prompt_manager: Prompt管理器实例
        """
        self.parser = JSONParser(json_path)
        self.api_client = api_client or APIClient()
        self.prompt_manager = prompt_manager or PromptManager()
        self.test_items: List[Dict[str, Any]] = []
        self.test_cases: List[Dict[str, Any]] = []
        self.test_case_counter = 0
    
    def generate_test_items(self, function_points: Optional[List[Dict[str, Any]]] = None,
                           progress_callback: Optional[Callable] = None) -> List[Dict[str, Any]]:
        """
        生成测试项
        
        Args:
            function_points: 功能点列表，如果为None则自动提取
            progress_callback: 进度回调函数 (current, total, message)
        
        Returns:
            测试项列表
        """
        if function_points is None:
            function_points = self.parser.extract_function_points()
        
        test_items = []
        total = len(function_points)
        
        for idx, func_point in enumerate(function_points):
            if progress_callback:
                progress_callback(idx + 1, total, f"正在生成测试项: {func_point['function_name']}")
            
            try:
                # 构建功能描述
                function_description = self._build_function_description(func_point)
                
                # 格式化prompt
                prompt = self.prompt_manager.format_prompt(
                    'test_item',
                    function_description=function_description,
                    module_name=func_point['module_name']
                )
                
                # 调用API
                response = self.api_client.call_api(prompt)
                
                # 解析响应
                test_items_for_func = self._parse_test_items_response(response, func_point)
                test_items.extend(test_items_for_func)
                
            except Exception as e:
                # 如果生成失败，创建一个默认测试项
                test_items.append({
                    'id': f"TI-{len(test_items) + 1:03d}",
                    'name': f"{func_point['function_name']}功能测试",
                    'module_name': func_point['module_name'],
                    'function_name': func_point['function_name'],
                    'test_type': '功能测试',
                    'priority': '中',
                    'test_objective': f"测试{func_point['function_name']}功能是否正常工作",
                    'error': str(e)
                })
        
        self.test_items = test_items
        return test_items
    
    def generate_test_cases(self, test_items: Optional[List[Dict[str, Any]]] = None,
                          progress_callback: Optional[Callable] = None) -> List[Dict[str, Any]]:
        """
        为测试项生成测试用例
        
        Args:
            test_items: 测试项列表，如果为None则使用已生成的测试项
            progress_callback: 进度回调函数
        
        Returns:
            测试用例列表
        """
        if test_items is None:
            test_items = self.test_items
        
        if not test_items:
            raise ValueError("没有可用的测试项，请先生成测试项")
        
        test_cases = []
        total = len(test_items)
        
        for idx, test_item in enumerate(test_items):
            if progress_callback:
                progress_callback(idx + 1, total, f"正在生成测试用例: {test_item['name']}")
            
            try:
                # 获取功能点信息
                function_points = self.parser.extract_function_points()
                func_point = next(
                    (fp for fp in function_points if fp['function_name'] == test_item.get('function_name', '')),
                    None
                )
                
                if not func_point:
                    continue
                
                function_description = self._build_function_description(func_point)
                
                # 格式化prompt
                prompt = self.prompt_manager.format_prompt(
                    'test_case',
                    test_item_name=test_item['name'],
                    test_type=test_item.get('test_type', '功能测试'),
                    module_name=test_item['module_name'],
                    function_description=function_description
                )
                
                # 调用API
                response = self.api_client.call_api(prompt)
                
                # 解析响应
                cases_for_item = self._parse_test_cases_response(response, test_item)
                test_cases.extend(cases_for_item)
                
            except Exception as e:
                # 如果生成失败，创建一个默认测试用例
                self.test_case_counter += 1
                test_cases.append({
                    'id': f"TC-{self.test_case_counter:03d}",
                    'test_item_id': test_item.get('id', ''),
                    'name': f"{test_item['name']} - 基础功能验证",
                    'module_name': test_item['module_name'],
                    'preconditions': '系统正常运行',
                    'test_steps': ['步骤1：打开功能模块', '步骤2：执行操作', '步骤3：验证结果'],
                    'expected_result': '功能正常工作',
                    'priority': test_item.get('priority', '中'),
                    'test_type': test_item.get('test_type', '功能测试'),
                    'error': str(e)
                })
        
        self.test_cases = test_cases
        return test_cases
    
    def generate_batch(self, function_points: Optional[List[Dict[str, Any]]] = None,
                      progress_callback: Optional[Callable] = None) -> Dict[str, List[Dict[str, Any]]]:
        """
        批量生成测试项和测试用例（一次性生成）
        
        Args:
            function_points: 功能点列表
            progress_callback: 进度回调函数
        
        Returns:
            包含test_items和test_cases的字典
        """
        if function_points is None:
            function_points = self.parser.extract_function_points()
        
        all_test_items = []
        all_test_cases = []
        total = len(function_points)
        self.test_case_counter = 0
        
        for idx, func_point in enumerate(function_points):
            if progress_callback:
                progress_callback(idx + 1, total, f"正在生成: {func_point['function_name']}")
            
            try:
                # 转换为requirement格式（如果使用规范化Prompt）
                requirement = self._convert_to_requirement(func_point)
                
                # 尝试使用规范化Prompt（如果支持）
                if self.prompt_manager.use_standards:
                    prompt = self.prompt_manager.format_prompt(
                        'batch',
                        requirement=requirement
                    )
                else:
                    # 使用传统方式
                    function_description = self._build_function_description(func_point)
                    prompt = self.prompt_manager.format_prompt(
                        'batch',
                        function_description=function_description,
                        module_name=func_point['module_name']
                    )
                
                # 调用API
                response = self.api_client.call_api(prompt)
                
                # 解析批量响应
                result = self._parse_batch_response(response, func_point)
                all_test_items.extend(result['test_items'])
                all_test_cases.extend(result['test_cases'])
                
            except Exception as e:
                # 创建默认测试项和测试用例
                item_id = f"TI-{len(all_test_items) + 1:03d}"
                all_test_items.append({
                    'id': item_id,
                    'name': f"{func_point['function_name']}功能测试",
                    'module_name': func_point['module_name'],
                    'function_name': func_point['function_name'],
                    'test_type': '功能测试',
                    'priority': '中',
                    'test_objective': f"测试{func_point['function_name']}功能",
                    'error': str(e)
                })
                
                self.test_case_counter += 1
                all_test_cases.append({
                    'id': f"TC-{self.test_case_counter:03d}",
                    'test_item_id': item_id,
                    'name': f"{func_point['function_name']} - 基础验证",
                    'module_name': func_point['module_name'],
                    'preconditions': '系统正常运行',
                    'test_steps': ['执行功能操作', '验证结果'],
                    'expected_result': '功能正常',
                    'priority': '中',
                    'test_type': '功能测试',
                    'error': str(e)
                })
        
        self.test_items = all_test_items
        self.test_cases = all_test_cases
        
        return {
            'test_items': all_test_items,
            'test_cases': all_test_cases
        }
    
    def _build_function_description(self, func_point: Dict[str, Any]) -> str:
        """构建功能描述文本"""
        parts = []
        
        if func_point.get('module_description'):
            parts.append(f"模块描述：{func_point['module_description']}")
        
        if func_point.get('description'):
            parts.append(f"功能描述：{func_point['description']}")
        
        if func_point.get('operation_steps'):
            parts.append(f"操作步骤：{'；'.join(func_point['operation_steps'])}")
        
        return '\n'.join(parts) if parts else func_point.get('function_name', '')
    
    def _parse_test_items_response(self, response: str, func_point: Dict[str, Any]) -> List[Dict[str, Any]]:
        """解析测试项API响应"""
        try:
            # 尝试提取JSON
            json_str = self._extract_json_from_response(response)
            data = json.loads(json_str)
            
            test_items = []
            for idx, item in enumerate(data.get('test_items', [])):
                test_items.append({
                    'id': f"TI-{len(self.test_items) + len(test_items) + 1:03d}",
                    'name': item.get('name', ''),
                    'module_name': func_point['module_name'],
                    'function_name': func_point['function_name'],
                    'test_type': item.get('test_type', '功能测试'),
                    'priority': item.get('priority', '中'),
                    'test_objective': item.get('test_objective', '')
                })
            
            return test_items if test_items else [self._create_default_test_item(func_point)]
            
        except Exception:
            return [self._create_default_test_item(func_point)]
    
    def _parse_test_cases_response(self, response: str, test_item: Dict[str, Any]) -> List[Dict[str, Any]]:
        """解析测试用例API响应"""
        try:
            json_str = self._extract_json_from_response(response)
            data = json.loads(json_str)
            
            test_cases = []
            for case in data.get('test_cases', []):
                self.test_case_counter += 1
                test_cases.append({
                    'id': f"TC-{self.test_case_counter:03d}",
                    'test_item_id': test_item.get('id', ''),
                    'name': case.get('name', ''),
                    'module_name': test_item['module_name'],
                    'preconditions': case.get('preconditions', ''),
                    'test_steps': case.get('test_steps', []),
                    'expected_result': case.get('expected_result', ''),
                    'priority': case.get('priority', test_item.get('priority', '中')),
                    'test_type': case.get('test_type', test_item.get('test_type', '功能测试'))
                })
            
            return test_cases if test_cases else [self._create_default_test_case(test_item)]
            
        except Exception:
            return [self._create_default_test_case(test_item)]
    
    def _parse_batch_response(self, response: str, func_point: Dict[str, Any]) -> Dict[str, List[Dict[str, Any]]]:
        """解析批量生成API响应"""
        try:
            print("\n" + "-"*60)
            print("[解析响应] 开始解析API响应...")
            print(f"原始响应长度: {len(response)} 字符")
            
            json_str = self._extract_json_from_response(response)
            print(f"提取的JSON长度: {len(json_str)} 字符")
            
            data = json.loads(json_str)
            print(f"JSON解析成功！")
            print(f"  - test_items数量: {len(data.get('test_items', []))}")
            
            test_items = []
            test_cases = []
            
            for item_data in data.get('test_items', []):
                item_id = f"TI-{len(self.test_items) + len(test_items) + 1:03d}"
                test_item = {
                    'id': item_id,
                    'name': item_data.get('name', ''),
                    'module_name': func_point['module_name'],
                    'function_name': func_point['function_name'],
                    'test_type': item_data.get('test_type', '功能测试'),
                    'priority': item_data.get('priority', '中'),
                    'test_objective': item_data.get('test_objective', '')
                }
                test_items.append(test_item)
                print(f"  ✓ 测试项: {test_item['name']}")
                
                # 处理该测试项下的测试用例
                cases_in_item = item_data.get('test_cases', [])
                print(f"    - 测试用例数量: {len(cases_in_item)}")
                
                for case_data in cases_in_item:
                    self.test_case_counter += 1
                    test_cases.append({
                        'id': f"TC-{self.test_case_counter:03d}",
                        'test_item_id': item_id,
                        'name': case_data.get('name', ''),
                        'module_name': func_point['module_name'],
                        'preconditions': case_data.get('preconditions', ''),
                        'test_steps': case_data.get('test_steps', []),
                        'expected_result': case_data.get('expected_result', ''),
                        'priority': case_data.get('priority', test_item['priority']),
                        'test_type': case_data.get('test_type', test_item['test_type'])
                    })
            
            if not test_items:
                print("  ⚠️  没有解析到test_items，使用默认值")
                test_item = self._create_default_test_item(func_point)
                test_items.append(test_item)
                test_cases.append(self._create_default_test_case(test_item))
            
            print(f"[解析响应] 完成！共 {len(test_items)} 个测试项，{len(test_cases)} 个测试用例")
            print("-"*60 + "\n")
            
            return {
                'test_items': test_items,
                'test_cases': test_cases
            }
            
        except Exception as e:
            print("\n" + "-"*60)
            print(f"[解析响应] ❌ 解析失败！错误: {str(e)}")
            print(f"原始响应前500字符: {response[:500]}")
            print("-"*60 + "\n")
            
            test_item = self._create_default_test_item(func_point)
            return {
                'test_items': [test_item],
                'test_cases': [self._create_default_test_case(test_item)]
            }

    
    def _extract_json_from_response(self, response: str) -> str:
        """从API响应中提取JSON字符串"""
        # 尝试直接解析
        try:
            json.loads(response)
            return response
        except:
            pass
        
        # 尝试提取代码块中的JSON
        json_pattern = r'```(?:json)?\s*(\{.*?\})\s*```'
        match = re.search(json_pattern, response, re.DOTALL)
        if match:
            return match.group(1)
        
        # 尝试提取大括号中的内容
        brace_match = re.search(r'\{.*\}', response, re.DOTALL)
        if brace_match:
            return brace_match.group(0)
        
        raise ValueError("无法从响应中提取JSON")
    
    def _create_default_test_item(self, func_point: Dict[str, Any]) -> Dict[str, Any]:
        """创建默认测试项"""
        return {
            'id': f"TI-{len(self.test_items) + 1:03d}",
            'name': f"{func_point['function_name']}功能测试",
            'module_name': func_point['module_name'],
            'function_name': func_point['function_name'],
            'test_type': '功能测试',
            'priority': '中',
            'test_objective': f"测试{func_point['function_name']}功能是否正常工作"
        }
    
    def _create_default_test_case(self, test_item: Dict[str, Any]) -> Dict[str, Any]:
        """创建默认测试用例"""
        self.test_case_counter += 1
        return {
            'id': f"TC-{self.test_case_counter:03d}",
            'test_item_id': test_item.get('id', ''),
            'name': f"{test_item['name']} - 基础功能验证",
            'module_name': test_item['module_name'],
            'preconditions': '系统正常运行',
            'test_steps': ['步骤1：打开功能模块', '步骤2：执行操作', '步骤3：验证结果'],
            'expected_result': '功能正常工作',
            'priority': test_item.get('priority', '中'),
            'test_type': test_item.get('test_type', '功能测试')
        }
    
    def _convert_to_requirement(self, func_point: Dict[str, Any]) -> Dict[str, Any]:
        """
        将功能点转换为需求格式（用于规范化Prompt）
        
        Args:
            func_point: 功能点字典
            
        Returns:
            需求字典
        """
        requirement = {
            'requirement_id': func_point.get('requirement_id', func_point.get('function_name', '')),
            'requirement_type': func_point.get('requirement_type', '功能需求'),
            'description': func_point.get('description', func_point.get('function_name', '')),
            'module_name': func_point.get('module_name', '')
        }
        
        # 如果有接口信息，添加进去
        if func_point.get('interface_info'):
            requirement['interface_info'] = func_point['interface_info']
        
        return requirement

