import json
import re
from functools import cmp_to_key

from flask_app.general.投标人须知正文提取指定内容 import extract_between_sections


#生成结构化的数据，即根据序号1 1.1 1.1.1生成有层级的JSON，已废弃！
#工程标版
def compare_headings(a, b):
    a_nums = [int(num) for num in a[0].rstrip('.').split('.') if num.isdigit()]
    b_nums = [int(num) for num in b[0].rstrip('.').split('.') if num.isdigit()]
    return (a_nums > b_nums) - (a_nums < b_nums)

# 主要是处理键值中若存在若干序号且每个序号块的内容>=50字符的时候，用列表表示。
def post_process(value):
    # 如果传入的是非字符串值，直接返回原值
    if not isinstance(value, str):
        return value

    # 定义可能的分割模式及其正则表达式
    patterns = [
        (r'\d+、', r'(?=\d+、)'),  # 匹配 '1、'
        (r'[（(]\d+[）)]', r'(?=[（(]\d+[）)])'),  # 匹配 '(1)' 或 '（1）'
        (r'\d+\.', r'(?=\d+\.)'),  # 匹配 '1.'
        (r'[一二三四五六七八九十]、', r'(?=[一二三四五六七八九十]、)'),  # 匹配 '一、'、'二、' 等
        (r'[一二三四五六七八九十]\.', r'(?=[一二三四五六七八九十]\.)')  # 匹配 '一.'、'二.' 等
    ]

    # 初始化用于保存最早匹配到的模式及其位置
    first_match = None
    first_match_position = len(value)  # 初始值设为文本长度，确保任何匹配都会更新它

    # 遍历所有模式，找到第一个出现的位置
    for search_pattern, split_pattern_candidate in patterns:
        match = re.search(search_pattern, value)
        if match:
            # 如果这个匹配的位置比当前记录的更靠前，更新匹配信息
            if match.start() < first_match_position:
                first_match = split_pattern_candidate
                first_match_position = match.start()

    # 如果找到了最早出现的匹配模式，使用它来分割文本
    if first_match:
        blocks = re.split(first_match, value)
    else:
        # 如果没有匹配的模式，保留原文本
        blocks = [value]

    processed_blocks = []
    for block in blocks:
        if not block:
            continue
        # 计算中英文字符总数，如果大于50，则加入列表
        if block and len(re.findall(r'[\u4e00-\u9fff\w]', block)) >= 50:
            processed_blocks.append(block.strip())
        else:
            # 如果发现有块长度小于50，返回原数据
            return value

    # 如果所有的块都符合条件，返回分割后的列表
    return processed_blocks
def preprocess_data(data):
    """
    预处理数据，自动添加缺失的父层级键，并按数字顺序排序。
    """
    keys_to_add = set()
    for key in data.keys():
        parts = key.split('.')
        if len(parts) > 1:
            parent_key = parts[0] + '.'
            if parent_key not in data:
                keys_to_add.add(parent_key)

    # 添加缺失的父层级键
    for parent_key in keys_to_add:
        data[parent_key] = parent_key.rstrip('.')

    # 对键进行排序
    sorted_data = dict(sorted(data.items(), key=cmp_to_key(compare_headings)))

    return sorted_data
def transform_json(data):
    result = {}
    temp = {0: result}  # 初始化根字典
    data=preprocess_data(data)
    # 首先,创建一个临时字典用于检查是否存在三级标题
    has_subkey = {}
    for key in data.keys():
        parts = key.split('.')
        if len(parts) > 2 and parts[1]:
            parent_key = parts[0] + '.' + parts[1]
            has_subkey[parent_key] = True

    for key, value in data.items():
        match = re.match(r'(\d+)(?:\.(\d+))?(?:\.(\d+))?', key)
        if match:
            levels = [int(l) for l in match.groups() if l is not None]
            if (len(levels) - 1) in temp:
                parent = temp[len(levels) - 1]
            else:
                print(f"No parent found at level {len(levels) - 1} for key '{key}'. Check the data structure.")
                continue

            if len(levels) == 1:  # 一级标题
                # 新增逻辑：判断值中是否有 ':' 或 '：'，并进行拆分
                # 优先按 '\n' 拆分
                if '\n' in value:
                    new_key, *new_value = value.split('\n', 1)
                    new_key = new_key.strip()
                    new_value = new_value[0].strip() if new_value else ""
                # 如果没有 '\n'，再检查 ':' 或 '：'，并进行拆分
                elif ':' in value or '：' in value:
                    delimiter = ':' if ':' in value else '：'
                    new_key, new_value = value.split(delimiter, 1)
                    new_key = new_key.strip()
                    new_value = new_value.strip()
                else:
                    new_key = value.strip()
                    new_value = ""

                parent[new_key] = {}
                if new_value:
                    parent[new_key][new_key] = new_value  # 使用 new_key 作为键名，而不是固定的 "content"
                temp[len(levels)] = parent[new_key]
            elif len(levels) == 2:  # 二级标题
                new_key, *new_value = value.split('\n', 1)
                new_key = new_key.strip()
                new_value = new_value[0].strip() if new_value else ""

                if f"{levels[0]}.{levels[1]}" in has_subkey:
                    parent[new_key] = [new_value] if new_value else []
                else:
                    parent[new_key] = new_value

                temp[len(levels)] = parent[new_key]
            else:  # 三级标题
                if isinstance(parent, dict):
                    parent_key = list(parent.keys())[-1]
                    if isinstance(parent[parent_key], list):
                        parent[parent_key].append(value)
                    elif parent[parent_key]:
                        parent[parent_key] = [parent[parent_key], value]
                    else:
                        parent[parent_key] = [value]
                elif isinstance(parent, list):
                    parent.append(value)

    def remove_single_item_lists(node):
        if isinstance(node, dict):
            for key in list(node.keys()):
                node[key] = remove_single_item_lists(node[key])
                if isinstance(node[key], list) and len(node[key]) == 1:
                    node[key] = node[key][0]
        return node

    return remove_single_item_lists(result)

def sort_clean_data_keys(data):
    # 预处理：删除键名中的空格
    def preprocess_key(key):
        return re.sub(r'\s+', '', key)

    # 将键转换成由整数构成的元组，作为排序依据
    def key_func(key):
        return tuple(int(part) for part in re.split(r'\D+', key) if part)

    # 创建一个新的字典，键名经过预处理
    preprocessed_data = {preprocess_key(key): value for key, value in data.items()}

    # 对预处理后的字典键进行排序
    sorted_keys = sorted(preprocessed_data.keys(), key=key_func)

    # 创建一个新的字典，按照排序后的键添加键值对
    sorted_data = {key: preprocessed_data[key] for key in sorted_keys}

    return sorted_data
#---------------------------------
"""
递归处理嵌套的数据结构（字典和列表）。
对最内层的字符串值应用 post_process 函数。
post_process 函数尝试将长字符串按特定模式分割成块，每块至少包含50个中英文字符。
如果字典中所有值都是 ""、"/" 或空列表，则返回'键'的列表。
"""
def process_nested_data(data):
    # 先检查是否所有值都是 ""、"/" 或空列表
    if isinstance(data, dict) and all(v == "" or v == "/" or (isinstance(v, list) and not v) for v in data.values()):
        return list(data.keys())
    # 递归遍历字典，处理最内层的字符串
    if isinstance(data, dict):
        # 如果当前项是字典，继续递归遍历其键值对
        result = {}
        for key, value in data.items():
            processed_value = process_nested_data(value)
            # 如果处理后的值是只有一个元素的列表，就直接使用该元素
            if isinstance(processed_value, list) and len(processed_value) == 1:
                result[key] = processed_value[0]
            else:
                result[key] = processed_value
        return result
    elif isinstance(data, list):
        # 如果是列表，直接返回列表，保持原样
        return data
    else:
        # 到达最内层，处理非字典和非列表的元素（字符串）
        return post_process(data)
def process_with_outer_key(data):
    processed_data = {}

    # 遍历外层的键值对
    for outer_key, inner_data in data.items():
        # 调用 transform_json 函数对内层数据进行处理
        processed_inner_data = transform_json(inner_data)

        # 将处理后的数据保留在外层键下
        processed_data[outer_key] = processed_inner_data

    return processed_data

if __name__ == "__main__":
    clause_path=r'C:\Users\Administrator\Desktop\货物\test\test\clause1.json'
    type_target_map = {
        1: ["投标文件", "响应文件", "响应性文件"],
        2: ["开标", "评标", "定标", "评审", "成交", "合同", "磋商", "谈判", "中标", "程序", "步骤"],
        3: ["重新招标、不再招标和终止招标", "重新招标", "重新采购", "不再招标", "不再采购", "终止招标", "终止采购"],
        4: ["评标"]  # 测试
    }
    type=1
    target_values = type_target_map.get(type)
    with open(clause_path, 'r', encoding='utf-8') as file:
        data = json.load(file)
    extracted_data = extract_between_sections(data, target_values)  # 读取json，截取大标题之间的内容
    #旧版逻辑，大标题：
    transformed_data = process_with_outer_key(extracted_data)
    final_result = process_nested_data(transformed_data)
    #旧版逻辑，序号提取
    sorted_data = sort_clean_data_keys(extracted_data)  # 对输入的字典 data 的键进行预处理和排序
    transformed_data = transform_json(sorted_data)

    print(json.dumps(transformed_data,ensure_ascii=False,indent=4))
