import json
from typing import Dict, List, Any, Optional, Tuple
from equipment_calculation.bcl_calculator import (
    BCLCalculator,
    BCLContext,
    BCLVariant,
    BCLVariantType,
    BCLPrefixContext,
    BCLPrefixPrevContext,
    BCLDataSourceItem,
    BCLDataSourceContext,
)
from equipment_calculation.project import Ration, MaterialOrEquipment, Material, Equipment, bill_node
from copy import deepcopy
import logging

# 全局变量
calculator = BCLCalculator()


def load_json_data(json_file_path: str, json_path: str = None) -> Dict[str, Any]:
    """
    从JSON文件中加载指定路径的数据

    Args:
        json_file_path: JSON文件路径
        json_path: JSON路径表达式，格式如 "projectData.projectInfo"，None表示返回整个JSON

    Returns:
        Dict[str, Any]: 加载的数据
    """
    try:
        with open(json_file_path, "r", encoding="utf-8") as f:
            data = json.load(f)

        if not json_path:
            return data

        # 按路径逐级获取数据
        parts = json_path.split(".")
        result = data
        for part in parts:
            if isinstance(result, dict) and part in result:
                result = result.get(part, {})
            else:
                print(f"JSON路径 '{json_path}' 中的部分 '{part}' 不存在")
                return {}

        return result
    except Exception as e:
        print(f"加载JSON数据时出错: {e}")
        return {}


def create_node_from_type(node: dict[str, any]):
    """
    根据项目划分子节点类型动态创建对应类型的对象

    Args:
        node: 项目划分子节点数据

    Returns:
        对应类型的对象：Ration、Material或Equipment
    """
    # 获取节点类型
    node_type = node.get("类型", "")
    type_code = node.get("type", "")

    # 判断是否为“定额”类型：node_type 或 type_code 是 "定额" 或 "0"
    if node_type in ["定额", "0"] or type_code in ["定额", "0"]:
        return create_ration_from_node(node)
    elif node_type in ["主材", "1"] or type_code in ["主材", "1"]:
        return create_material_from_node(node)
    elif node_type in ["设备", "配件"] or type_code in ["设备", "配件"]:
        return create_equipment_from_node(node)
    else:
        logging.warning(f"未知节点类型: 类型={node_type}, type={type_code}，默认创建Ration对象")
        return create_ration_from_node(node)


def create_list_from_node(node: dict[str, any]) -> bill_node:
    """
    创建定额对象

    Args:
        node: 项目划分子节点数据

    Returns:
        list: 创建的清单对象
    """
    bill = bill_node()

    # 设置定额相关属性
    bill.清单名称 = node.get("清单名称")
    bill.清单全码 = node.get("清单全码")
    bill.编码 = node.get("编码")
    bill.单位 = node.get("单位")
    bill.计算式 = node.get("计算式")
    bill.数量 = node.get("数量")
    bill.取费表 = node.get("取费表")
    bill.合价 = node.get("合价")
    bill.工作内容 = node.get("工作内容")
    bill.类型 = node.get("类型")
    bill.type = node.get("type")
    bill.项目特征 = node.get("项目特征")
    bill.资源库名称 = node.get("资源库名称")
    bill.计算规则 = node.get("计算规则")
    bill.单价 = node.get("单价")
    bill.一次性费用 = node.get("一次性费用")
    bill.取费表名称 = node.get("取费表名称")
    bill.取费表类型 = node.get("取费表类型")
    bill.单价不含税 = node.get("单价不含税")
    bill.合价不含税 = node.get("合价不含税")
    bill.专业类型 = node.get("专业类型")
    bill.关联父级量 = node.get("关联父级量")
    bill.含量 = node.get("含量")

    # 遍历节点的所有属性，确保所有可能的字段都被设置
    for key, value in node.items():
        if hasattr(bill, key) and not key.startswith("_"):
            if value is not None:
                setattr(bill, key, str(value) if value != "" else "")

    return bill


def create_ration_from_node(node: dict[str, any]) -> Ration:
    """
    创建定额对象

    Args:
        node: 项目划分子节点数据

    Returns:
        Ration: 创建的定额对象
    """
    ration = Ration()

    # 设置定额相关属性
    ration.id = node.get("id")
    ration.type = node.get("类型")
    ration.name = node.get("项目名称")
    ration.编码 = node.get("编码")
    ration.单位 = node.get("单位")
    ration.数量 = node.get("数量")
    ration.资源库名称 = node.get("资源库名称")
    ration.计算式 = node.get("计算式")
    ration.人工费 = node.get("人工费")
    ration.机械费 = node.get("机械费")
    ration.甲供材料费不含税 = node.get("甲供材料费不含税")
    ration.材料费 = node.get("材料费")
    ration.定额系数 = node.get("定额系数")
    ration.人工系数 = node.get("人工系数")
    ration.材料系数 = node.get("材料系数")
    ration.机械系数 = node.get("机械系数")
    ration.定额范围 = node.get("定额范围")
    ration.定额章节名称 = node.get("定额章节名称")
    ration.费用类型 = node.get("费用类型")
    ration.甲供材料费含税 = node.get("甲供材料费含税")
    ration.投标合价 = node.get("投标合价")
    ration.其中甲供材料费 = node.get("其中：甲供材料费")
    ration.合价不含税 = node.get("合价不含税")
    ration.基价 = node.get("基价")
    ration.所属定额库 = node.get("所属定额库")
    ration.专业属性 = node.get("专业属性")
    ration.地形费计算方式 = node.get("地形费计算方式")

    # 遍历节点的所有属性，确保所有可能的字段都被设置
    for key, value in node.items():
        if hasattr(ration, key) and not key.startswith("_"):
            if value is not None:
                setattr(ration, key, str(value) if value != "" else "")

    ration.乙供材料费不含税 = node.get("材料费")
    return ration


def create_material_from_node(node: dict[str, any]) -> Material:
    """
    创建主材对象

    Args:
        node: 项目划分子节点数据

    Returns:
        Material: 创建的主材对象
    """
    material = Material()

    # 设置主材相关属性
    material.id = node.get("id")
    material.name = node.get("项目名称")
    material.type = node.get("类型", "主材")
    material.供货方 = node.get("供货方")
    material.关联父级量 = node.get("关联父级量")
    material.制造长度 = node.get("制造长度")
    material.单位 = node.get("单位")
    material.单重 = node.get("单重")
    material.增值税率 = node.get("增值税率")
    material.数量 = node.get("数量")
    material.损耗率 = node.get("损耗率")
    material.规格型号 = node.get("规格型号")
    material.线重 = node.get("线重")
    material.截面积 = node.get("截面积")
    material.市场价不含税 = node.get("市场价不含税")
    material.市场价含税 = node.get("市场价含税")
    material.资源库名称 = node.get("资源库名称")
    material.编码 = node.get("编码")
    material.集中配送 = node.get("集中配送")
    material.投标数量 = node.get("投标数量")
    material.投标单价 = node.get("投标单价")
    material.特征段 = node.get("特征段")
    material.颜色标记 = node.get("颜色标记")
    material.单价不含税 = node.get("单价不含税")
    material.单价含税 = node.get("单价含税")
    material.结算市场价不含税 = node.get("结算市场价不含税")
    material.结算市场价含税 = node.get("结算市场价含税")
    material.基准价不含税 = node.get("基准价不含税")
    material.基准价含税 = node.get("基准价含税")
    material.费用类型 = node.get("费用类型")
    material.合价含税 = node.get("合价含税")
    material.合价不含税 = node.get("合价不含税")
    material.保管 = node.get("保管")
    material.卸车 = node.get("卸车")
    material.暂估价 = node.get("暂估价")
    material.每件重 = node.get("每件重")
    material.设备性材料 = node.get("设备性材料")
    material.调差类型 = node.get("调差类型")
    material.运输类型 = node.get("运输类型")
    material.拆分 = node.get("拆分")

    # 遍历节点的所有属性，确保所有可能的字段都被设置
    for key, value in node.items():
        if hasattr(material, key) and not key.startswith("_"):
            if value is not None:
                setattr(material, key, str(value) if value != "" else "")

    material.预算价不含税 = material.单价不含税

    return material


def create_equipment_from_node(node: dict[str, any]) -> Equipment:
    """
    创建设备对象

    Args:
        node: 项目划分子节点数据

    Returns:
        Equipment: 创建的设备对象
    """
    equipment = Equipment()

    # 设置设备相关属性
    equipment.id = node.get("id")
    equipment.name = node.get("项目名称")
    equipment.type = node.get("类型", "设备")
    equipment.供货方 = node.get("供货方")
    equipment.关联父级量 = node.get("关联父级量")
    equipment.制造长度 = node.get("制造长度")
    equipment.单位 = node.get("单位")
    equipment.单重 = node.get("单重")
    equipment.增值税率 = node.get("增值税率")
    equipment.数量 = node.get("数量")
    equipment.损耗率 = node.get("损耗率")
    equipment.规格型号 = node.get("规格型号")
    equipment.线重 = node.get("线重")
    equipment.市场价不含税 = node.get("市场价不含税")
    equipment.市场价含税 = node.get("市场价含税")
    equipment.编码 = node.get("编码")
    equipment.设备类型 = node.get("设备类型")
    equipment.资源库名称 = node.get("资源库名称")
    equipment.集中配送 = node.get("集中配送")
    equipment.运杂费率 = node.get("运杂费率")
    equipment.投标数量 = node.get("投标数量")
    equipment.投标单价 = node.get("投标单价")
    equipment.特征段 = node.get("特征段")
    equipment.颜色标记 = node.get("颜色标记")
    equipment.单价不含税 = node.get("单价不含税")
    equipment.单价含税 = node.get("单价含税")
    equipment.合价含税 = node.get("合价含税")
    equipment.合价不含税 = node.get("合价不含税")
    equipment.保管 = node.get("保管")
    equipment.卸车 = node.get("卸车")
    equipment.工程量索引 = node.get("工程量索引")
    equipment.截面积 = node.get("截面积")
    equipment.拆分 = node.get("拆分")
    equipment.暂估价 = node.get("暂估价")
    equipment.计算式 = node.get("计算式")
    equipment.设备性材料 = node.get("设备性材料")
    equipment.调差类型 = node.get("调差类型")

    # 遍历节点的所有属性，确保所有可能的字段都被设置
    for key, value in node.items():
        if hasattr(equipment, key) and not key.startswith("_"):
            if value is not None:
                setattr(equipment, key, str(value) if value != "" else "")

    return equipment


def init_bcl_calculator(software_category, engineering_type, calculation_type):
    """
    初始化BCL计算器

    Args:
        software_category: 软件类别（主网/配网/技改）
        engineering_type: 工程类型（预算/清单）
        calculation_type: 计算类型（工程量/人材机）

    Returns:
        bool: 是否成功初始化
    """
    try:

        # 构建计算配置路径
        # 格式：计算配置/软件类型（主网，配网，技改）/计算类型（工程量，人材机）/工程类型（预算，清单）
        config_path = f"equipment_calculation/计算配置/{software_category}/{calculation_type}/{engineering_type}"

        print(f"加载计算配置: {config_path}")

        # 检查目录是否存在
        import os

        if not os.path.exists(config_path):
            print(f"计算配置目录不存在: {config_path}")
            # 尝试创建目录
            try:
                os.makedirs(config_path, exist_ok=True)
                print(f"已创建计算配置目录: {config_path}")
            except Exception as e:
                print(f"创建计算配置目录失败: {e}")

            # 如果目录不存在，使用默认配置
            default_path = "equipment_calculation/计算配置/主网/工程量/预算"
            print(f"使用默认计算配置: {default_path}")

            # 检查默认配置目录是否存在
            if not os.path.exists(default_path):
                print(f"默认计算配置目录不存在: {default_path}")
                # 尝试使用原始默认配置
                original_default_path = "equipment_calculation/计算配置/主网/主网预算"
                print(f"尝试使用原始默认计算配置: {original_default_path}")

                if os.path.exists(original_default_path):
                    config_path = original_default_path
                else:
                    print(f"原始默认计算配置目录不存在: {original_default_path}")
                    return False
            else:
                config_path = default_path

        # 加载脚本
        result = calculator.load_scripts_dir(config_path)
        if False == result:
            print(f"加载脚本错误: {calculator.get_last_error()}")
            # 尝试使用默认配置
            default_path = "equipment_calculation/计算配置/主网/工程量/预算"
            print(f"尝试使用默认计算配置: {default_path}")

            # 检查默认配置目录是否存在
            if not os.path.exists(default_path):
                print(f"默认计算配置目录不存在: {default_path}")
                # 尝试使用原始默认配置
                original_default_path = "equipment_calculation/计算配置/主网/主网预算"
                print(f"尝试使用原始默认计算配置: {original_default_path}")

                if os.path.exists(original_default_path):
                    result = calculator.load_scripts_dir(original_default_path)
                    if False == result:
                        print(f"加载原始默认脚本错误: {calculator.get_last_error()}")
                        return False
                    else:
                        print(f"成功加载原始默认脚本: {original_default_path}")
                else:
                    print(f"原始默认计算配置目录不存在: {original_default_path}")
                    return False
            else:
                result = calculator.load_scripts_dir(default_path)
                if False == result:
                    print(f"加载默认脚本错误: {calculator.get_last_error()}")
                    return False
                else:
                    print(f"成功加载默认脚本: {default_path}")
        else:
            print(f"成功加载脚本: {config_path}")

        return True
    except Exception as e:
        print(f"初始化BCL计算器错误: {e}")
        return False


def create_material_or_equipment_from_node(node: dict[str, any]) -> MaterialOrEquipment:
    """
    根据项目划分子节点动态创建 MaterialOrEquipment 对象

    Args:
        node: 人材机子节点数据

    Returns:
        MaterialOrEquipment: 创建的人材机对象
    """
    me = MaterialOrEquipment()

    # 设置基本属性
    me.id = node.get("id")
    me.编码 = node.get("编码")
    me.名称 = node.get("名称")
    me.单位 = node.get("单位")
    me.type = node.get("类型")
    me.供货方 = node.get("供货方", "")
    me.预算价不含税 = node.get("预算价不含税")
    me.市场价不含税 = node.get("市场价不含税")
    me.预算价含税 = node.get("预算价含税")
    me.市场价含税 = node.get("市场价含税")
    me.结算预算价不含税 = node.get("结算预算价不含税")
    me.结算市场价不含税 = node.get("结算市场价不含税")
    me.结算预算价含税 = node.get("结算预算价含税")
    me.结算市场价含税 = node.get("结算市场价含税")
    me.暂估价 = node.get("暂估价", "")
    me.拆分 = node.get("拆分", "")
    me.全口径市场价不含税 = node.get("全口径市场价不含税")
    me.全口径市场价含税 = node.get("全口径市场价含税")
    me.商品砼 = node.get("商品砼", "")
    me.数量 = node.get("数量")
    me.是否未计价 = node.get("是否未计价")

    # 遍历节点的所有属性，确保所有可能的字段都被设置
    for key, value in node.items():
        if hasattr(me, key) and not key.startswith("_"):
            setattr(me, key, str(value))

    return me


# 不需要派生，写一个函数去生成上下文
class ZjProjectBCLContext(BCLPrefixPrevContext):
    """
    工程信息上下文类，用于从JSON文件中读取工程信息并提供给BCL计算器
    """

    def __init__(self, prefix="@工程信息", valueDict=None, prevContext=None, project_division_name=None, **kwargs):
        # 创建空字典作为valueDict参数
        super().__init__(prefix=prefix, valueDict=valueDict or {}, prevContext=prevContext)
        self.project_division_name = project_division_name

    def add_variable(self, name, value):
        """
        添加变量到上下文中

        Args:
            name: 变量名
            value: 变量值
        """
        self._childContext.variables[name] = BCLVariant(value)

    def add_variables_from_dict(self, data_dict: Dict[str, Any]):
        """
        从字典批量添加变量到上下文中

        Args:
            data_dict: 数据字典或列表
        """
        # 如果是列表，直接添加为"属性"变量
        if isinstance(data_dict, list):
            self.add_variable("属性", data_dict)
            return

        # 原有的字典处理逻辑
        for key, value in data_dict.items():
            if isinstance(value, dict):
                continue  # 跳过嵌套字典

            # 尝试将字符串转换为数字
            if isinstance(value, str) and value.replace(".", "", 1).isdigit():
                try:
                    value = float(value)
                except (ValueError, TypeError):
                    pass

            self.add_variable(key, value)

    def _get_variable_value(self, var_name: str) -> BCLVariant:
        """
        获取变量值，支持直接查找价差系数属性

        Args:
            var_name: 变量名，格式为'对象.属性'

        Returns:
            BCLVariant: 变量值
        """
        # 首先尝试使用父类的方法获取变量
        result = super()._get_variable_value(var_name)

        # 如果是价差系数相关的变量
        if var_name.startswith("@价差系数."):
            # 提取属性名称
            attr_name = var_name.split(".", 1)[1]

            # 获取价差系数数据
            price_diff_data = None
            if (
                self._prefix == "@价差系数"
                and hasattr(self, "_childContext")
                and hasattr(self._childContext, "variables")
            ):
                if "属性" in self._childContext.variables:
                    price_diff_data = self._childContext.variables["属性"].value

            # 如果没有在当前上下文找到，尝试从父上下文查找
            if price_diff_data is None and self._prevContext is not None:
                prev_ctx = self._prevContext
                while prev_ctx is not None:
                    if isinstance(prev_ctx, ZjProjectBCLContext) and prev_ctx._prefix == "@价差系数":
                        if hasattr(prev_ctx, "_childContext") and hasattr(prev_ctx._childContext, "variables"):
                            if "属性" in prev_ctx._childContext.variables:
                                price_diff_data = prev_ctx._childContext.variables["属性"].value
                                break
                    prev_ctx = prev_ctx._prevContext

            # 如果找到了价差系数数据，在属性列表中查找匹配项
            if price_diff_data is not None and isinstance(price_diff_data, list):
                for item in price_diff_data:
                    if isinstance(item, dict) and item.get("名称") == attr_name:
                        return BCLVariant(item.get("值", ""))

            # 如果找不到匹配项，返回空值
            print(f"警告: 未找到价差系数属性 '{attr_name}'")
            return BCLVariant("")

        return result


# 前缀配置定义
class PrefixConfig:
    def __init__(self, prefix: str, json_path: str = None, field_mappings: Dict[str, str] = None):
        """
        前缀配置类

        Args:
            prefix: 前缀名称，如 "@工程信息"
            json_path: JSON路径表达式，如 "projectData.projectInfo"
            field_mappings: 字段映射，键为JSON字段名，值为BCL变量名
        """
        self.prefix = prefix
        self.json_path = json_path
        self.field_mappings = field_mappings or {}


def create_project_contexts(json_file_path: str, prefix_configs: List[PrefixConfig] = None) -> BCLContext:
    """
    从JSON文件创建多个前缀上下文，并将它们链接在一起

    Args:
        json_file_path: JSON文件路径
        prefix_configs: 前缀配置列表，None时使用默认配置

    Returns:
        BCLContext: 链接好的上下文对象
    """
    try:
        # 使用默认配置（如果未提供）
        if prefix_configs is None:
            prefix_configs = [
                # 工程信息前缀
                PrefixConfig(prefix="@工程信息", json_path="projectData.projectInfo"),
                # 调差系数前缀
                PrefixConfig(
                    prefix="@价差系数",
                    json_path="projectData.价差系数",
                ),
            ]

        # 创建根上下文
        root_context = None

        # 为每个前缀创建上下文并链接
        for config in prefix_configs:
            # 加载数据
            data = load_json_data(json_file_path, config.json_path)

            # 创建上下文
            context = ZjProjectBCLContext(prefix=config.prefix, prevContext=root_context)

            # 如果有字段映射，应用映射
            if config.field_mappings:
                mapped_data = {}
                for bcl_name, json_name in config.field_mappings.items():
                    if json_name in data:
                        mapped_data[bcl_name] = data[json_name]
                context.add_variables_from_dict(mapped_data)
            else:
                # 直接添加所有数据
                context.add_variables_from_dict(data)

            # 更新根上下文
            root_context = context

        return root_context

    except Exception as e:
        print(f"创建工程上下文时出错: {e}")
        # 返回一个空的上下文
        return ZjProjectBCLContext()


class ZjBillBCLContext(BCLPrefixPrevContext):
    def __init__(self, prefix=None, valueDict=None, prevContext=None, **kwargs):
        # 正确调用父类构造函数，提供必要的参数
        super().__init__(prefix=prefix, valueDict=valueDict or {}, prevContext=prevContext)


class ZjQuantityBCLContext(BCLPrefixPrevContext):
    def __init__(self, node_data=None, json_file_path=None, prevContext=None, **kwargs):
        # 只传递BCLPrefixContext需要的参数
        super().__init__(prefix="node", valueDict={}, prevContext=prevContext)

        # 保存json_file_path作为实例变量
        self.json_file_path = json_file_path

        if node_data:
            node = create_node_from_type(node_data)
            # 添加项目特定变量
            self.variables["source"] = BCLVariant([node])


def create_parent_ration(parent_node=None, project_node=None):
    """
    创建父级定额对象

    Args:
        parent_node: 父级节点数据
        project_node: 项目节点数据

    Returns:
        Ration: 创建的父级定额对象
    """
    if parent_node:
        parent_ration = create_ration_from_node(parent_node)
    elif project_node:
        parent_ration = create_ration_from_node(project_node)
    else:
        parent_ration = create_ration_from_node({})

    # 确保父级节点中有必要的系数
    if not hasattr(parent_ration, "定额系数") or not parent_ration.定额系数:
        parent_ration.定额系数 = "1.0"
    if not hasattr(parent_ration, "人工系数") or not parent_ration.人工系数:
        parent_ration.人工系数 = "1.0"
    if not hasattr(parent_ration, "材料系数") or not parent_ration.材料系数:
        parent_ration.材料系数 = "1.0"
    if not hasattr(parent_ration, "机械系数") or not parent_ration.机械系数:
        parent_ration.机械系数 = "1.0"

    # 确保父级节点中的数量是有效的数值
    if not hasattr(parent_ration, "数量") or not parent_ration.数量:
        parent_ration.数量 = "0.0"

    return parent_ration


class ZjMaterialOrEquipmentBCLContext(BCLPrefixContext):
    def __init__(self, node_data=None, parent_node=None, prevContext=None, **kwargs):
        """
        初始化人材机上下文

        Args:
            node_data: 人材机节点，可以是单个节点或节点列表
            parent_node: 父级定额节点
            prevContext: 上一级上下文（定额上下文）
            **kwargs: 其他参数
        """

        # 调用父类构造函数
        super().__init__(prefix="node", valueDict={}, prevContext=prevContext, **kwargs)

        # 创建父级定额
        self.parent_ration = create_parent_ration(parent_node)

        # 创建人材机对象列表
        self.items = []
        if node_data:
            if isinstance(node_data, list):
                # 如果传入的是列表，处理每个人材机节点
                self.items = [create_material_or_equipment_from_node(node) for node in node_data]
            else:
                # 如果传入的是单个节点
                self.items = [create_material_or_equipment_from_node(node_data)]

        # 初始化 parent_variables（用于支持 parent.xxx 表达式）
        self.parent_variables = {}
        for key, value in self.parent_ration.__dict__.items():
            if value is None:
                value = ""
            self.parent_variables[key] = BCLVariant(value)

        # 设置上下文变量
        self.variables["items"] = BCLVariant(self.items)
        self.variables["curnode"] = BCLVariant(self.items)
        self.variables["source"] = BCLVariant(self.items)
        self.variables["parent"] = BCLVariant([self.parent_ration])

        # 添加调试信息
        print(f"父级节点数量: {self.parent_ration.数量}")
        print(f"父级节点定额系数: {self.parent_ration.定额系数}")
        print(f"父级节点人工系数: {self.parent_ration.人工系数}")
        print(f"父级节点材料系数: {self.parent_ration.材料系数}")
        print(f"父级节点机械系数: {self.parent_ration.机械系数}")

        if self.items:
            print(f"人材机节点类型: {self.items[0].type}")
            print(f"人材机节点数量: {self.items[0].数量}")

    def _get_variable_value(self, var_name: str) -> BCLVariant:
        # 添加调试信息
        print(f"获取变量: {var_name}")

        if var_name.startswith("@"):
            # 对于全局变量，尝试从上下文链中获取
            result = super()._get_variable_value(var_name)
            print(f"  全局变量 {var_name} = {result.value if result else None}")
            return result

        if "." in var_name:
            obj_name, attr = var_name.split(".", maxsplit=1)
            if obj_name == "parent":
                # 确保父级变量存在
                if attr not in self.parent_variables:
                    print(f"  警告: 父级变量 '{attr}' 不存在，返回默认值")
                    if attr in ["数量", "定额系数", "人工系数", "材料系数", "机械系数"]:
                        return BCLVariant("1.0")
                    return BCLVariant("")
                result = self.parent_variables.get(attr)
                print(f"  父级变量 {attr} = {result.value if result else None}")
                return result
            elif obj_name in ["curnode", "items"]:
                items = self.variables[obj_name].value
                if isinstance(items, list) and len(items) > 0:
                    item = items[0]
                    val = getattr(item, attr, None)
                    result = BCLVariant(val)
                    print(f"  项目变量 {obj_name}.{attr} = {result.value if result else None}")
                    return result
                else:
                    print(f"  警告: {obj_name} 为空或不是列表")
                    return BCLVariant("")
        else:
            if var_name in self.variables:
                result = self.variables[var_name]
                print(f"  上下文变量 {var_name} = {result.value if result else None}")
                return result

        # 如果在本地找不到变量，尝试从上下文链中获取
        print(f"  尝试从上下文链中获取变量 {var_name}")
        return super()._get_variable_value(var_name)
