import json


def equipment_calculation(json_file_path):

    # 读取JSON文件
    with open(json_file_path, "r", encoding="utf-8") as f:
        data = json.load(f)

    # 获取projectDivision
    project_division = data["projectData"]["projectDivision"]

    def collect_nodes_by_type(parent_name):
        # 初始化五个列表，分别存储不同类型的节点
        zhucai_nodes = []  # 主材
        shebei_nodes = []  # 设备
        rengong_nodes = []  # 人工
        cailiao_nodes = []  # 材料
        jixie_nodes = []  # 机械

        found_parent = [False]  # 使用列表作为可变引用

        # 递归查找函数 - 处理嵌套结构
        def find_parent_and_collect(node, target_name):
            # 如果节点是字典
            if isinstance(node, dict):
                # 检查当前节点是否为目标父节点
                node_name = node.get("项目名称", node.get("名称", ""))
                if node_name == target_name:
                    print(f"找到目标节点: {target_name}")
                    # 找到目标父节点，开始收集子节点
                    collect_children(node)
                    found_parent[0] = True
                    return True

                # 处理所有可能的子节点路径
                for key, value in node.items():
                    if find_parent_and_collect(value, target_name):
                        return True

            # 如果节点是列表
            elif isinstance(node, list):
                for item in node:
                    if find_parent_and_collect(item, target_name):
                        return True

            return False

        # 递归收集子节点中的不同类型节点
        def collect_children(node, parent_quantity=1.0):
            # 检查当前节点类型并添加到对应列表
            node_type = node.get("类型")
            node_name = node.get("项目名称", node.get("名称", "未知"))
            node_quantity = float(node.get("数量", 1.0))

            # 只有当前节点是五类特定节点之一时，才考虑其父节点数量
            if node_type:
                print(f"发现节点: {node_name}, 类型: {node_type}, 数量: {node_quantity}, 父节点数量: {parent_quantity}")

                # 创建节点的副本，避免修改原始数据
                node_copy = node.copy()
                # 保存原始数量
                node_copy["原始数量"] = node_quantity
                # 保存父节点数量，用于后续计算
                node_copy["父节点数量"] = parent_quantity

                if node_type == "主材":
                    zhucai_nodes.append(node_copy)
                elif node_type == "设备":
                    shebei_nodes.append(node_copy)
                elif node_type == "人工":
                    rengong_nodes.append(node_copy)
                elif node_type == "材料":
                    cailiao_nodes.append(node_copy)
                elif node_type == "机械":
                    jixie_nodes.append(node_copy)

            # 计算当前节点传递给子节点的数量
            # 如果当前节点不是特定五类节点之一，则将其数量与父节点数量相乘传递给子节点
            current_parent_quantity = (
                node_quantity * parent_quantity
                if node_type not in ["主材", "设备", "人工", "材料", "机械"]
                else parent_quantity
            )

            # 递归处理children子节点
            children = node.get("children", [])
            for child in children:
                collect_children(child, current_parent_quantity)

            # 递归处理材机列表子节点
            caiji_list = node.get("材机列表", [])
            for item in caiji_list:
                collect_children(item, current_parent_quantity)

        # 从根节点开始查找目标父节点
        find_parent_and_collect(project_division, parent_name)

        if not found_parent[0]:
            print(f"警告: 未找到名为 '{parent_name}' 的节点")

            # 尝试查找相似名称的节点
            all_names = []

            def collect_names(node):
                if isinstance(node, dict):
                    if "项目名称" in node:
                        all_names.append(node["项目名称"])
                    if "名称" in node:
                        all_names.append(node["名称"])

                    # 遍历所有子节点
                    for key, value in node.items():
                        collect_names(value)

                elif isinstance(node, list):
                    for item in node:
                        collect_names(item)

            collect_names(project_division)

            # 打印一些可能的节点名称
            print("可能的节点名称示例:")
            unique_names = sorted(set(all_names))
            for name in unique_names[:20]:  # 只显示前20个，去重并排序
                print(f"- {name}")

        # 返回五个分类列表
        return {
            "主材": zhucai_nodes,
            "设备": shebei_nodes,
            "人工": rengong_nodes,
            "材料": cailiao_nodes,
            "机械": jixie_nodes,
        }

    # 合并同类型节点并计算价格差异
    def merge_same_nodes(nodes_dict):
        merged_results = {"主材": [], "设备": [], "人工": [], "材料": [], "机械": []}

        # 遍历每种类型的节点
        for node_type, nodes in nodes_dict.items():
            # 用于存储合并的节点
            merged_nodes = {}

            # 遍历每个节点
            for node in nodes:
                # 获取节点属性
                name = node.get("名称", node.get("项目名称", "未知"))
                budget_price = str(node.get("预算价不含税", "0"))
                market_price = str(node.get("市场价不含税", "0"))

                # 获取当前节点的数量和父节点数量
                node_quantity = float(node.get("原始数量", node.get("数量", "0")))
                parent_quantity = float(node.get("父节点数量", 1.0))

                # 计算实际数量 = 节点数量 * 父节点数量
                actual_quantity = node_quantity * parent_quantity

                print(
                    f"合并节点: {name}, 节点数量: {node_quantity}, 父节点数量: {parent_quantity}, 实际数量: {actual_quantity}"
                )

                # 创建唯一键以识别相同节点 - 使用名称、预算价和市场价作为键
                key = f"{name}_{budget_price}_{market_price}"

                # 如果已存在相同键的节点，则合并数量
                if key in merged_nodes:
                    merged_nodes[key]["数量"] += actual_quantity
                else:
                    # 深拷贝节点，避免修改原始数据
                    merged_node = node.copy()
                    merged_node["数量"] = actual_quantity
                    # 移除辅助字段
                    if "原始数量" in merged_node:
                        del merged_node["原始数量"]
                    if "父节点数量" in merged_node:
                        del merged_node["父节点数量"]
                    merged_nodes[key] = merged_node

            # 计算合并后的预算价合价、市场价合价和价差
            for key, merged_node in merged_nodes.items():
                quantity = float(merged_node["数量"])
                budget_price = float(merged_node.get("预算价不含税", 0))
                market_price = float(merged_node.get("市场价不含税", 0))

                # 计算合价
                budget_total = budget_price * quantity
                market_total = market_price * quantity
                price_diff = market_total - budget_total

                # 添加计算结果到节点属性
                merged_node["预算价合价"] = round(budget_total, 2)
                merged_node["市场价合价"] = round(market_total, 2)
                merged_node["价差"] = round(price_diff, 2)

                # 将合并后的节点添加到结果中
                merged_results[node_type].append(merged_node)

        return merged_results

    # 打印合并结果的统计信息
    def print_merge_stats(merged_results):
        for node_type, nodes in merged_results.items():
            total_budget = sum(node.get("预算价合价", 0) for node in nodes)
            total_market = sum(node.get("市场价合价", 0) for node in nodes)
            total_diff = sum(node.get("价差", 0) for node in nodes)

            print(f"{node_type}节点数量: {len(nodes)}")
            print(f"{node_type}总预算价合价: {round(total_budget, 2)}")
            print(f"{node_type}总市场价合价: {round(total_market, 2)}")
            print(f"{node_type}总价差: {round(total_diff, 2)}")
            print("-" * 30)

    # 主函数流程
    parent_name = "基础工程材料工地运输"
    result = collect_nodes_by_type(parent_name)

    print("\n原始节点统计:")
    print(f"主材节点数量: {len(result['主材'])}")
    print(f"设备节点数量: {len(result['设备'])}")
    print(f"人工节点数量: {len(result['人工'])}")
    print(f"材料节点数量: {len(result['材料'])}")
    print(f"机械节点数量: {len(result['机械'])}")

    print("\n开始合并相同节点...")
    merged_results = merge_same_nodes(result)

    print("\n合并后节点统计及价格信息:")
    print_merge_stats(merged_results)

    # 输出样例节点详情
    for node_type, nodes in merged_results.items():
        if nodes:
            sample_node = nodes[0]
            print(f"\n{node_type}节点样例:")
            for key, value in sample_node.items():
                if key in [
                    "名称",
                    "项目名称",
                    "数量",
                    "预算价不含税",
                    "市场价不含税",
                    "预算价合价",
                    "市场价合价",
                    "价差",
                ]:
                    print(f"  {key}: {value}")
            break

    return merged_results


if __name__ == "__main__":
    json_file_path = "主网预算/架空_clean.json"

    equipment_calculation(json_file_path)
