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

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_CATALOG_ITEM_NOT_EXISTS;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_INCREMENT_BASE_THRESHOLD_INVALID;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_INCREMENT_BASE_THRESHOLD_NOT_ASCENDING;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_INCREMENT_FIELD_INCREMENTS_EMPTY;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_INCREMENT_SEQ_DUPLICATE;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_INCREMENT_STEP_INVALID;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_ITEM_CATALOG_NOT_RATE_MODE;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_ITEM_HAS_CHILDREN;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_ITEM_LEVEL_EXCEED;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_ITEM_NOT_DIRECTORY_CANNOT_SET_EDITABLE;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_ITEM_NOT_EXISTS;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_ITEM_NOT_SAME_LEVEL;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_ITEM_NOT_SAME_MODE;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_ITEM_PARENT_NOT_DIRECTORY;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_ITEM_PARENT_NOT_EXISTS;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_ITEM_PARENT_NOT_SAME_MODE;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_MODE_PARENT_NOT_SPECIALTY;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_TIER_COMPARE_TYPE_INVALID;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_TIER_COMPARE_TYPE_MIXED;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_TIER_FIELD_VALUES_EMPTY;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_TIER_SEQ_DUPLICATE;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_TIER_THRESHOLD_INVALID;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_RATE_TIER_THRESHOLD_NOT_ASCENDING;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import com.yhy.module.core.controller.admin.quota.vo.QuotaRateFieldRespVO;
import com.yhy.module.core.controller.admin.quota.vo.QuotaRateItemRespVO;
import com.yhy.module.core.controller.admin.quota.vo.QuotaRateItemSaveReqVO;
import com.yhy.module.core.controller.admin.quota.vo.QuotaRateModeNodeSaveReqVO;
import com.yhy.module.core.controller.admin.quota.vo.QuotaRateValueRulesReqVO;
import com.yhy.module.core.dal.dataobject.quota.QuotaCatalogItemDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaRateFieldDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaRateItemDO;
import com.yhy.module.core.dal.mysql.quota.QuotaCatalogItemMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaRateFieldMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaRateItemMapper;
import com.yhy.module.core.service.quota.QuotaRateFieldService;
import com.yhy.module.core.service.quota.QuotaRateItemService;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 定额费率项 Service 实现
 */
@Service
@RequiredArgsConstructor
public class QuotaRateItemServiceImpl implements QuotaRateItemService {

    private final QuotaRateItemMapper rateItemMapper;
    private final QuotaRateFieldMapper rateFieldMapper;
    private final QuotaRateFieldService rateFieldService;
    private final QuotaCatalogItemMapper catalogItemMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createRateModeNode(QuotaRateModeNodeSaveReqVO createReqVO) {
        // 1. 验证父节点必须是定额专业节点
        QuotaCatalogItemDO parentNode = catalogItemMapper.selectById(createReqVO.getParentId());
        if (parentNode == null) {
            throw exception(QUOTA_CATALOG_ITEM_NOT_EXISTS);
        }
        
        // 验证父节点类型必须是 specialty
        if (!"specialty".equals(parentNode.getNodeType())) {
            throw exception(QUOTA_RATE_MODE_PARENT_NOT_SPECIALTY);
        }
        
        // 2. 创建 rate_mode 节点
        QuotaCatalogItemDO rateModeNode = new QuotaCatalogItemDO();
        rateModeNode.setParentId(createReqVO.getParentId());
        // 使用 code 字段，如果未提供则自动生成
        rateModeNode.setCode(createReqVO.getCode() != null ? createReqVO.getCode() : "MODE_" + System.currentTimeMillis());
        rateModeNode.setName(createReqVO.getName());
        rateModeNode.setNodeType("rate_mode");
        rateModeNode.setSortOrder(createReqVO.getSortOrder() != null ? createReqVO.getSortOrder() : 0);
        
        // 设置路径
        String[] parentPath = parentNode.getPath();
        String[] newPath = new String[parentPath.length + 1];
        System.arraycopy(parentPath, 0, newPath, 0, parentPath.length);
        newPath[parentPath.length] = parentNode.getId().toString();
        rateModeNode.setPath(newPath);
        
        // 设置 attributes
        Map<String, Object> attributes = new HashMap<>();
        attributes.put("node_type", "rate_mode");
        rateModeNode.setAttributes(attributes);
        
        catalogItemMapper.insert(rateModeNode);
        return rateModeNode.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createRateItem(QuotaRateItemSaveReqVO createReqVO) {
        // 1. 验证模式节点
        validateRateModeNode(createReqVO.getCatalogItemId());
        
        // 2. 验证父节点
        validateParent(createReqVO.getParentId(), createReqVO.getCatalogItemId());
        
        // 3. 计算层级
        Integer level = calculateLevel(createReqVO.getParentId());
        if (level > 3) {
            throw exception(QUOTA_RATE_ITEM_LEVEL_EXCEED);
        }
        
        // 3. 设置排序值
        Integer sortOrder = createReqVO.getSortOrder();
        if (sortOrder == null) {
            sortOrder = rateItemMapper.selectMaxSortOrder(createReqVO.getCatalogItemId(), createReqVO.getParentId()) + 1;
        }
        
        // 4. 创建费率项
        QuotaRateItemDO rateItem = BeanUtils.toBean(createReqVO, QuotaRateItemDO.class);
        rateItem.setLevel(level);
        rateItem.setSortOrder(sortOrder);
        if (rateItem.getValueMode() == null) {
            rateItem.setValueMode(QuotaRateItemDO.VALUE_MODE_STATIC);
        }
        if (rateItem.getIsEditable() == null) {
            rateItem.setIsEditable(false);
        }
        
        rateItemMapper.insert(rateItem);
        return rateItem.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRateItem(QuotaRateItemSaveReqVO updateReqVO) {
        // 1. 验证存在
        QuotaRateItemDO existItem = validateRateItemExists(updateReqVO.getId());
        
        // 2. 验证 isEditable 只能在 directory 节点上修改
        if (updateReqVO.getIsEditable() != null && 
            !Objects.equals(existItem.getIsEditable(), updateReqVO.getIsEditable())) {
            if (!existItem.isDirectory()) {
                throw exception(QUOTA_RATE_ITEM_NOT_DIRECTORY_CANNOT_SET_EDITABLE);
            }
        }
        
        // 3. 如果修改了父节点，需要验证
        if (updateReqVO.getParentId() != null && 
            !Objects.equals(existItem.getParentId(), updateReqVO.getParentId())) {
            validateParent(updateReqVO.getParentId(), existItem.getCatalogItemId());
            // 重新计算层级
            Integer newLevel = calculateLevel(updateReqVO.getParentId());
            if (newLevel > 3) {
                throw exception(QUOTA_RATE_ITEM_LEVEL_EXCEED);
            }
            updateReqVO.setSortOrder(newLevel);
        }
        
        // 4. 更新
        QuotaRateItemDO updateObj = BeanUtils.toBean(updateReqVO, QuotaRateItemDO.class);
        rateItemMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRateItem(Long id) {
        // 1. 验证存在
        validateRateItemExists(id);
        
        // 2. 验证没有子节点
        if (rateItemMapper.hasChildren(id)) {
            throw exception(QUOTA_RATE_ITEM_HAS_CHILDREN);
        }
        
        // 3. 删除费率项（字段绑定基于catalog_item_id，不需要删除）
        rateItemMapper.deleteById(id);
    }

    @Override
    public QuotaRateItemDO getRateItem(Long id) {
        return rateItemMapper.selectById(id);
    }

    @Override
    public QuotaRateItemRespVO getRateItemDetail(Long id) {
        QuotaRateItemDO rateItem = validateRateItemExists(id);
        QuotaRateItemRespVO respVO = BeanUtils.toBean(rateItem, QuotaRateItemRespVO.class);
        
        // 查询字段绑定
        List<QuotaRateFieldRespVO> fields = rateFieldService.getRateFieldList(id);
        respVO.setFields(fields);
        respVO.setHasChildren(rateItemMapper.hasChildren(id));
        
        return respVO;
    }

    @Override
    public List<QuotaRateItemRespVO> getRateItemList(Long catalogItemId, Long parentId) {
        List<QuotaRateItemDO> list;
        if (parentId == null) {
            list = rateItemMapper.selectRootListByCatalogItemId(catalogItemId);
        } else {
            list = rateItemMapper.selectListByParentId(parentId);
        }
        
        // 转换并查询字段绑定
        return list.stream().map(item -> {
            QuotaRateItemRespVO respVO = BeanUtils.toBean(item, QuotaRateItemRespVO.class);
            respVO.setFields(rateFieldService.getRateFieldList(item.getId()));
            respVO.setHasChildren(rateItemMapper.hasChildren(item.getId()));
            return respVO;
        }).collect(Collectors.toList());
    }

    @Override
    public List<QuotaRateItemRespVO> getRateItemTree(Long catalogItemId) {
        // 1. 查询所有费率项
        List<QuotaRateItemDO> allItems = rateItemMapper.selectListByCatalogItemId(catalogItemId);
        if (CollUtil.isEmpty(allItems)) {
            return Collections.emptyList();
        }
        
        // 2. 查询字段绑定配置（基于catalog_item_id，所有费率项共享）
        List<QuotaRateFieldDO> allFieldConfigs = rateFieldMapper.selectListByCatalogItemId(catalogItemId);
        
        // 3. 转换为 VO
        List<QuotaRateItemRespVO> allVOs = allItems.stream().map(item -> {
            QuotaRateItemRespVO vo = BeanUtils.toBean(item, QuotaRateItemRespVO.class);
            
            // 构建字段列表
            List<QuotaRateFieldRespVO> fields = new ArrayList<>();
            
            // 从 settings.fieldValues 中读取所有字段值
            Map<Integer, java.math.BigDecimal> fieldValuesMap = new HashMap<>();
            if (item.getSettings() != null) {
                Map<String, Object> settings = item.getSettings();
                Object fieldValuesObj = settings.get("fieldValues");
                if (fieldValuesObj instanceof Map) {
                    @SuppressWarnings("unchecked")
                    Map<String, Object> fieldValues = (Map<String, Object>) fieldValuesObj;
                    
                    // 遍历所有字段值
                    fieldValues.forEach((key, value) -> {
                        try {
                            int fieldIndex = Integer.parseInt(key);
                            if (value != null) {
                                java.math.BigDecimal decimalValue = null;
                                if (value instanceof Number) {
                                    decimalValue = new java.math.BigDecimal(value.toString());
                                } else if (value instanceof String) {
                                    try {
                                        decimalValue = new java.math.BigDecimal((String) value);
                                    } catch (NumberFormatException e) {
                                        // 忽略无效值
                                    }
                                }
                                if (decimalValue != null) {
                                    fieldValuesMap.put(fieldIndex, decimalValue);
                                }
                            }
                        } catch (NumberFormatException e) {
                            // 忽略无效的字段索引
                        }
                    });
                }
            }
            
            // 如果有字段配置，使用配置信息
            if (!allFieldConfigs.isEmpty()) {
                fields = allFieldConfigs.stream().map(config -> {
                    QuotaRateFieldRespVO fieldVO = new QuotaRateFieldRespVO();
                    fieldVO.setId(config.getId());
                    fieldVO.setFieldIndex(config.getFieldIndex());
                    fieldVO.setFieldLabelId(config.getFieldLabelId());
                    fieldVO.setBindingIds(config.getBindingIds());
                    
                    // 从 fieldValuesMap 中获取字段值
                    java.math.BigDecimal fieldValue = fieldValuesMap.get(config.getFieldIndex());
                    if (fieldValue != null) {
                        fieldVO.setFieldValue(fieldValue);
                    }
                    
                    return fieldVO;
                }).collect(Collectors.toList());
            } else if (!fieldValuesMap.isEmpty()) {
                // 如果没有字段配置，但有字段值，创建简单的字段VO
                fields = fieldValuesMap.entrySet().stream()
                    .sorted(Map.Entry.comparingByKey())
                    .map(entry -> {
                        QuotaRateFieldRespVO fieldVO = new QuotaRateFieldRespVO();
                        fieldVO.setFieldIndex(entry.getKey());
                        fieldVO.setFieldValue(entry.getValue());
                        return fieldVO;
                    }).collect(Collectors.toList());
            }
            
            vo.setFields(fields);
            
            return vo;
        }).collect(Collectors.toList());
        
        // 4. 构建树结构
        return buildTree(allVOs);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void swapSort(Long nodeId1, Long nodeId2) {
        // 1. 查询两个节点
        QuotaRateItemDO node1 = validateRateItemExists(nodeId1);
        QuotaRateItemDO node2 = validateRateItemExists(nodeId2);
        
        // 2. 验证同级（parent_id 相同）
        if (!Objects.equals(node1.getParentId(), node2.getParentId())) {
            throw exception(QUOTA_RATE_ITEM_NOT_SAME_LEVEL);
        }
        
        // 3. 验证同一模式（catalog_item_id 相同）
        if (!Objects.equals(node1.getCatalogItemId(), node2.getCatalogItemId())) {
            throw exception(QUOTA_RATE_ITEM_NOT_SAME_MODE);
        }
        
        // 4. 交换排序值
        Integer temp = node1.getSortOrder();
        rateItemMapper.updateSortOrder(nodeId1, node2.getSortOrder());
        rateItemMapper.updateSortOrder(nodeId2, temp);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void moveNode(Long nodeId, Long targetNodeId) {
        // 1. 查询两个节点
        QuotaRateItemDO moveNode = validateRateItemExists(nodeId);
        QuotaRateItemDO targetNode = validateRateItemExists(targetNodeId);
        
        // 2. 验证同级（parent_id 相同）
        if (!Objects.equals(moveNode.getParentId(), targetNode.getParentId())) {
            throw exception(QUOTA_RATE_ITEM_NOT_SAME_LEVEL);
        }
        
        // 3. 验证同一模式（catalog_item_id 相同）
        if (!Objects.equals(moveNode.getCatalogItemId(), targetNode.getCatalogItemId())) {
            throw exception(QUOTA_RATE_ITEM_NOT_SAME_MODE);
        }
        
        // 4. 查询同级所有节点，按 sort_order 排序
        List<QuotaRateItemDO> siblings;
        if (moveNode.getParentId() == null) {
            siblings = rateItemMapper.selectRootListByCatalogItemId(moveNode.getCatalogItemId());
        } else {
            siblings = rateItemMapper.selectListByParentId(moveNode.getParentId());
        }
        
        // 按 sort_order 排序
        siblings.sort(Comparator.comparing(QuotaRateItemDO::getSortOrder));
        
        // 5. 找到移动节点和目标节点的当前位置
        int moveIndex = -1;
        int targetIndex = -1;
        for (int i = 0; i < siblings.size(); i++) {
            if (siblings.get(i).getId().equals(nodeId)) {
                moveIndex = i;
            }
            if (siblings.get(i).getId().equals(targetNodeId)) {
                targetIndex = i;
            }
        }
        
        if (moveIndex == -1 || targetIndex == -1) {
            throw exception(QUOTA_RATE_ITEM_NOT_EXISTS);
        }
        
        // 6. 如果位置相同或相邻，不需要移动
        if (moveIndex == targetIndex || moveIndex + 1 == targetIndex) {
            return;
        }
        
        // 7. 移动节点：从原位置移除，插入到目标位置之前
        QuotaRateItemDO movedNode = siblings.remove(moveIndex);
        // 重新计算目标位置（因为移除了一个元素）
        if (moveIndex < targetIndex) {
            targetIndex--;
        }
        siblings.add(targetIndex, movedNode);
        
        // 8. 重新分配 sort_order（从1开始）
        for (int i = 0; i < siblings.size(); i++) {
            QuotaRateItemDO node = siblings.get(i);
            rateItemMapper.updateSortOrder(node.getId(), i + 1);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void configValueRules(QuotaRateValueRulesReqVO reqVO) {
        // 1. 验证费率项存在
        QuotaRateItemDO rateItem = validateRateItemExists(reqVO.getRateItemId());
        
        // 2. 验证阶梯规则的合理性
        if (reqVO.getTiers() != null && !reqVO.getTiers().isEmpty()) {
            validateTierRules(reqVO.getTiers());
        }
        
        // 3. 验证增量规则的合理性
        if (reqVO.getIncrements() != null && !reqVO.getIncrements().isEmpty()) {
            validateIncrementRules(reqVO.getIncrements());
        }
        
        // 4. 构建规则
        Map<String, Object> settings = rateItem.getSettings();
        if (settings == null) {
            settings = new HashMap<>();
        }
        
        Map<String, Object> valueRules = new HashMap<>();
        if (reqVO.getTiers() != null) {
            valueRules.put("tiers", reqVO.getTiers());
        }
        if (reqVO.getIncrements() != null) {
            valueRules.put("increments", reqVO.getIncrements());
        }
        settings.put("valueRules", valueRules);
        
        // 5. 更新
        rateItem.setSettings(settings);
        rateItem.setValueMode(QuotaRateItemDO.VALUE_MODE_DYNAMIC);
        rateItemMapper.updateById(rateItem);
    }

    @Override
    @SuppressWarnings("unchecked")
    public Map<Integer, BigDecimal> calculateDynamicFields(Long rateItemId, BigDecimal baseValue) {
        QuotaRateItemDO rateItem = validateRateItemExists(rateItemId);
        
        if (!rateItem.isDynamicMode()) {
            return Collections.emptyMap();
        }
        
        Map<String, Object> valueRules = rateItem.getValueRules();
        if (valueRules == null) {
            return Collections.emptyMap();
        }
        
        Map<Integer, BigDecimal> result = new HashMap<>();
        
        // 1. 获取阶梯规则（默认计算方式）
        List<Map<String, Object>> tiers = (List<Map<String, Object>>) valueRules.get("tiers");
        if (tiers == null || tiers.isEmpty()) {
            return result;
        }
        
        // 2. 按阈值排序（从小到大）
        tiers.sort(Comparator.comparing(t -> new BigDecimal(t.get("threshold").toString())));
        
        // 3. 默认使用阶梯规则：找到第一个满足条件的阶梯
        Map<String, Object> matchedTier = null;
        for (Map<String, Object> tier : tiers) {
            BigDecimal threshold = new BigDecimal(tier.get("threshold").toString());
            String compareType = (String) tier.getOrDefault("compareType", "lte");
            
            boolean matched = false;
            switch (compareType) {
                case "lte":
                    matched = baseValue.compareTo(threshold) <= 0;
                    break;
                case "lt":
                    matched = baseValue.compareTo(threshold) < 0;
                    break;
                case "gte":
                    matched = baseValue.compareTo(threshold) >= 0;
                    break;
                case "gt":
                    matched = baseValue.compareTo(threshold) > 0;
                    break;
            }
            
            if (matched) {
                matchedTier = tier;
                break;
            }
        }
        
        // 4. 如果没有匹配到任何阶梯，使用最后一个阶梯（兜底逻辑）
        if (matchedTier == null && !tiers.isEmpty()) {
            matchedTier = tiers.get(tiers.size() - 1);
        }
        
        // 5. 获取阶梯对应的字段值（这是默认的计算结果）
        if (matchedTier != null) {
            Map<String, Object> fieldValues = (Map<String, Object>) matchedTier.get("fieldValues");
            if (fieldValues != null) {
                for (Map.Entry<String, Object> entry : fieldValues.entrySet()) {
                    Integer fieldIndex = Integer.parseInt(entry.getKey());
                    BigDecimal value = new BigDecimal(entry.getValue().toString());
                    result.put(fieldIndex, value);
                }
            }
        }
        
        // 6. 增量规则（可选，如果配置了则在阶梯基础上叠加）
        // 注意：增量规则是可选的，不配置也不影响阶梯规则的使用
        List<Map<String, Object>> increments = (List<Map<String, Object>>) valueRules.get("increments");
        if (increments != null && !increments.isEmpty()) {
            for (Map<String, Object> increment : increments) {
                BigDecimal step = new BigDecimal(increment.get("step").toString());
                BigDecimal baseThreshold = increment.get("baseThreshold") != null 
                        ? new BigDecimal(increment.get("baseThreshold").toString()) 
                        : BigDecimal.ZERO;
                
                // 计算超出基础阈值的部分
                if (baseValue.compareTo(baseThreshold) > 0) {
                    BigDecimal excess = baseValue.subtract(baseThreshold);
                    BigDecimal times = excess.divide(step, 10, RoundingMode.HALF_UP);
                    
                    Map<String, Object> fieldIncrements = (Map<String, Object>) increment.get("fieldIncrements");
                    if (fieldIncrements != null) {
                        for (Map.Entry<String, Object> entry : fieldIncrements.entrySet()) {
                            Integer fieldIndex = Integer.parseInt(entry.getKey());
                            BigDecimal incrementValue = new BigDecimal(entry.getValue().toString());
                            BigDecimal addValue = incrementValue.multiply(times);
                            
                            // 在阶梯基础值上叠加增量
                            result.merge(fieldIndex, addValue, BigDecimal::add);
                        }
                    }
                }
            }
        }
        
        return result;
    }

    @Override
    public QuotaRateItemDO validateRateItemExists(Long id) {
        QuotaRateItemDO rateItem = rateItemMapper.selectById(id);
        if (rateItem == null) {
            throw exception(QUOTA_RATE_ITEM_NOT_EXISTS);
        }
        return rateItem;
    }

    // ==================== 私有方法 ====================

    /**
     * 验证模式节点
     */
    private void validateRateModeNode(Long catalogItemId) {
        QuotaCatalogItemDO catalogItem = catalogItemMapper.selectById(catalogItemId);
        if (catalogItem == null) {
            throw exception(QUOTA_CATALOG_ITEM_NOT_EXISTS);
        }
        
        // 验证是否为 rate_mode 节点
        Map<String, Object> attributes = catalogItem.getAttributes();
        if (attributes == null || !"rate_mode".equals(attributes.get("node_type"))) {
            throw exception(QUOTA_RATE_ITEM_CATALOG_NOT_RATE_MODE);
        }
    }

    private void validateParent(Long parentId, Long catalogItemId) {
        if (parentId == null) {
            return;
        }
        QuotaRateItemDO parent = rateItemMapper.selectById(parentId);
        if (parent == null) {
            throw exception(QUOTA_RATE_ITEM_PARENT_NOT_EXISTS);
        }
        if (!Objects.equals(parent.getCatalogItemId(), catalogItemId)) {
            throw exception(QUOTA_RATE_ITEM_PARENT_NOT_SAME_MODE);
        }
        if (!parent.isDirectory()) {
            throw exception(QUOTA_RATE_ITEM_PARENT_NOT_DIRECTORY);
        }
    }

    private Integer calculateLevel(Long parentId) {
        if (parentId == null) {
            return 1;
        }
        QuotaRateItemDO parent = rateItemMapper.selectById(parentId);
        return parent == null ? 1 : parent.getLevel() + 1;
    }

    private List<QuotaRateItemRespVO> buildTree(List<QuotaRateItemRespVO> allVOs) {
        Map<Long, QuotaRateItemRespVO> voMap = allVOs.stream()
                .collect(Collectors.toMap(QuotaRateItemRespVO::getId, v -> v));
        
        List<QuotaRateItemRespVO> roots = new ArrayList<>();
        
        for (QuotaRateItemRespVO vo : allVOs) {
            if (vo.getParentId() == null) {
                roots.add(vo);
            } else {
                QuotaRateItemRespVO parent = voMap.get(vo.getParentId());
                if (parent != null) {
                    if (parent.getChildren() == null) {
                        parent.setChildren(new ArrayList<>());
                    }
                    parent.getChildren().add(vo);
                }
            }
        }
        
        // 设置 hasChildren
        for (QuotaRateItemRespVO vo : allVOs) {
            vo.setHasChildren(vo.getChildren() != null && !vo.getChildren().isEmpty());
        }
        
        return roots;
    }
    
    /**
     * 验证阶梯规则的合理性
     */
    private void validateTierRules(List<QuotaRateValueRulesReqVO.TierRule> tiers) {
        if (tiers == null || tiers.isEmpty()) {
            return;
        }
        
        // 1. 验证序号唯一性
        Set<Integer> seqSet = new HashSet<>();
        for (QuotaRateValueRulesReqVO.TierRule tier : tiers) {
            if (!seqSet.add(tier.getSeq())) {
                throw exception(QUOTA_RATE_TIER_SEQ_DUPLICATE, tier.getSeq());
            }
        }
        
        // 2. 按阈值排序
        List<QuotaRateValueRulesReqVO.TierRule> sortedTiers = new ArrayList<>(tiers);
        sortedTiers.sort(Comparator.comparing(QuotaRateValueRulesReqVO.TierRule::getThreshold));
        
        // 3. 验证阈值的连续性和合理性
        for (int i = 0; i < sortedTiers.size(); i++) {
            QuotaRateValueRulesReqVO.TierRule current = sortedTiers.get(i);
            
            // 验证阈值为正数
            if (current.getThreshold().compareTo(BigDecimal.ZERO) <= 0) {
                throw exception(QUOTA_RATE_TIER_THRESHOLD_INVALID, current.getSeq());
            }
            
            // 验证比较类型
            String compareType = current.getCompareType();
            if (compareType == null || (!compareType.equals("lte") && !compareType.equals("lt") 
                    && !compareType.equals("gte") && !compareType.equals("gt"))) {
                throw exception(QUOTA_RATE_TIER_COMPARE_TYPE_INVALID, current.getSeq());
            }
            
            // 验证字段值不为空
            if (current.getFieldValues() == null || current.getFieldValues().isEmpty()) {
                throw exception(QUOTA_RATE_TIER_FIELD_VALUES_EMPTY, current.getSeq());
            }
            
            // 验证相邻阶梯的阈值关系
            if (i > 0) {
                QuotaRateValueRulesReqVO.TierRule previous = sortedTiers.get(i - 1);
                
                // 如果前一个是 lte/lt，当前应该是 lte/lt，且阈值递增
                if ((previous.getCompareType().equals("lte") || previous.getCompareType().equals("lt"))
                        && (compareType.equals("lte") || compareType.equals("lt"))) {
                    if (current.getThreshold().compareTo(previous.getThreshold()) <= 0) {
                        throw exception(QUOTA_RATE_TIER_THRESHOLD_NOT_ASCENDING, 
                                previous.getSeq(), current.getSeq());
                    }
                }
                
                // 如果前一个是 gte/gt，当前应该是 gte/gt，且阈值递增
                if ((previous.getCompareType().equals("gte") || previous.getCompareType().equals("gt"))
                        && (compareType.equals("gte") || compareType.equals("gt"))) {
                    if (current.getThreshold().compareTo(previous.getThreshold()) <= 0) {
                        throw exception(QUOTA_RATE_TIER_THRESHOLD_NOT_ASCENDING, 
                                previous.getSeq(), current.getSeq());
                    }
                }
                
                // 不允许混用 lte/lt 和 gte/gt
                if ((previous.getCompareType().equals("lte") || previous.getCompareType().equals("lt"))
                        && (compareType.equals("gte") || compareType.equals("gt"))) {
                    throw exception(QUOTA_RATE_TIER_COMPARE_TYPE_MIXED, 
                            previous.getSeq(), current.getSeq());
                }
                if ((previous.getCompareType().equals("gte") || previous.getCompareType().equals("gt"))
                        && (compareType.equals("lte") || compareType.equals("lt"))) {
                    throw exception(QUOTA_RATE_TIER_COMPARE_TYPE_MIXED, 
                            previous.getSeq(), current.getSeq());
                }
            }
        }
    }
    
    /**
     * 验证增量规则的合理性
     */
    private void validateIncrementRules(List<QuotaRateValueRulesReqVO.IncrementRule> increments) {
        if (increments == null || increments.isEmpty()) {
            return;
        }
        
        // 1. 验证序号唯一性
        Set<Integer> seqSet = new HashSet<>();
        for (QuotaRateValueRulesReqVO.IncrementRule increment : increments) {
            if (!seqSet.add(increment.getSeq())) {
                throw exception(QUOTA_RATE_INCREMENT_SEQ_DUPLICATE, increment.getSeq());
            }
        }
        
        // 2. 按基准阈值排序
        List<QuotaRateValueRulesReqVO.IncrementRule> sortedIncrements = new ArrayList<>(increments);
        sortedIncrements.sort(Comparator.comparing(QuotaRateValueRulesReqVO.IncrementRule::getBaseThreshold));
        
        // 3. 验证增量规则的合理性
        for (int i = 0; i < sortedIncrements.size(); i++) {
            QuotaRateValueRulesReqVO.IncrementRule current = sortedIncrements.get(i);
            
            // 验证基准阈值为正数
            if (current.getBaseThreshold().compareTo(BigDecimal.ZERO) <= 0) {
                throw exception(QUOTA_RATE_INCREMENT_BASE_THRESHOLD_INVALID, current.getSeq());
            }
            
            // 验证步长为正数
            if (current.getStep().compareTo(BigDecimal.ZERO) <= 0) {
                throw exception(QUOTA_RATE_INCREMENT_STEP_INVALID, current.getSeq());
            }
            
            // 验证字段增量不为空
            if (current.getFieldIncrements() == null || current.getFieldIncrements().isEmpty()) {
                throw exception(QUOTA_RATE_INCREMENT_FIELD_INCREMENTS_EMPTY, current.getSeq());
            }
            
            // 验证相邻增量规则的基准阈值递增
            if (i > 0) {
                QuotaRateValueRulesReqVO.IncrementRule previous = sortedIncrements.get(i - 1);
                if (current.getBaseThreshold().compareTo(previous.getBaseThreshold()) <= 0) {
                    throw exception(QUOTA_RATE_INCREMENT_BASE_THRESHOLD_NOT_ASCENDING, 
                            previous.getSeq(), current.getSeq());
                }
            }
        }
    }
}
