#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
InterTool 类 - AI 审查工具类

负责 AI 审查结果的辅助计算和结果处理功能。
"""

import asyncio
import json
import re
from typing import Optional, Dict, Any, List, TypedDict
from langchain_core.messages import BaseMessage
from foundation.observability.logger.loggering import review_logger as logger

# 常量定义
RISK_LEVELS = {"high": "高风险", "medium": "中风险", "low": "低风险"}
DEFAULT_RISK_LEVEL = "medium"


class AIReviewState(TypedDict):
    """AI审查工作流状态"""

    file_id: str
    callback_task_id: str
    file_name: str
    user_id: str
    structured_content: Dict[str, Any]
    review_results: Optional[Dict[str, Any]]
    current_stage: str
    status: str
    error_message: Optional[str]
    progress_manager: Optional[Any]
    # 消息日志（用于LangGraph状态追踪）
    messages: List[BaseMessage]


class InterTool:
    """AI审查工具类 - 负责辅助计算和结果处理"""

    def _calculate_overall_risk(self, basic_result: Dict, technical_result: Dict, rag_result: Dict) -> str:
        """
        计算总体风险等级

        Args:
            basic_result: 基础合规性审查结果，包含overall_score字段
            technical_result: 技术性审查结果，包含overall_score字段
            rag_result: RAG增强审查结果（当前未使用）

        Returns:
            str: 风险等级 ("low", "medium", "high")

        Note:
            风险等级计算逻辑：
            - low: 基础和技术审查都达到90分以上
            - medium: 基础和技术审查都达到70分以上
            - high: 其他情况
            异常情况下返回默认风险等级medium
        """
        try:
            # 基于各种审查结果计算风险等级
            # 风险等级计算逻辑：基础和技术审查都达到90分以上为低风险，70分以上为中风险，否则为高风险
            basic_score = basic_result.get('overall_score', 0)
            technical_score = technical_result.get('overall_score', 0)

            if basic_score >= 90 and technical_score >= 90:
                return "low"
            elif basic_score >= 70 and technical_score >= 70:
                return "medium"
            else:
                return "high"
        except (KeyError, TypeError, ValueError) as e:
            logger.warning(f"风险等级计算异常: {str(e)}，使用默认风险等级")
            return DEFAULT_RISK_LEVEL

    def _aggregate_results(self, successful_results: List) -> Dict[str, Any]:
        """
        汇总审查结果（issues格式）

        Args:
            successful_results: 成功的审查结果列表，支持两种格式：
                - 嵌套列表格式：[[issue1, issue2], [issue3], ...]，每个单元返回一个issues列表
                - 扁平列表格式：[issue1, issue2, issue3, ...]，所有issues合并为扁平列表

        Returns:
            Dict[str, Any]: 汇总后的统计信息，包含以下字段：
                - risk_stats: 各风险等级的数量统计 {"low": 0, "medium": 0, "high": 0}
                - total_reviewed: 成功审查的总数量
                - total_issues: 总问题数量

        Note:
            当输入为空时返回空字典，异常时记录错误并返回空字典
            自动检测输入格式（嵌套列表 or 扁平列表）并分别处理
        """
        try:
            if not successful_results:
                return {}

            # 计算风险等级统计和问题总数
            risk_stats = {"low": 0, "medium": 0, "high": 0}
            total_issues = 0

            # 检测输入格式（通过第一个元素判断是扁平列表还是嵌套列表）
            is_flat_format = False
            if successful_results and len(successful_results) > 0:
                first_element = successful_results[0]
                if isinstance(first_element, dict):
                    # 第一个元素是字典，说明是扁平列表格式
                    is_flat_format = True
                    logger.debug(f"检测到扁平列表格式，总元素数: {len(successful_results)}")
                elif isinstance(first_element, list):
                    # 第一个元素是列表，说明是嵌套列表格式
                    logger.debug(f"检测到嵌套列表格式，总单元数: {len(successful_results)}")

            if is_flat_format:
                # 扁平列表格式: [issue1, issue2, issue3, ...]
                # 每个 issue 是一个 dict: {issue_id: {risk_summary: {...}, ...}}
                for issue in successful_results:
                    if isinstance(issue, dict):
                        for issue_data in issue.values():
                            risk_summary = issue_data.get('risk_summary', {})
                            max_risk = risk_summary.get('max_risk_level', '0')

                            if max_risk in risk_stats:
                                risk_stats[max_risk] += 1
                            elif max_risk == '0':
                                risk_stats['low'] += 1  # 无风险视为低风险

                total_issues = len(successful_results)
                total_reviewed = len(successful_results)

            else:
                # 嵌套列表格式: [[issue1, issue2], [issue3], ...]
                # 每个 unit_issues 是一个 issues 列表
                for unit_issues in successful_results:
                    if unit_issues and isinstance(unit_issues, list):
                        total_issues += len(unit_issues)

                        # 统计每个issue中的风险等级
                        for issue in unit_issues:
                            if isinstance(issue, dict):
                                # issue格式: {issue_id: {risk_summary: {...}}}
                                for issue_data in issue.values():
                                    risk_summary = issue_data.get('risk_summary', {})
                                    max_risk = risk_summary.get('max_risk_level', '0')

                                    if max_risk in risk_stats:
                                        risk_stats[max_risk] += 1
                                    elif max_risk == '0':
                                        risk_stats['low'] += 1  # 无风险视为低风险

                total_reviewed = len(successful_results)

            logger.info(f"结果汇总完成: total_issues={total_issues}, total_reviewed={total_reviewed}, risk_stats={risk_stats}")

            return {
                'risk_stats': risk_stats,
                'total_reviewed': total_reviewed,
                'total_issues': total_issues
            }
        except (ZeroDivisionError, KeyError, TypeError) as e:
            logger.error(f"结果汇总失败: {str(e)}")
            return {}

    def _format_review_results_to_issues(self, callback_task_id: str, unit_index: int, review_location_label: str,
                                        chapter_code:str,unit_content: Dict[str, Any], basic_result: Dict[str, Any],
                                        technical_result: Dict[str, Any], merged_results: Dict[str, Any] = None) -> List[Dict[str, Any]]:
        """
        将审查结果格式化为issues结构

        Args:
            callback_task_id: 回调任务ID，用于生成唯一issue_id
            unit_index: 单元索引，用于生成唯一issue_id
            review_location_label: 审查位置标签，如"第3页：第一章"
            chapter_code: 章节编码
            unit_content: 单元内容，包含原始文本等信息
            basic_result: 基础合规性审查结果，包含各项检查结果
            technical_result: 技术性审查结果，包含技术标准检查结果
            merged_results: 合并的审查结果（check_item 模式使用），如果提供则直接使用，忽略 basic_result 和 technical_result

        Returns:
            List[Dict]: 格式化后的issues列表，每个issue包含：
                - issue_id: 唯一标识符，格式为"{callback_task_id}-{risk_level}-{unit_index}"
                - metadata: 元数据，包含审查位置和原始内容
                - risk_summary: 风险摘要，包含最高风险等级和问题数量统计
                - review_lists: 详细审查问题列表

        Note:
            自动跳过overall_score字段，提取所有检查项的详细结果
            支持风险等级统计和最高风险等级确定
            check_item 模式：直接使用 merged_results，无需区分 basic_result 和 technical_result
        """
        TRCH_CHECK_ITEMS = [
            "non_parameter_compliance_check",
            "parameter_compliance_check",
        ]
        issues = []
        review_lists = []
        risk_count = {"high": 0, "medium": 0, "low": 0}
        max_risk_level = "low"

        # 合并所有审查结果
        all_results = {}

        # check_item 模式：如果提供了 merged_results，需要特殊处理
        if merged_results is not None:
            logger.debug(f"使用 check_item 模式的合并结果: {list(merged_results.keys()) if isinstance(merged_results, dict) else 'N/A'}")

            # 检查是否是 entity_based 模式
            if isinstance(merged_results, dict) and merged_results.get('review_mode') == 'entity_based' and 'entity_review_results' in merged_results:
                # entity_based 模式：需要提取嵌套的审查结果
                logger.debug(f"🔍 [DEBUG] merged_results 是 entity_based 模式，提取审查结果")
                entity_review_results = merged_results.get('entity_review_results', [])
                func_name = merged_results.get('func_name', '')

                for idx, entity_item in enumerate(entity_review_results):
                    entity = entity_item.get('entity', f'entity_{idx}')

                    # ✅ 实际结构：result 字段包含 ReviewResult 对象
                    if 'result' in entity_item:
                        result_key = f'{func_name}_{entity}_{idx}'  # 使用 func_name 作为键名前缀
                        all_results[result_key] = entity_item['result']
                        logger.debug(f"🔍 [DEBUG] 提取审查结果: {result_key}, 结果类型: {type(entity_item['result'])}")

                logger.debug(f"🔍 [DEBUG] entity_based 模式处理完成，共提取 {len(entity_review_results)} 个实体的审查结果")
            else:
                # 普通模式：直接使用 merged_results
                all_results.update(merged_results)
        else:
            # core_review 模式：合并 basic_result 和 technical_result
            if basic_result:
                logger.debug(f"🔍 [DEBUG] basic_result 类型: {type(basic_result)}, 键: {list(basic_result.keys()) if isinstance(basic_result, dict) else 'N/A'}")
                all_results.update(basic_result)

            if technical_result:
                logger.debug(f"🔍 [DEBUG] technical_result 类型: {type(technical_result)}, 键: {list(technical_result.keys()) if isinstance(technical_result, dict) else 'N/A'}")
                # 遍历 technical_result，处理可能的 entity_based 模式
                for tech_key, tech_value in technical_result.items():
                    if isinstance(tech_value, dict) and tech_value.get('review_mode') == 'entity_based':
                        # entity_based 模式：提取嵌套的审查结果
                        logger.debug(f"🔍 [DEBUG] technical_result[{tech_key}] 是 entity_based 模式，提取审查结果")
                        entity_review_results = tech_value.get('entity_review_results', [])
                        func_name = tech_value.get('func_name', tech_key)
                        
                        for idx, entity_item in enumerate(entity_review_results):
                            entity = entity_item.get('entity', f'entity_{idx}')
                            if 'result' in entity_item:
                                result_key = f'{func_name}_{entity}_{idx}'
                                all_results[result_key] = entity_item['result']
                                logger.debug(f"🔍 [DEBUG] 提取审查结果: {result_key}, 结果类型: {type(entity_item['result'])}")
                    else:
                        # 普通模式：直接添加
                        all_results[tech_key] = tech_value

        logger.debug(f"开始格式化审查结果，合并后结果: {list(all_results.keys())}")

        for check_key, check_result in all_results.items():
            logger.debug(f"处理检查项: {check_key}, 结果类型: {type(check_result)}")

            if check_key == 'overall_score':  # 跳过分数字段
                logger.debug(f"跳过分数字段: {check_key}")
                continue

            # 🔧 特殊处理：timeliness_basis_reviewer 和 reference_basis_reviewer 的返回格式
            if check_key == 'timeliness_basis_reviewer' and isinstance(check_result, dict):
                timeliness_data = check_result.get('timeliness_basis_review_results', {})
                batch_results = timeliness_data.get('review_results', [])
                logger.debug(f"🔍 [DEBUG] 处理时效性审查结果，批次数: {len(batch_results)}")
                
                for batch in batch_results:
                    if isinstance(batch, list):
                        # 批次是列表，遍历其中的每个 item
                        for item in batch:
                            if isinstance(item, dict):
                                review_lists.append({
                                    "check_item": item.get('check_item', 'timeliness_check'),
                                    "chapter_code": item.get('chapter_code', chapter_code),
                                    "check_item_code": item.get('check_item_code', f"{chapter_code}_timeliness_check"),
                                    "check_result": item.get('check_result', item),
                                    "exist_issue": item.get('exist_issue', False),
                                    "risk_info": item.get('risk_info', {"risk_level": "low"})
                                })
                    elif isinstance(batch, dict):
                        # 批次本身就是单个 item
                        review_lists.append({
                            "check_item": batch.get('check_item', 'timeliness_check'),
                            "chapter_code": batch.get('chapter_code', chapter_code),
                            "check_item_code": batch.get('check_item_code', f"{chapter_code}_timeliness_check"),
                            "check_result": batch.get('check_result', batch),
                            "exist_issue": batch.get('exist_issue', False),
                            "risk_info": batch.get('risk_info', {"risk_level": "low"})
                        })
                logger.info(f"🔍 时效性审查结果处理完成，添加 {len(review_lists)} 个问题项")
                continue
            
            if check_key == 'reference_basis_reviewer' and isinstance(check_result, dict):
                reference_data = check_result.get('reference_basis_review_results', {})
                batch_results = reference_data.get('review_results', [])
                logger.debug(f"🔍 [DEBUG] 处理规范性审查结果，批次数: {len(batch_results)}")

                for batch in batch_results:
                    if isinstance(batch, list):
                        for item in batch:
                            if isinstance(item, dict):
                                review_lists.append({
                                    "check_item": item.get('check_item', 'reference_check'),
                                    "chapter_code": item.get('chapter_code', chapter_code),
                                    "check_item_code": item.get('check_item_code', f"{chapter_code}_reference_check"),
                                    "check_result": item.get('check_result', item),
                                    "exist_issue": item.get('exist_issue', False),
                                    "risk_info": item.get('risk_info', {"risk_level": "low"})
                                })
                    elif isinstance(batch, dict):
                        review_lists.append({
                            "check_item": batch.get('check_item', 'reference_check'),
                            "chapter_code": batch.get('chapter_code', chapter_code),
                            "check_item_code": batch.get('check_item_code', f"{chapter_code}_reference_check"),
                            "check_result": batch.get('check_result', batch),
                            "exist_issue": batch.get('exist_issue', False),
                            "risk_info": batch.get('risk_info', {"risk_level": "low"})
                        })
                logger.info(f"🔍 规范性审查结果处理完成，添加 {len(review_lists)} 个问题项")
                continue

            # 🔧 特殊处理：timeliness_content_reviewer 的返回格式
            if check_key == 'timeliness_content_reviewer' and isinstance(check_result, dict):
                content_timeliness_data = check_result.get('timeliness_content_review_results', {})
                batch_results = content_timeliness_data.get('review_results', [])
                logger.debug(f"🔍 [DEBUG] 处理内容时效性审查结果，问题数: {len(batch_results)}")

                for item in batch_results:
                    if isinstance(item, dict):
                        review_lists.append({
                            "check_item": item.get('check_item', 'content_timeliness_check'),
                            "chapter_code": item.get('chapter_code', chapter_code),
                            "check_item_code": item.get('check_item_code', f"{chapter_code}_content_timeliness_check"),
                            "check_result": item.get('check_result', item),
                            "exist_issue": item.get('exist_issue', False),
                            "risk_info": item.get('risk_info', {"risk_level": "low"}),
                            "location_info": item.get('location_info', []),
                            "content_context": item.get('content_context', '')
                        })
                logger.info(f"🔍 内容时效性审查结果处理完成，添加 {len(batch_results)} 个问题项")
                continue

            # 🔧 类型安全检查：支持字典和 base_reviewer.ReviewResult 对象
            is_dict = isinstance(check_result, dict)
            is_review_result = hasattr(check_result, 'details') and hasattr(check_result, 'success')

            if not is_dict and not is_review_result:
                logger.warning(f"⚠️ 检查项 {check_key} 的结果类型不支持: {type(check_result).__name__}, 跳过")
                continue

            # 检查 check_result 是否为 None 或不包含 details
            if is_dict and (not check_result or "details" not in check_result):
                logger.debug(f"检查项 {check_key} 结果为空或缺少details字段，跳过")
                continue

            if is_review_result and not check_result.details:
                logger.warning(f"检查项 {check_key} 的 base_reviewer.ReviewResult 中 details 为空，跳过")
                continue

            # 根据类型获取 details
            details = check_result["details"] if is_dict else check_result.details

            check_name = details.get("name")
            if "response" in details:
                response = details["response"]
                check_name = details.get("name")
                reference_source = details.get("rag_reference_source")
                review_references = details.get("rag_review_references")




                # 类型安全检查：确保 check_name 是字符串
                if not isinstance(check_name, str):
                    logger.warning(f"check_name 类型异常: {type(check_name).__name__}, 值: {check_name}, 将跳过此检查项")
                    continue

                if check_name  not in TRCH_CHECK_ITEMS:
                    logger.debug(f"检查项 {check_name} 无参考来源，直接解析响应")

                    # 🔧 检查 response 是否已经是列表格式（如 completeness_check 返回的格式）
                    if isinstance(response, list):
                        check_issues = []
                        for issue_item in response:
                            if isinstance(issue_item, dict):
                                # 如果已经是标准格式（包含 check_item 字段），直接使用
                                if "check_item" in issue_item:
                                    check_issues.append(issue_item)
                                else:
                                    # 兼容旧格式：转换为标准格式
                                    formatted_issue = {
                                        "check_item": check_name,
                                        "chapter_code": details.get("chapter_code", chapter_code),
                                        "check_item_code": f"{details.get('chapter_code', chapter_code)}_{check_name}",
                                        "check_result": issue_item.get("issue_point", ""),
                                        "exist_issue": True,
                                        "risk_info": {"risk_level": issue_item.get("risk_level", "medium")},
                                        # 保留原始字段
                                        "location": issue_item.get("location", ""),
                                        "suggestion": issue_item.get("suggestion", ""),
                                        "reason": issue_item.get("reason", ""),
                                        "review_references": issue_item.get("review_references", ""),
                                        "reference_source": issue_item.get("reference_source", "")
                                    }
                                    check_issues.append(formatted_issue)
                        logger.debug(f"检查项 {check_name} 的 response 已是列表格式，直接处理 {len(check_issues)} 个问题项")
                    else:
                        # response 是字符串，使用原有的解析逻辑
                        check_issues = self.parse_ai_review_response(response, check_name, chapter_code)

                    # 将解析后的结果添加到review_lists中
                    for check_issue in check_issues:
                        if isinstance(check_issue, dict):
                            # 确保risk_info字段存在且正确
                            if "risk_info" not in check_issue:
                                check_issue["risk_info"] = {}

                            # 确保exist_issue字段存在
                            if "exist_issue" not in check_issue:
                                check_result = check_issue.get("check_result", "")
                                if isinstance(check_result, str) and "无明显问题" in check_result:
                                    check_issue["exist_issue"] = False
                                else:
                                    check_issue["exist_issue"] = True

                            review_lists.append(check_issue)

                else:
                    if reference_source and review_references:
                        logger.debug(f"RAG检查：检查项找到相关rag依据 {check_name} : {review_references}")
                    else:
                        logger.debug(f"RAG检查：检查项未找到相关rag依据 {check_name}")
                    logger.debug(f"检查项 {check_name} 存在参考来源，开始处理参考来源")
                    check_issues = self.parse_ai_review_response(response, check_name,chapter_code)
                    processed_issues = []

                    for idx, item in enumerate(check_issues):
                        if not isinstance(item, dict):
                            logger.warning(f"第 {idx} 个问题不是字典类型，跳过补充字段：{item}")
                            continue

                        # 处理包装格式的问题
                        if "check_result" in item and isinstance(item["check_result"], dict):
                            # 这是包装格式，提取实际的问题内容
                            issue_content = item["check_result"].copy()

                            # 添加参考来源到实际问题内容中
                            if review_references:
                                issue_content["review_references"] = review_references
                            else:
                                logger.debug(f"RAG检查：检查项找到相关review_references {check_name} ")
                            if reference_source:
                                issue_content["reference_source"] = reference_source
                            else:
                                logger.debug(f"RAG检查：检查项未找到相关reference_source {check_name} ")

                            # 更新包装格式中的check_result
                            item["check_result"] = issue_content
                            processed_issues.append(item)

                        elif "issue_point" in item:
                            # 这是直接的问题格式，直接添加参考来源
                            issue = item.copy()

                            if review_references:
                                issue["review_references"] = review_references
                            if reference_source:
                                issue["reference_source"] = reference_source

                            processed_issues.append(issue)
                        else:
                            logger.warning(f"第 {idx} 个问题格式不符合预期：{item}")
                            processed_issues.append(item)

                    # 计算风险等级并添加到review_lists
                    for processed_issue in processed_issues:
                        if isinstance(processed_issue, dict):
                            # 获取风险等级
                            if "check_result" in processed_issue and isinstance(processed_issue["check_result"], dict):
                                # 包装格式：从check_result内部获取风险等级
                                inner_risk = processed_issue["check_result"].get("risk_level", "low")
                                risk_level = self._convert_risk_level(inner_risk)
                            elif "risk_info" in processed_issue:
                                # 标准格式：从risk_info获取
                                outer_risk = processed_issue["risk_info"].get("risk_level", "low")
                                risk_level = outer_risk
                            elif "risk_level" in processed_issue:
                                # 直接格式：直接获取
                                direct_risk = processed_issue.get("risk_level", "low")
                                risk_level = self._convert_risk_level(direct_risk)
                            else:
                                risk_level = "low"

                            # 确保risk_info字段存在且正确
                            if "risk_info" not in processed_issue:
                                processed_issue["risk_info"] = {}
                            processed_issue["risk_info"]["risk_level"] = risk_level

                            review_lists.append(processed_issue)
            else:
                logger.warning(f"检查项 {check_key} 格式不符合要求，缺少details或response字段")
                logger.warning(f"check_result内容: {check_result}")

        # 统计风险等级
        for issue in review_lists:
            risk_level = issue.get("risk_info", {}).get("risk_level", "low")
            if risk_level in risk_count:
                risk_count[risk_level] += 1

        # 确定最高风险等级
        if risk_count["high"] > 0:
            max_risk_level = "high"
        elif risk_count["medium"] > 0:
            max_risk_level = "medium"

        # 如果有审查结果，创建issue
        if review_lists:
            issue_id = f"{callback_task_id}-{max_risk_level if max_risk_level else '0'}-{unit_index}"
            issue = {
                issue_id: {
                    "metadata": {
                        "review_location_label": review_location_label,
                        "original_content": unit_content.get('content', '')
                    },
                    "risk_summary": {
                        "max_risk_level": max_risk_level if max_risk_level else '0',
                        "risk_count": risk_count if risk_count else 0
                    },
                    "review_lists": review_lists
                }
            }
            issues.append(issue)

        return issues

    def parse_ai_review_response(self, response: str, check_name: str,chapter_code:str) -> List[Dict[str, Any]]:
        """
        解析AI审查的JSON格式响应

        Args:
            response: AI审查响应内容
            check_name: 检查项名称（如"词句语法检查"）
            chapter_code: 章节编码

        Returns:
            List[Dict]: 解析后的审查结果列表，包含check_item、check_result、exist_issue、risk_info等字段

        Note:
            支持识别"无明显问题"等关键词，自动设置风险等级
            解析新的英文键名JSON格式: issue_point, location, suggestion, reason, risk_level
        """
        review_lists = []
        check_item_code = chapter_code+"_"+check_name
        try:
            # 1. 检查无问题情况
            if any(keyword in response for keyword in ["无明显问题", "无问题", "符合要求","无风险"]):
                return [{
                    "check_item": check_name,
                    "chapter_code": chapter_code,
                    "check_item_code": check_item_code,
                    "check_result": "无明显问题",
                    "exist_issue": False,
                    "risk_info": {"risk_level": "low"}
                }]

            # 2. 尝试提取和解析JSON
            json_data = self._extract_json_data(response)
            if json_data:
                # 处理数组格式 - 保存调试数据
                if isinstance(json_data, list):
                    for issue_data in json_data:
                        review_lists.append(self._create_issue_item(issue_data, check_name, chapter_code,check_item_code))
                # 处理对象格式
                elif isinstance(json_data, dict):
                    review_lists.append(self._create_issue_item(json_data, check_name, chapter_code,check_item_code))

            # 3. 如果JSON解析失败，回退到文本解析
            if not review_lists:
                # 🔧 修复：检查响应是否为空或只包含空白字符
                response_stripped = response.strip() if isinstance(response, str) else ""
                is_empty_response = not response_stripped or response_stripped in ["", "null", "None", "undefined"]

                risk_level = self._determine_risk_level(response)

                # 如果响应为空，则设置 exist_issue=False
                review_lists.append({
                    "check_item": check_name,
                    "chapter_code": chapter_code,
                    "check_item_code": check_item_code,
                    "check_result": response,
                    "exist_issue": not is_empty_response,  # 🔧 修复：空响应不存在问题
                    "risk_info": {"risk_level": risk_level}
                })

        except Exception as e:
            logger.error(f"解析AI审查响应失败: {str(e)}")
            review_lists.append({
                "check_item": check_name,
                "chapter_code": chapter_code,
                "check_item_code": check_item_code,
                "check_result": response,
                "exist_issue": True,
                "risk_info": {"risk_level": "low"}
            })

        return review_lists

    def _extract_json_data(self, response):
        """
        从响应中提取JSON数据，合并所有提取策略

        Args:
            response: 可以是字符串、列表或字典

        Returns:
            提取的JSON数据（列表或字典），如果提取失败返回None
        """
        try:
            # 如果 response 已经是列表或字典，直接返回
            if isinstance(response, (list, dict)):
                return response

            # 确保 response 是字符串
            if not isinstance(response, str):
                logger.warning(f"响应类型错误: {type(response)}, 期望字符串")
                return None

            # 尝试直接解析整个响应
            response_stripped = response.strip()
            if ((response_stripped.startswith('{') and response_stripped.endswith('}')) or
                (response_stripped.startswith('[') and response_stripped.endswith(']'))):
                try:
                    return json.loads(response_stripped)
                except json.JSONDecodeError:
                    pass

            # 尝试从代码块中提取JSON
            code_block_patterns = [
                r'```json\s*(\[[\s\S]*?\]|\{[\s\S]*?\})\s*```',
                r'```(?:json)?\s*(\{[\s\S]*?\})\s*```',
                r'```json\s*(.*?)\s*```'
            ]

            for pattern in code_block_patterns:
                matches = re.findall(pattern, response, re.DOTALL)
                if matches:
                    for match in matches:
                        # 确保 match 是字符串
                        if isinstance(match, str):
                            try:
                                return json.loads(match.strip())
                            except json.JSONDecodeError:
                                continue
                        # 如果 match 是列表/元组（多捕获组），取第一个元素
                        elif isinstance(match, (list, tuple)) and len(match) > 0:
                            try:
                                return json.loads(str(match[0]).strip())
                            except (json.JSONDecodeError, IndexError):
                                continue

            # 尝试模式匹配提取JSON
            json_patterns = [
                r"(\{[\s\S]*\}|\[[\s\S]*\])",  # 容器模式
                r'\[\s*\{.*?\}\s*\]',           # 数组模式
                r'\{[^{}]*"issue_point"[^{}]*\}'  # 对象模式
            ]

            for pattern in json_patterns:
                matches = re.findall(pattern, response, re.DOTALL)
                for match in matches:
                    # 确保 match 是字符串
                    if isinstance(match, str):
                        try:
                            return json.loads(match)
                        except json.JSONDecodeError:
                            continue

        except Exception as e:
            logger.warning(f"JSON提取失败: {str(e)}")

        return None

    def _create_issue_item(self, issue_data: dict, check_name: str, chapter_code:str,check_item_code:str) -> Dict[str, Any]:
        """创建单个审查问题项"""
        risk_level = self._determine_risk_level(issue_data.get("risk_level", ""))

        # 🔧 修复：首先检查 issue_data 是否为空
        is_empty = False
        if isinstance(issue_data, list):
            is_empty = len(issue_data) == 0
        elif isinstance(issue_data, dict):
            # 检查是否为空字典，或者只有 risk_level 字段但没有其他实质内容
            is_empty = len(issue_data) == 0 or (len(issue_data) == 1 and "risk_level" in issue_data)

        # 根据原始风险等级和内容判断是否存在问题
        original_risk_level = issue_data.get("risk_level", "") if isinstance(issue_data, dict) else ""
        # 只有当内容不为空，且风险等级不是"无风险"类时，才认为存在问题
        exist_issue = not is_empty and original_risk_level not in ["无风险", "无", "通过", "符合要求"]

        # 记录调试信息
        if is_empty:
            logger.debug(f"检查项 {check_name} 的 issue_data 为空，设置 exist_issue=False")

        return {
            "check_item": check_name,
            "chapter_code": chapter_code,
            "check_item_code":check_item_code,
            "check_result": issue_data,
            "exist_issue": exist_issue,
            "risk_info": {"risk_level": risk_level}
        }

    def _convert_risk_level(self, risk_input) -> str:
        """转换风险等级，支持中文到英文的转换"""
        if not risk_input:
            return "low"

        risk_str = str(risk_input).lower()
        if "高" in risk_str or "high" in risk_str:
            return "high"
        elif "中" in risk_str or "medium" in risk_str:
            return "medium"
        else:
            return "low"

    def _determine_risk_level(self, risk_input) -> str:
        """确定风险等级，支持字符串直接输入或文本解析"""
        if not risk_input:
            return "medium"

        # 如果输入的是文本，尝试从中提取风险等级
        if isinstance(risk_input, str) and len(risk_input) > 50:  # 假设是长文本
            lines = risk_input.split('\n')
            for line in lines:
                line = line.strip()
                if line.startswith('**风险等级**：') or line.startswith('**risk_level**：'):
                    if '：' in line:
                        risk_str = line.split('：', 1)[1].strip()
                    elif ':' in line:
                        risk_str = line.split(':', 1)[1].strip()
                    else:
                        continue
                    return self._determine_risk_level(risk_str)

        # 处理直接的风险等级字符串 - 先转换为字符串避免 dict 类型错误
        risk_str = str(risk_input).lower()
        if "高" in risk_str or "high" in risk_str:
            return "high"
        elif "中" in risk_str or "medium" in risk_str:
            return "medium"
        else:
            return "low"

    def _check_ai_review_result(self, state: AIReviewState) -> str:
        """
        检查AI审查结果状态

        Args:
            state: AI审查工作流状态

        Returns:
            str: 状态标识 ("success" 或 "error")

        Note:
            根据状态中是否存在错误信息来判断审查是否成功
        """
        if state.get("error_message"):
            return "error"
        return "success"

    async def _complete_format(self,result, state, unit_index, total_units, completeness_config):
        section_label = completeness_config.get('section_label')
        chapter_code = completeness_config.get('chapter_code', '')
        logger.info(f"section_label:  {section_label}")
        # 格式化issues以获取问题数量
        issues = self._format_review_results_to_issues(
            state["callback_task_id"],
            unit_index,
            section_label,
            chapter_code,
            completeness_config,
            result.basic_compliance,
            result.technical_compliance
        )

        current = int(((unit_index + 1) / total_units) * 100)

        # 立即发送单元审查详情（包含unit_review和processing_flag事件）
        await self._send_unit_review_progress(state, unit_index, total_units, section_label, issues, current)

        return issues

    async def _send_unit_review_progress(self, state: AIReviewState, unit_index: int,
                                            total_units: int, section_label: str,
                                            issues: List[Dict], current: int) -> None:
        """
        发送单元审查详细信息 - 强制串行并统一进度值
        """
        try:
            # 1. 计算问题数量
            issues_count = 0
            if isinstance(issues, list) and issues:
                issues_count = sum(
                    1 for issue in issues
                    for issue_data in issue.values()
                    for review_item in issue_data.get("review_lists", [])
                    if review_item.get("exist_issue", False)
                )

            real_current = await self._send_unit_overall_progress(
                state, unit_index, total_units, section_label, issues_count
            )

            final_current = real_current if real_current is not None else current

            await asyncio.sleep(0.05)

            # 3. 发送单元详情 (Unit Review)
            if isinstance(issues, list) and issues and state["progress_manager"]:
                stage_name = f"AI审查:{section_label}"

                await state["progress_manager"].update_stage_progress(
                    callback_task_id=state["callback_task_id"],
                    stage_name=stage_name,
                    current=final_current,  # 【关键】使用与 Flag 事件完全一致的进度值
                    status="unit_review_update",
                    message=f"发现{issues_count}个问题: {section_label}",
                    issues=issues,
                    user_id=state.get("user_id", ""),
                    overall_task_status="processing",
                    event_type="unit_review"
                )

                # 再次微小延迟，确保 Clear 不会吞掉 Review
                await asyncio.sleep(0.02)

                # 清空当前issues
                await state["progress_manager"].update_stage_progress(
                    callback_task_id=state["callback_task_id"],
                    issues=['clear']
                )

        except Exception as e:
            logger.error(f"发送单元审查详情失败: {str(e)}")

    async def _send_unit_overall_progress(self, state: AIReviewState, unit_index: int,
                                           total_units: int, section_label: str,
                                           issues_count: int = None) -> Optional[int]:
        """
        发送单元完成进度更新 - 返回计算出的实时进度
        Returns:
            int: 基于 Redis 统计的实时进度百分比
        """
        current_percent = None
        try:
            task_id = state.get("callback_task_id", "")
            redis_client = None
            try:
                from foundation.infrastructure.cache.redis_connection import RedisConnectionFactory
                redis_client = await RedisConnectionFactory.get_connection()
            except Exception as e:
                logger.error(f"Redis连接失败: {str(e)}")

            completed_count = 0

            if redis_client and task_id:
                completed_key = f"ai_review:overall_task_progress:{task_id}:completed"
                # 原子操作
                await redis_client.sadd(completed_key, str(unit_index))
                await redis_client.expire(completed_key, 3600)
                completed_count = await redis_client.scard(completed_key)

                # 计算进度
                current_percent = int((completed_count / total_units) * 100)
            else:
                # 降级方案
                completed_count = unit_index + 1
                current_percent = int((completed_count / total_units) * 100)

            # 构建消息
            if issues_count is not None and issues_count > 0:
                message = f"已完成第 {completed_count}/{total_units} 个单元: {section_label}（已发现{issues_count}个问题）"
            else:
                message = f"已完成第 {completed_count}/{total_units} 个单元: {section_label}"

            logger.info(f"进度更新: {current_percent}% - {message}")

            if state["progress_manager"]:
                await state["progress_manager"].update_stage_progress(
                    callback_task_id=state["callback_task_id"],
                    stage_name="AI审查",
                    current=current_percent,
                    status="processing",
                    message=message,
                    user_id=state.get("user_id", ""),
                    overall_task_status="processing",
                    event_type="processing_flag"
                )

            return current_percent

        except Exception as e:
            logger.warning(f"发送单元完成进度更新失败: {str(e)}")
            # 发生异常时，尝试返回一个基于 index 的估算值
            try:
                return int(((unit_index + 1) / total_units) * 100)
            except:
                return 0