package com.yhy.module.core.service.resource.impl;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yhy.module.core.enums.ErrorCodeConstants.RESOURCE_MERGED_CALC_BASE_CATEGORY_NOT_FOUND;
import static com.yhy.module.core.enums.ErrorCodeConstants.RESOURCE_MERGED_CALC_BASE_INVALID;
import static com.yhy.module.core.enums.ErrorCodeConstants.RESOURCE_MERGED_FORMULA_PARSE_ERROR;
import static com.yhy.module.core.enums.ErrorCodeConstants.RESOURCE_MERGED_NOT_EXISTS;
import static com.yhy.module.core.enums.ErrorCodeConstants.RESOURCE_MERGED_PERCENT_UNIT_NOT_ALLOWED;
import static com.yhy.module.core.enums.ErrorCodeConstants.RESOURCE_MERGED_SELF_REFERENCE;
import static com.yhy.module.core.enums.ErrorCodeConstants.RESOURCE_MERGED_SOURCE_NOT_EXISTS;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import com.yhy.module.core.controller.admin.resource.vo.ResourceMergedPageReqVO;
import com.yhy.module.core.controller.admin.resource.vo.ResourceMergedRespVO;
import com.yhy.module.core.controller.admin.resource.vo.ResourceMergedSaveReqVO;
import com.yhy.module.core.dal.dataobject.resource.ResourceItemDO;
import com.yhy.module.core.dal.dataobject.resource.ResourceMergedDO;
import com.yhy.module.core.dal.mysql.resource.ResourceItemMapper;
import com.yhy.module.core.dal.mysql.resource.ResourceMergedMapper;
import com.yhy.module.core.service.resource.ResourceMergedService;
import com.yhy.module.core.util.FormulaEvaluator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

/**
 * 复合工料机 Service 实现类
 *
 * @author yihuiyong
 */
@Service
@Validated
@Slf4j
public class ResourceMergedServiceImpl implements ResourceMergedService {

    @Resource
    private ResourceMergedMapper resourceMergedMapper;

    @Resource
    private ResourceItemMapper resourceItemMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createResourceMerged(ResourceMergedSaveReqVO createReqVO) {
        // 校验不允许自己关联自己
        if (createReqVO.getMergedId() != null && createReqVO.getSourceId() != null
                && createReqVO.getMergedId().equals(createReqVO.getSourceId())) {
            throw exception(RESOURCE_MERGED_SELF_REFERENCE);
        }
        
        // 校验父工料机单位不能为 %
        validateParentUnitNotPercent(createReqVO.getMergedId());
        
        // 校验子工料机如果单位为 %，必须配置计算基数
        validateSourceCalcBase(createReqVO.getSourceId());
        
        // 确保父工料机（merged_id）的税率为空
        ensureParentTaxRateIsNull(createReqVO.getMergedId());
        
        // 插入
        ResourceMergedDO resourceMerged = BeanUtils.toBean(createReqVO, ResourceMergedDO.class);
        resourceMergedMapper.insert(resourceMerged);
        
        // 将父工料机标记为复合工料机
        updateParentIsMerged(createReqVO.getMergedId(), true);
        
        // 不再自动触发价格计算，由虚拟字段动态计算
        // calculateMergedPrices(resourceMerged.getMergedId());
        
        // 返回
        return resourceMerged.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateResourceMerged(ResourceMergedSaveReqVO updateReqVO) {
        // 校验存在
        ResourceMergedDO existing = validateResourceMergedExists(updateReqVO.getId());
        
        // 只允许更新定额消耗量
        ResourceMergedDO updateObj = new ResourceMergedDO();
        updateObj.setId(existing.getId());
        updateObj.setQuotaConsumption(updateReqVO.getQuotaConsumption());
        resourceMergedMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteResourceMerged(Long id) {
        // 校验存在
        ResourceMergedDO merged = validateResourceMergedExists(id);
        Long mergedId = merged.getMergedId();
        
        // 删除
        resourceMergedMapper.deleteById(id);
        
        // 检查父工料机是否还有子项，如果没有则取消复合工料机标记
        checkAndUpdateParentIsMerged(mergedId);
    }

    private ResourceMergedDO validateResourceMergedExists(Long id) {
        ResourceMergedDO merged = resourceMergedMapper.selectById(id);
        if (merged == null) {
            throw exception(RESOURCE_MERGED_NOT_EXISTS);
        }
        return merged;
    }

    @Override
    public ResourceMergedRespVO getResourceMerged(Long id) {
        // 查询数据（JOIN 第四层）
        ResourceMergedRespVO respVO = resourceMergedMapper.selectByIdWithDetails(id);
        if (respVO == null) {
            throw exception(RESOURCE_MERGED_NOT_EXISTS);
        }
        // 格式化数值：价格/税率保留2位小数，消耗量/合价保留4位小数
        formatSingleItem(respVO);
        return respVO;
    }

    @Override
    public PageResult<ResourceMergedRespVO> getResourceMergedPage(ResourceMergedPageReqVO pageReqVO) {
        // 计算偏移量
        int offset = (pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize();
        
        // 查询数据（JOIN 第四层）
        List<ResourceMergedRespVO> list = resourceMergedMapper.selectPageWithDetails(pageReqVO, offset);
        
        // 为单位为 % 的子工料机计算合价
        calculatePercentUnitTotals(list);
        
        // 格式化数值：价格/税率保留2位小数，消耗量/合价保留4位小数
        formatDecimalValues(list);
        
        // 查询总数
        Long total = resourceMergedMapper.selectCountWithDetails(pageReqVO);
        
        return new PageResult<>(list, total);
    }

    /**
     * 为单位为 % 的子工料机计算合价
     * 
     * @param list 子工料机列表
     */
    @SuppressWarnings("unchecked")
    private void calculatePercentUnitTotals(List<ResourceMergedRespVO> list) {
        if (list == null || list.isEmpty()) {
            return;
        }
        
        // 按 mergedId 分组
        Map<Long, List<ResourceMergedRespVO>> groupedByMergedId = list.stream()
                .collect(Collectors.groupingBy(ResourceMergedRespVO::getMergedId));
        
        // 遍历每个组
        for (Map.Entry<Long, List<ResourceMergedRespVO>> entry : groupedByMergedId.entrySet()) {
            List<ResourceMergedRespVO> group = entry.getValue();
            
            // 第一次遍历：构建类别价格映射表（只处理普通工料机）
            Map<Long, CategoryPriceSum> categoryPriceMap = new HashMap<>();
            
            for (ResourceMergedRespVO item : group) {
                if (!"%".equals(item.getUnit())) {
                    // 普通工料机：计算合价并记录到类别映射表
                    if (item.getCategoryId() != null) {
                        CategoryPriceSum categoryPrice = categoryPriceMap.computeIfAbsent(
                                item.getCategoryId(), k -> new CategoryPriceSum());
                        
                        // 累加到类别价格
                        categoryPrice.taxExclBasePrice = categoryPrice.taxExclBasePrice.add(
                                item.getTaxExclBaseTotal() != null ? item.getTaxExclBaseTotal() : BigDecimal.ZERO);
                        categoryPrice.taxInclBasePrice = categoryPrice.taxInclBasePrice.add(
                                item.getTaxInclBaseTotal() != null ? item.getTaxInclBaseTotal() : BigDecimal.ZERO);
                        categoryPrice.taxExclCompilePrice = categoryPrice.taxExclCompilePrice.add(
                                item.getTaxExclCompileTotal() != null ? item.getTaxExclCompileTotal() : BigDecimal.ZERO);
                        categoryPrice.taxInclCompilePrice = categoryPrice.taxInclCompilePrice.add(
                                item.getTaxInclCompileTotal() != null ? item.getTaxInclCompileTotal() : BigDecimal.ZERO);
                    }
                }
            }
            
            // 第二次遍历：处理单位为 % 的工料机
            for (ResourceMergedRespVO item : group) {
                if ("%".equals(item.getUnit()) && item.getCalcBase() != null) {
                    try {
                        // 解析 calc_base
                        Map<String, Object> calcBase = item.getCalcBase();
                        if (!calcBase.containsKey("formula") || !calcBase.containsKey("variables")) {
                            continue;
                        }
                        
                        String formula = (String) calcBase.get("formula");
                        Map<String, Object> variablesConfig = (Map<String, Object>) calcBase.get("variables");
                        
                        // 构建变量值映射表
                        Map<String, BigDecimal> taxExclBaseVars = new HashMap<>();
                        Map<String, BigDecimal> taxInclBaseVars = new HashMap<>();
                        Map<String, BigDecimal> taxExclCompileVars = new HashMap<>();
                        Map<String, BigDecimal> taxInclCompileVars = new HashMap<>();
                        
                        boolean allCategoriesFound = true;
                        for (Map.Entry<String, Object> varEntry : variablesConfig.entrySet()) {
                            String varName = varEntry.getKey();
                            Long categoryId = Long.valueOf(varEntry.getValue().toString());
                            
                            CategoryPriceSum categoryPrice = categoryPriceMap.get(categoryId);
                            if (categoryPrice == null) {
                                allCategoriesFound = false;
                                break;
                            }
                            
                            taxExclBaseVars.put(varName, categoryPrice.taxExclBasePrice);
                            taxInclBaseVars.put(varName, categoryPrice.taxInclBasePrice);
                            taxExclCompileVars.put(varName, categoryPrice.taxExclCompilePrice);
                            taxInclCompileVars.put(varName, categoryPrice.taxInclCompilePrice);
                        }
                        
                        if (!allCategoriesFound) {
                            continue;
                        }
                        
                        // 计算公式结果
                        BigDecimal taxExclBaseSum = FormulaEvaluator.evaluate(formula, taxExclBaseVars);
                        BigDecimal taxInclBaseSum = FormulaEvaluator.evaluate(formula, taxInclBaseVars);
                        BigDecimal taxExclCompileSum = FormulaEvaluator.evaluate(formula, taxExclCompileVars);
                        BigDecimal taxInclCompileSum = FormulaEvaluator.evaluate(formula, taxInclCompileVars);
                        
                        // 乘以 (定额消耗量 / 100)
                        BigDecimal quotaConsumption = item.getQuotaConsumption() != null 
                                ? item.getQuotaConsumption() : BigDecimal.ZERO;
                        BigDecimal factor = quotaConsumption.divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP);
                        
                        // 设置虚拟字段
                        item.setTaxExclBaseTotal(taxExclBaseSum.multiply(factor).setScale(4, RoundingMode.HALF_UP));
                        item.setTaxInclBaseTotal(taxInclBaseSum.multiply(factor).setScale(4, RoundingMode.HALF_UP));
                        item.setTaxExclCompileTotal(taxExclCompileSum.multiply(factor).setScale(4, RoundingMode.HALF_UP));
                        item.setTaxInclCompileTotal(taxInclCompileSum.multiply(factor).setScale(4, RoundingMode.HALF_UP));
                    } catch (Exception e) {
                        log.error("[calculatePercentUnitTotals] 计算失败，id={}, error={}", item.getId(), e.getMessage(), e);
                    }
                }
            }
        }
    }

    /**
     * 类别价格汇总
     */
    private static class CategoryPriceSum {
        BigDecimal taxExclBasePrice = BigDecimal.ZERO;
        BigDecimal taxInclBasePrice = BigDecimal.ZERO;
        BigDecimal taxExclCompilePrice = BigDecimal.ZERO;
        BigDecimal taxInclCompilePrice = BigDecimal.ZERO;
    }

    /**
     * 格式化数值：价格/税率保留2位小数，消耗量/合价保留4位小数
     * 
     * @param list 子工料机列表
     */
    private void formatDecimalValues(List<ResourceMergedRespVO> list) {
        if (list == null || list.isEmpty()) {
            return;
        }
        
        for (ResourceMergedRespVO item : list) {
            // 价格/税率保留2位小数
            item.setTaxRate(formatScale(item.getTaxRate(), 2));
            item.setTaxExclBasePrice(formatScale(item.getTaxExclBasePrice(), 2));
            item.setTaxInclBasePrice(formatScale(item.getTaxInclBasePrice(), 2));
            item.setTaxExclCompilePrice(formatScale(item.getTaxExclCompilePrice(), 2));
            item.setTaxInclCompilePrice(formatScale(item.getTaxInclCompilePrice(), 2));
            item.setTaxExclMarketPrice(formatScale(item.getTaxExclMarketPrice(), 2));
            
            // 消耗量保留4位小数
            item.setQuotaConsumption(formatScale(item.getQuotaConsumption(), 4));
            
            // 合价保留4位小数
            item.setTaxExclBaseTotal(formatScale(item.getTaxExclBaseTotal(), 4));
            item.setTaxInclBaseTotal(formatScale(item.getTaxInclBaseTotal(), 4));
            item.setTaxExclCompileTotal(formatScale(item.getTaxExclCompileTotal(), 4));
            item.setTaxInclCompileTotal(formatScale(item.getTaxInclCompileTotal(), 4));
        }
    }

    /**
     * 格式化单个工料机项的数值
     */
    private void formatSingleItem(ResourceMergedRespVO item) {
        if (item == null) {
            return;
        }
        // 价格/税率保留2位小数
        item.setTaxRate(formatScale(item.getTaxRate(), 2));
        item.setTaxExclBasePrice(formatScale(item.getTaxExclBasePrice(), 2));
        item.setTaxInclBasePrice(formatScale(item.getTaxInclBasePrice(), 2));
        item.setTaxExclCompilePrice(formatScale(item.getTaxExclCompilePrice(), 2));
        item.setTaxInclCompilePrice(formatScale(item.getTaxInclCompilePrice(), 2));
        item.setTaxExclMarketPrice(formatScale(item.getTaxExclMarketPrice(), 2));
        
        // 消耗量保留4位小数
        item.setQuotaConsumption(formatScale(item.getQuotaConsumption(), 4));
        
        // 合价保留4位小数
        item.setTaxExclBaseTotal(formatScale(item.getTaxExclBaseTotal(), 4));
        item.setTaxInclBaseTotal(formatScale(item.getTaxInclBaseTotal(), 4));
        item.setTaxExclCompileTotal(formatScale(item.getTaxExclCompileTotal(), 4));
        item.setTaxInclCompileTotal(formatScale(item.getTaxInclCompileTotal(), 4));
    }

    /**
     * 格式化BigDecimal精度
     */
    private BigDecimal formatScale(BigDecimal value, int scale) {
        if (value == null) {
            return null;
        }
        return value.setScale(scale, RoundingMode.HALF_UP);
    }

    /**
     * 验证父工料机单位不能为 %
     * 
     * @param mergedId 复合工料机ID
     */
    private void validateParentUnitNotPercent(Long mergedId) {
        if (mergedId == null) {
            return;
        }
        
        ResourceItemDO parent = resourceItemMapper.selectById(mergedId);
        if (parent == null) {
            throw exception(RESOURCE_MERGED_NOT_EXISTS);
        }
        
        // 如果单位为 %，不允许添加子工料机
        if ("%".equals(parent.getUnit())) {
            throw exception(RESOURCE_MERGED_PERCENT_UNIT_NOT_ALLOWED);
        }
    }

    /**
     * 验证子工料机如果单位为 %，必须配置计算基数
     * 
     * @param sourceId 子工料机ID
     */
    private void validateSourceCalcBase(Long sourceId) {
        if (sourceId == null) {
            return;
        }
        
        ResourceItemDO source = resourceItemMapper.selectById(sourceId);
        if (source == null) {
            throw exception(RESOURCE_MERGED_SOURCE_NOT_EXISTS);
        }
        
        // 如果单位为 %，必须配置计算基数
        if ("%".equals(source.getUnit())) {
            if (source.getCalcBase() == null || source.getCalcBase().isEmpty()) {
                throw exception(RESOURCE_MERGED_CALC_BASE_INVALID, "单位为 % 的子工料机必须配置计算基数");
            }
            
            // 验证计算基数格式
            if (!source.getCalcBase().containsKey("formula") || !source.getCalcBase().containsKey("variables")) {
                throw exception(RESOURCE_MERGED_CALC_BASE_INVALID, "计算基数格式不正确，必须包含 formula 和 variables");
            }
        }
    }

    /**
     * 确保父工料机（复合工料机）的税率为空
     * 
     * @param mergedId 复合工料机ID
     */
    private void ensureParentTaxRateIsNull(Long mergedId) {
        if (mergedId == null) {
            return;
        }
        
        ResourceItemDO parent = resourceItemMapper.selectById(mergedId);
        if (parent == null) {
            throw exception(RESOURCE_MERGED_NOT_EXISTS);
        }
        
        // 如果税率不为空，则清空
        if (parent.getTaxRate() != null) {
            log.info("[ensureParentTaxRateIsNull] 清空复合工料机的税率，mergedId={}, 原税率={}", 
                    mergedId, parent.getTaxRate());
            resourceItemMapper.clearTaxRate(mergedId);
        }
    }

    /**
     * 计算指定 merged_id 的价格
     * 
     * @param mergedId 复合工料机ID
     */
    private void calculateMergedPrices(Long mergedId) {
        log.info("[calculateMergedPrices] 开始计算复合工料机价格，mergedId={}", mergedId);
        
        // 1. 查询该 merged_id 的所有第五层数据
        List<ResourceMergedDO> mergedList = resourceMergedMapper.selectByMergedId(mergedId);
        if (mergedList.isEmpty()) {
            log.warn("[calculateMergedPrices] 未找到第五层数据，mergedId={}", mergedId);
            return;
        }
        
        // 2. 查询所有引用的第四层数据
        List<Long> sourceIds = mergedList.stream()
                .map(ResourceMergedDO::getSourceId)
                .filter(id -> id != null)
                .distinct()
                .collect(Collectors.toList());
        
        if (sourceIds.isEmpty()) {
            log.warn("[calculateMergedPrices] 所有第五层数据的 source_id 都为空，mergedId={}", mergedId);
            return;
        }
        
        Map<Long, ResourceItemDO> sourceMap = resourceItemMapper.selectBatchIds(sourceIds).stream()
                .collect(Collectors.toMap(ResourceItemDO::getId, item -> item));
        
        // 3. 计算4个价格字段的合价
        PriceResult priceResult = calculateTotalPrices(mergedList, sourceMap);
        
        // 4. 更新第四层（merged_id 对应的工料机）的价格
        resourceItemMapper.updatePrices(
                mergedId,
                priceResult.taxExclBasePrice,
                priceResult.taxInclBasePrice,
                priceResult.taxExclCompilePrice,
                priceResult.taxInclCompilePrice
        );
        
        log.info("[calculateMergedPrices] 计算完成，mergedId={}, 除税基价={}, 含税基价={}, 除税编制价={}, 含税编制价={}",
                mergedId, priceResult.taxExclBasePrice, priceResult.taxInclBasePrice,
                priceResult.taxExclCompilePrice, priceResult.taxInclCompilePrice);
    }

    /**
     * 计算总价格
     */
    private PriceResult calculateTotalPrices(List<ResourceMergedDO> mergedList, 
                                             Map<Long, ResourceItemDO> sourceMap) {
        PriceResult result = new PriceResult();
        
        // 按类别分组，用于计算基数公式
        Map<Long, PriceResult> categoryPriceMap = new HashMap<>();
        
        for (ResourceMergedDO merged : mergedList) {
            if (merged.getSourceId() == null) {
                log.warn("[calculateTotalPrices] source_id 为空，跳过，id={}", merged.getId());
                continue;
            }
            
            ResourceItemDO source = sourceMap.get(merged.getSourceId());
            if (source == null) {
                throw exception(RESOURCE_MERGED_SOURCE_NOT_EXISTS);
            }
            
            // 计算单条数据的价格
            PriceResult itemPrice = calculateItemPrice(merged, source, mergedList, sourceMap, categoryPriceMap);
            
            // 累加到总价
            result.add(itemPrice);
            
            // 记录类别价格（用于计算基数）
            if (source.getCategoryId() != null) {
                categoryPriceMap.computeIfAbsent(source.getCategoryId(), k -> new PriceResult()).add(itemPrice);
            }
        }
        
        return result;
    }

    /**
     * 计算单条数据的价格
     */
    private PriceResult calculateItemPrice(ResourceMergedDO merged,
                                           ResourceItemDO source,
                                           List<ResourceMergedDO> allMergedList,
                                           Map<Long, ResourceItemDO> sourceMap,
                                           Map<Long, PriceResult> categoryPriceMap) {
        PriceResult result = new PriceResult();
        
        // 定额消耗量
        BigDecimal quotaConsumption = merged.getQuotaConsumption();
        if (quotaConsumption == null) {
            quotaConsumption = BigDecimal.ZERO;
        }
        
        // 判断是否为百分比单位
        boolean isPercentUnit = "%".equals(source.getUnit());
        
        if (isPercentUnit && source.getCalcBase() != null) {
            // 场景2：单位为"%"，使用计算基数公式
            result = calculateWithCalcBase(merged, source, allMergedList, sourceMap, categoryPriceMap);
        } else {
            // 场景1：普通工料机
            // 合价 = 价格 × 消耗量（与定额基价模块保持一致）
            result.taxExclBasePrice = multiplyOrZero(source.getTaxExclBasePrice(), quotaConsumption);
            result.taxInclBasePrice = multiplyOrZero(source.getTaxInclBasePrice(), quotaConsumption);
            result.taxExclCompilePrice = multiplyOrZero(source.getTaxExclCompilePrice(), quotaConsumption);
            result.taxInclCompilePrice = multiplyOrZero(source.getTaxInclCompilePrice(), quotaConsumption);
        }
        
        return result;
    }

    /**
     * 使用计算基数公式计算价格
     */
    @SuppressWarnings("unchecked")
    private PriceResult calculateWithCalcBase(ResourceMergedDO merged,
                                              ResourceItemDO source,
                                              List<ResourceMergedDO> allMergedList,
                                              Map<Long, ResourceItemDO> sourceMap,
                                              Map<Long, PriceResult> categoryPriceMap) {
        PriceResult result = new PriceResult();
        
        Map<String, Object> calcBase = source.getCalcBase();
        if (calcBase == null || !calcBase.containsKey("formula") || !calcBase.containsKey("variables")) {
            throw exception(RESOURCE_MERGED_CALC_BASE_INVALID);
        }
        
        String formula = (String) calcBase.get("formula");
        Map<String, Object> variablesConfig = (Map<String, Object>) calcBase.get("variables");
        
        // 构建变量值映射表（4个价格字段分别计算）
        Map<String, BigDecimal> taxExclBaseVars = new HashMap<>();
        Map<String, BigDecimal> taxInclBaseVars = new HashMap<>();
        Map<String, BigDecimal> taxExclCompileVars = new HashMap<>();
        Map<String, BigDecimal> taxInclCompileVars = new HashMap<>();
        
        for (Map.Entry<String, Object> entry : variablesConfig.entrySet()) {
            String varName = entry.getKey();
            Long categoryId = Long.valueOf(entry.getValue().toString());
            
            // 从类别价格映射表中获取价格
            PriceResult categoryPrice = categoryPriceMap.get(categoryId);
            if (categoryPrice == null) {
                throw exception(RESOURCE_MERGED_CALC_BASE_CATEGORY_NOT_FOUND);
            }
            
            taxExclBaseVars.put(varName, categoryPrice.taxExclBasePrice);
            taxInclBaseVars.put(varName, categoryPrice.taxInclBasePrice);
            taxExclCompileVars.put(varName, categoryPrice.taxExclCompilePrice);
            taxInclCompileVars.put(varName, categoryPrice.taxInclCompilePrice);
        }
        
        // 计算公式结果
        try {
            BigDecimal taxExclBaseSum = FormulaEvaluator.evaluate(formula, taxExclBaseVars);
            BigDecimal taxInclBaseSum = FormulaEvaluator.evaluate(formula, taxInclBaseVars);
            BigDecimal taxExclCompileSum = FormulaEvaluator.evaluate(formula, taxExclCompileVars);
            BigDecimal taxInclCompileSum = FormulaEvaluator.evaluate(formula, taxInclCompileVars);
            
            // 单位为%的工料机：合价 = 公式结果 × (消耗量 / 100)
            // 与定额基价模块保持一致
            BigDecimal percentFactor = merged.getQuotaConsumption().divide(new BigDecimal("100"), 6, RoundingMode.HALF_UP);
            
            result.taxExclBasePrice = taxExclBaseSum.multiply(percentFactor).setScale(4, RoundingMode.HALF_UP);
            result.taxInclBasePrice = taxInclBaseSum.multiply(percentFactor).setScale(4, RoundingMode.HALF_UP);
            result.taxExclCompilePrice = taxExclCompileSum.multiply(percentFactor).setScale(4, RoundingMode.HALF_UP);
            result.taxInclCompilePrice = taxInclCompileSum.multiply(percentFactor).setScale(4, RoundingMode.HALF_UP);
        } catch (Exception e) {
            log.error("[calculateWithCalcBase] 公式计算失败，formula={}, error={}", formula, e.getMessage());
            throw exception(RESOURCE_MERGED_FORMULA_PARSE_ERROR);
        }
        
        return result;
    }

    /**
     * 安全乘法（处理 null 值）
     */
    private BigDecimal multiplyOrZero(BigDecimal value, BigDecimal factor) {
        if (value == null) {
            return BigDecimal.ZERO;
        }
        return value.multiply(factor).setScale(4, RoundingMode.HALF_UP);
    }

    /**
     * 价格结果对象
     */
    private static class PriceResult {
        BigDecimal taxExclBasePrice = BigDecimal.ZERO;
        BigDecimal taxInclBasePrice = BigDecimal.ZERO;
        BigDecimal taxExclCompilePrice = BigDecimal.ZERO;
        BigDecimal taxInclCompilePrice = BigDecimal.ZERO;
        
        void add(PriceResult other) {
            this.taxExclBasePrice = this.taxExclBasePrice.add(other.taxExclBasePrice);
            this.taxInclBasePrice = this.taxInclBasePrice.add(other.taxInclBasePrice);
            this.taxExclCompilePrice = this.taxExclCompilePrice.add(other.taxExclCompilePrice);
            this.taxInclCompilePrice = this.taxInclCompilePrice.add(other.taxInclCompilePrice);
        }
    }
    
    /**
     * 更新父工料机的 is_merged 标记
     * 
     * @param mergedId 父工料机ID
     * @param isMerged 是否为复合工料机
     */
    private void updateParentIsMerged(Long mergedId, boolean isMerged) {
        if (mergedId == null) {
            return;
        }
        
        ResourceItemDO parent = resourceItemMapper.selectById(mergedId);
        if (parent == null) {
            return;
        }
        
        int newValue = isMerged ? 1 : 0;
        if (parent.getIsMerged() == null || parent.getIsMerged() != newValue) {
            log.info("[updateParentIsMerged] 更新复合工料机标记，mergedId={}, isMerged={}", mergedId, isMerged);
            resourceItemMapper.updateIsMerged(mergedId, newValue);
        }
    }
    
    /**
     * 检查并更新父工料机的 is_merged 标记
     * 如果父工料机没有子项了，则将 is_merged 设为 0
     * 
     * @param mergedId 父工料机ID
     */
    private void checkAndUpdateParentIsMerged(Long mergedId) {
        if (mergedId == null) {
            return;
        }
        
        // 查询该父工料机是否还有子项
        List<ResourceMergedDO> children = resourceMergedMapper.selectByMergedId(mergedId);
        boolean hasChildren = children != null && !children.isEmpty();
        
        // 更新 is_merged 标记
        updateParentIsMerged(mergedId, hasChildren);
    }
}
