import json
import re
from collections import defaultdict
from copy import deepcopy


def generate_key_paths(data):
    """
    处理输入的字典，生成 key_paths, grouped_paths 和 good_list，并根据条件修改原始字典。

    参数:
        data (dict): 输入的嵌套字典。

    返回:
        tuple: 包含 key_paths, grouped_paths 和 good_list 的元组。
    """
    # 编译用于匹配后缀的正则表达式模式
    pattern = re.compile(r'(.+)-\d+$')

    # 初始化结果列表和字典
    key_paths = []
    grouped_counts = defaultdict(int)  # 用于记录每个 grouped_path 的数量
    good_list = []

    def recurse(current_dict, path):
        """
        递归遍历字典，处理 key_paths 和 grouped_paths，并收集 good_list 和 grouped_counts。

        参数:
            current_dict (dict): 当前遍历的字典。
            path (list): 当前路径的键列表。
        """
        # 第一遍遍历，统计每个基名的出现次数
        base_name_count = {}
        base_names = {}
        for key in current_dict.keys():
            match = pattern.match(key)
            if match:
                base = match.group(1)
            else:
                base = key
            base_names[key] = base
            base_name_count[base] = base_name_count.get(base, 0) + 1

        # 第二遍遍历，根据基名的出现次数分类
        keys_to_rename = {}
        for key, base in base_names.items():
            if base_name_count[base] == 1:
                # 检查是否是最内层（值为列表）
                value = current_dict[key]
                if isinstance(value, list):
                    current_path = '.'.join(path + [base])
                    key_paths.append(current_path)
                    # 收集 good_list，保持顺序且不重复
                    if base not in good_list:
                        good_list.append(base)
                    # 如果原键名有后缀，需要记录以便后续重命名
                    if key != base:
                        keys_to_rename[key] = base
                elif isinstance(value, dict):
                    # 继续递归处理
                    recurse(value, path + [base])
            else:
                # 记录分组路径，并统计数量
                grouped_path = '.'.join(path + [base])
                grouped_counts[grouped_path] += 1

        # 执行键名的重命名，同时保持原有顺序
        if keys_to_rename:
            new_ordered_dict = {}
            for key in current_dict.keys():
                if key in keys_to_rename:
                    new_key = keys_to_rename[key]
                    new_ordered_dict[new_key] = current_dict[key]
                else:
                    new_ordered_dict[key] = current_dict[key]
            current_dict.clear()
            current_dict.update(new_ordered_dict)

        # 对于基名重复的键，继续递归（如果值是字典）
        for key, base in base_names.items():
            if base_name_count[base] > 1:
                value = current_dict[key]
                if isinstance(value, dict):
                    recurse(value, path + [base])
                elif isinstance(value, list):
                    # 如果值是列表，仍需收集基名到 good_list
                    if base not in good_list:
                        good_list.append(base)

    # 深拷贝数据以避免修改原始输入
    data_copy = deepcopy(data)

    # 开始递归遍历
    recurse(data_copy, [])

    def collect_grouped_paths(current_dict, path, collected):
        for key in current_dict.keys():
            match = pattern.match(key)
            if match:
                base = match.group(1)
            else:
                base = key
            current_path = '.'.join(path + [base])
            if current_path in grouped_counts and current_path not in collected:
                collected.append(current_path)
            value = current_dict[key]
            if isinstance(value, dict):
                collect_grouped_paths(value, path + [base], collected)

    collected_grouped_paths = []
    collect_grouped_paths(data_copy, [], collected_grouped_paths)

    # 将 grouped_paths 转换为包含数量的字典列表
    grouped_paths = [{path: grouped_counts[path]} for path in collected_grouped_paths]

    return key_paths, grouped_paths, good_list, data_copy

def rename_keys(data):
    """
    对整个数据结构进行重命名处理。
    """

    def rename_keys_recursive(current_dict):
        """
        递归地重名字典中的键，确保同一层级下具有相同基名的键被正确编号。
        """
        if not isinstance(current_dict, dict):
            return current_dict

        key_order = list(current_dict.keys())
        base_name_dict = defaultdict(list)

        # 辅助函数：提取基名（去除可能的 -数字 后缀）
        def get_base_name(key):
            if '-' in key:
                parts = key.rsplit('-', 1)
                if parts[1].isdigit():
                    return parts[0]
            return key

        # 将键按基名分组
        for key in key_order:
            base = get_base_name(key)
            base_name_dict[base].append(key)

        new_dict = {}
        for key in key_order:
            base = get_base_name(key)
            keys = base_name_dict[base]
            if len(keys) > 1:
                # 如果存在同基名的多个键，则进行重命名
                if base not in new_dict:
                    # 按原始顺序对需要重命名的键进行排序
                    sorted_keys = sorted(keys, key=lambda x: key_order.index(x))
                    for idx, original_key in enumerate(sorted_keys, start=1):
                        new_key = f"{base}-{idx}"
                        # 如果值是字典，递归处理
                        if isinstance(current_dict[original_key], dict):
                            new_dict[new_key] = rename_keys_recursive(current_dict[original_key])
                        else:
                            new_dict[new_key] = current_dict[original_key]
            else:
                # 如果没有重复的基名，保持原名
                if isinstance(current_dict[key], dict):
                    new_dict[key] = rename_keys_recursive(current_dict[key])
                else:
                    new_dict[key] = current_dict[key]

        return new_dict

    # 对整个数据结构进行递归重命名
    return rename_keys_recursive(data)
def test_generate_key_paths():
    data0={
        "显示系统": {
            "LED全彩显示屏": [],
            "控制盒及电源": [],
            "大屏播控系统": [],
            "配电柜(含PLC)": [],
            "钢结构底座及铝型材支架": [],
            "电缆及信号线缆": [],
            "控制终端": [],
            "50寸液晶电视机": [],
            "50寸电视机地面推车": [],
            "高清监视器": []
        },
        "摄像系统": {
            "高清摄像机": [],
            "摄像机三脚架": [],
            "摄像机壁装架": [],
            "摄像机控制键盘": []
        },
        "视频处理系统": {
            "高清视频拼控矩阵(16*16)": [],
            "分量信号接口器": [],
            "高清四画面分割器": []
        },
        "发言系统": {
            "数字会议发言主机": [],
            "方形短杆代表话筒": [],
            "专用连接线缆": [],
            "手持无线话筒": []
        },
        "视频会议系统": {
            "多点控制器": [],
            "多串口控制服务器": [],
            "综合会议管理调度平台": [],
            "高清会议终端(主会场)": [],
            "高清会议终端(分会场)": [],
            "65寸电视机移动推车(9楼)": [],
            "65寸液晶电视机(分会场)": [],
            "控制平板及软件": [],
            "鹅颈话筒": []
        },
        "辅助系统": {
            "时序电源": [],
            "多媒体地插盒": [],
            "线材辅料": [],
            "墙体拆除及修复": []
        }
    }
    # 定义测试数据
    data = {
        "fruits": [],
        "fruits-1": [],
        "vegetables": {
            "root": [],
            "root-1": [],
            "leafy": []
        },
        "grains": {
            "交换机":[],
            "whole grains": [],  # 键名包含空格
            "whole-grains-1": []  # 同一基名，带后缀
        },
        "misc": {
            "system functions": [],  # 特殊键，包含空格
            "system functions-1": [],  # 特殊键，带后缀
            "fruits-1": [],
            "fruits-2": [],
            "fruits-3": []
        },
        "beverages": []
    }
    # 运行函数
    key_paths, grouped_paths, good_list, data_copy = generate_key_paths(data0)
    # 打印结果
    print("实际 data_copy:")
    print(json.dumps(data_copy,ensure_ascii=False,indent=4))
    modi=rename_keys(data_copy)
    print(json.dumps(modi, ensure_ascii=False, indent=4))

    print(key_paths)
    print(grouped_paths)
    print(good_list)

user_query_template = """请根据货物标中采购要求部分的内容，告诉我\"{}\"的技术参数或采购要求是什么。请以 JSON 格式返回结果，键名为\"{}\"，键值为一个列表，列表中包含若干描述\"{}\"的技术参数或采购要求的字符串，请按原文内容回答，保留三角▲、五角★和序号，不可擅自增删内容，尤其是不可擅自添加序号。

要求与指南：
1. 如果该货物没有相关采购要求或技术参数要求，键值应为空列表[]。
2. 如果存在嵌套结构，且原文为Markdown 的表格语法，如'摄像机|有效像素|≥900W像素'， 请不要返回该Markdown语法，而是使用冒号':'将相关信息拼接在一起，生成一条完整且清晰的技术参数（或采购要求）描述，作为列表中的一个字符串。如"摄像机：有效像素：≥900W像素"。
3. 字符串中的内容为具体的技术参数要求或采购要求，请不要返回诸如'（1）高清录像功能'这种标题性质且不能体现要求的内容。
4. 你的键值应该全面，对于同一个单元格内的数据，尽量全面，不要遗漏，对于单元格内以序号分隔的各条参数要求，请分别添加进键值（即字符串列表）中。

### 示例输出1如下：
{{
    "摄像机控制键盘": [
        "1、▲支持串行 RS232/RS422 和 IP 混合控制，允许在一个控制器上使用 RS232/RS422/IP 控制单个系统中的摄像机；",
        "2、支持 2 组 RS422 串口 VISCA 协议菊花链控制 2x7 台摄像机。",
        "★能够自动对焦，提供检测报告"
    ]
}}

### 示例输出2如下（包含嵌套结构）：
{{
    "摄像机": [
        "摄像机：有效像素：≥900W像素",
        "摄像机：最低照度：彩色≤0.001lx",
        "协议：routes 接口开放：具备；▲支持标准 ONVIF 协议与第三方厂家设备进行互联；支持 GB/T28181；应提供 SDK"
    ]
}}
"""

user_query_template_two="""请根据货物标中采购要求部分的内容，告诉我\"{}\"的技术参数或采购要求是什么。由于该货物存在 {} 种不同的采购要求或技术参数，请逐一列出，并以 JSON 格式返回结果。请以'货物名-编号'区分多种型号，编号为从 1 开始的自然数，依次递增，即第一个键名为\"{}-1\", 键值为一个列表，列表中包含若干描述\"{}\"的技术参数（或采购要求）的字符串，请按原文内容回答，保留三角▲、五角★和序号（若有），不可擅自增添内容。
请注意以下特殊情况：
要求与指南：
1. 如果该货物没有相关采购要求或技术参数要求，键值应为空列表。
2. 如果存在嵌套结构，且原文为Markdown 的表格语法，如'摄像机|有效像素|≥900W像素'， 请不要返回该Markdown语法，而是使用冒号':'将相关信息拼接在一起，生成一条完整且清晰的技术参数（或采购要求）描述，作为列表中的一个字符串。如"摄像机：有效像素：≥900W像素"。
3. 字符串中的内容为具体的技术参数要求或采购要求，请不要返回诸如'（1）高清录像功能'这种标题性质且不能体现要求的内容。
4. 你的键值应该全面，对于同一个单元格内的数据，尽量全面，不要遗漏，对于单元格内以序号分隔的各条参数要求，请分别添加进键值（即字符串列表）中。

### 示例输出1如下：
{{
    "交换机-1": [
        "★1、支持固化千兆电口≥8 个，固化千兆光口≥2 个，桌面型设备;",
        "2、支持静态链路聚合"
    ],
    "交换机-2": [
        "1、交换容量≥52Gbps，包转发率≥38.69Mpps，",
        "2、提供国家强制性产品认证证书及测试报告（3C）",
        "★能实现信号控制独立传输"
    ]
}}

### 示例输出2如下（包含嵌套结构）：
{{
    "摄像机-1": [
                "摄像机：有效像素：≥900W像素",
                "摄像机：最低照度：彩色≤0.001lx",
                "协议：routes 接口开放：具备；▲支持标准 ONVIF 协议与第三方厂家设备进行互联；支持 GB/T28181；应提供 SDK"
            ],
    "摄像机-2": [
        "支持夜视", "支持云存储"
    ]
}}
        """
def test_generate_ques_two(grouped_paths):
    queries=[]
    for grouped_dict in grouped_paths:
        for grouped_key, grouped_key_cnt in grouped_dict.items():
            # 将键中的 '.' 替换为 '下的'
            modified_grouped_key = grouped_key.replace('.', '下的')
            # 使用修改后的键填充第一个占位符，原始键填充第二个占位符
            # 如果需要使用 full_text，可以取消注释并提供相应的实现
            # full_text = read_txt_to_string(processed_filepath)
            # new_query = user_query_template_two.format(modified_grouped_key, grouped_key, modified_grouped_key, full_text)

            # 根据您的需求，生成新的查询字符串
            new_query = user_query_template_two.format(modified_grouped_key, grouped_key_cnt,grouped_key, modified_grouped_key)
            queries.append(new_query)
            print(new_query)

def test_generate_ques_one(key_paths):
    queries=[]
    for key in key_paths:
        # 将键中的 '.' 替换为 '下的'
        modified_key = key.replace('.', '下的')
        # 使用修改后的键填充第一个占位符，原始键填充第二个占位符
        # full_text = read_txt_to_string(processed_filepath)
        # new_query = user_query_template.format(modified_key, key, modified_key,full_text)   #转豆包后取消注释
        new_query = user_query_template.format(modified_key, key, modified_key)
        queries.append(new_query)
        print(new_query)

if __name__ == "__main__":
    # test_generate_key_paths()
    # grouped_paths=[{'fruits': 2}, {'vegetables.root': 2}, {'misc.system functions': 2}, {'misc.fruits': 3}]
    # key_paths=['显示系统.LED全彩显示屏', '显示系统.控制盒及电源', '显示系统.大屏播控系统', '显示系统.配电柜(含PLC)', '显示系统.钢结构底座及铝型材支架', '显示系统.电缆及信号线缆', '显示系统.控制终端', '显示系统.50寸液晶电视机', '显示系统.50寸电视机地面推车', '显示系统.高清监视器', '摄像系统.高清摄像机', '摄像系统.摄像机三脚架', '摄像系统.摄像机壁装架', '摄像系统.摄像机控制键盘', '视频处理系统.高清视频拼控矩阵(16*16)', '视频处理系统.分量信号接口器', '视频处理系统.高清四画面分割器', '发言系统.数字会议发言主机', '发言系统.方形短杆代表话筒', '发言系统.专用连接线缆', '发言系统.手持无线话筒', '视频会议系统.多点控制器', '视频会议系统.多串口控制服务器', '视频会议系统.综合会议管理调度平台', '视频会议系统.高清会议终端(主会场)', '视频会议系统.高清会议终端(分会场)', '视频会议系统.65寸电视机移动推车(9楼)', '视频会议系统.65寸液晶电视机(分会场)', '视频会议系统.控制平板及软件', '视频会议系统.鹅颈话筒', '辅助系统.时序电源', '辅助系统.多媒体地插盒', '辅助系统.线材辅料', '辅助系统.墙体拆除及修复']
    key_paths=['显示系统.LED全彩显示屏', '显示系统.控制盒及电源', '显示系统.大屏播控系统']
    # test_generate_ques(grouped_paths)
    test_generate_ques_one(key_paths)