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

import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import com.yhy.module.core.controller.admin.quota.vo.QuotaAdjustmentSaveReqVO;
import com.yhy.module.core.dal.dataobject.quota.QuotaAdjustmentDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaItemDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaCatalogItemDO;
import com.yhy.module.core.dal.dataobject.resource.ResourceCategoryDO;
import com.yhy.module.core.dal.dataobject.resource.ResourceCategoryTreeDO;
import com.yhy.module.core.dal.dataobject.resource.ResourceItemDO;
import com.yhy.module.core.dal.mysql.quota.QuotaAdjustmentMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaCatalogItemMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaItemMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaResourceMapper;
import com.yhy.module.core.dal.mysql.resource.ResourceCategoryMapper;
import com.yhy.module.core.dal.mysql.resource.ResourceCategoryTreeMapper;
import com.yhy.module.core.dal.mysql.resource.ResourceCategoryTreeMappingMapper;
import com.yhy.module.core.dal.mysql.resource.ResourceItemMapper;
import com.yhy.module.core.dal.dataobject.resource.ResourceCategoryTreeMappingDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaResourceDO;
import com.yhy.module.core.enums.quota.RoundingRuleEnum;
import com.yhy.module.core.enums.ErrorCodeConstants;
import com.yhy.module.core.enums.quota.QuotaAdjustmentTypeEnum;
import com.yhy.module.core.service.quota.QuotaAdjustmentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;

/**
 * 定额调整设置 Service 实现类
 */
@Service
@Validated
@Slf4j
public class QuotaAdjustmentServiceImpl implements QuotaAdjustmentService {

    @Resource
    private QuotaAdjustmentMapper quotaAdjustmentMapper;

    @Resource
    private QuotaItemMapper quotaItemMapper;

    @Resource
    private QuotaCatalogItemMapper quotaCatalogItemMapper;

    @Resource
    private ResourceCategoryTreeMapper resourceCategoryTreeMapper;

    @Resource
    private ResourceCategoryMapper resourceCategoryMapper;

    @Resource
    private ResourceCategoryTreeMappingMapper resourceCategoryTreeMappingMapper;

    @Resource
    private QuotaResourceMapper quotaResourceMapper;

    @Resource
    private ResourceItemMapper resourceItemMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createQuotaAdjustment(QuotaAdjustmentSaveReqVO createReqVO) {
        // 验证定额子目是否存在
        validateQuotaItemExists(createReqVO.getQuotaItemId());

        // 验证调整类型
        validateAdjustmentType(createReqVO.getAdjustmentType());

        // 验证调整规则
        validateAdjustmentRules(createReqVO.getAdjustmentType(), createReqVO.getAdjustmentRules());

        // 插入
        QuotaAdjustmentDO adjustment = QuotaAdjustmentDO.builder()
                .quotaItemId(createReqVO.getQuotaItemId())
                .name(createReqVO.getName())
                .content(createReqVO.getContent())
                .adjustmentType(createReqVO.getAdjustmentType())
                .adjustmentRules(createReqVO.getAdjustmentRules())
                .sortOrder(createReqVO.getSortOrder() != null ? createReqVO.getSortOrder() : 0)
                .build();
        quotaAdjustmentMapper.insert(adjustment);
        return adjustment.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateQuotaAdjustment(QuotaAdjustmentSaveReqVO updateReqVO) {
        // 验证存在
        validateQuotaAdjustmentExists(updateReqVO.getId());

        // 验证定额子目是否存在
        validateQuotaItemExists(updateReqVO.getQuotaItemId());

        // 验证调整类型
        validateAdjustmentType(updateReqVO.getAdjustmentType());

        // 验证调整规则
        validateAdjustmentRules(updateReqVO.getAdjustmentType(), updateReqVO.getAdjustmentRules());

        // 更新
        QuotaAdjustmentDO updateObj = QuotaAdjustmentDO.builder()
                .id(updateReqVO.getId())
                .quotaItemId(updateReqVO.getQuotaItemId())
                .name(updateReqVO.getName())
                .content(updateReqVO.getContent())
                .adjustmentType(updateReqVO.getAdjustmentType())
                .adjustmentRules(updateReqVO.getAdjustmentRules())
                .sortOrder(updateReqVO.getSortOrder())
                .build();
        quotaAdjustmentMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteQuotaAdjustment(Long id) {
        // 验证存在
        validateQuotaAdjustmentExists(id);
        // 删除
        quotaAdjustmentMapper.deleteById(id);
    }

    @Override
    public QuotaAdjustmentDO getQuotaAdjustment(Long id) {
        return quotaAdjustmentMapper.selectById(id);
    }

    @Override
    public List<QuotaAdjustmentDO> getQuotaAdjustmentList(Long quotaItemId) {
        return quotaAdjustmentMapper.selectListByQuotaItemId(quotaItemId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void swapSort(Long id1, Long id2) {
        // 验证两个调整设置是否存在
        QuotaAdjustmentDO adjustment1 = quotaAdjustmentMapper.selectByIdForUpdate(id1);
        QuotaAdjustmentDO adjustment2 = quotaAdjustmentMapper.selectByIdForUpdate(id2);

        if (adjustment1 == null) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_NOT_EXISTS);
        }
        if (adjustment2 == null) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_NOT_EXISTS);
        }

        // 验证是否属于同一个定额子目
        if (!adjustment1.getQuotaItemId().equals(adjustment2.getQuotaItemId())) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_NOT_SAME_QUOTA_ITEM);
        }

        // 交换排序值
        Integer tempSort = adjustment1.getSortOrder();
        adjustment1.setSortOrder(adjustment2.getSortOrder());
        adjustment2.setSortOrder(tempSort);

        quotaAdjustmentMapper.updateById(adjustment1);
        quotaAdjustmentMapper.updateById(adjustment2);
    }

    @Override
    public BigDecimal calculateAdjustedConsumeQty(Long quotaItemId, BigDecimal originalConsumeQty) {
        if (originalConsumeQty == null) {
            return BigDecimal.ZERO;
        }

        // 获取所有调整设置
        List<QuotaAdjustmentDO> adjustments = getQuotaAdjustmentList(quotaItemId);
        if (adjustments.isEmpty()) {
            return originalConsumeQty;
        }

        // 依次应用调整规则
        BigDecimal result = originalConsumeQty;
        for (QuotaAdjustmentDO adjustment : adjustments) {
            result = applyAdjustment(result, adjustment);
        }

        return result.setScale(6, RoundingMode.HALF_UP);
    }

    @Override
    public BigDecimal calculateAdjustedDosage(Long quotaItemId, String resourceCode, BigDecimal originalDosage) {
        if (originalDosage == null) {
            return BigDecimal.ZERO;
        }
        if (resourceCode == null || resourceCode.trim().isEmpty()) {
            return originalDosage;
        }

        // 获取所有调整设置
        List<QuotaAdjustmentDO> adjustments = getQuotaAdjustmentList(quotaItemId);
        if (adjustments.isEmpty()) {
            return originalDosage;
        }

        // 查找材料调整类型的调整设置
        BigDecimal result = originalDosage;
        for (QuotaAdjustmentDO adjustment : adjustments) {
            if ("material_adjustment".equals(adjustment.getAdjustmentType())) {
                result = applyMaterialAdjustment(result, resourceCode, adjustment);
            }
        }

        return result.setScale(6, RoundingMode.HALF_UP);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveMaterialItems(Long adjustmentId, List<Map<String, Object>> items) {
        // 验证调整设置存在
        QuotaAdjustmentDO adjustment = getQuotaAdjustment(adjustmentId);
        if (adjustment == null) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_NOT_EXISTS);
        }

        // 验证调整类型
        if (!"material_adjustment".equals(adjustment.getAdjustmentType())) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_TYPE_INVALID);
        }

        // 验证明细数据
        validateMaterialItems(items);

        // 更新调整规则
        Map<String, Object> rules = adjustment.getAdjustmentRules();
        if (rules == null) {
            rules = new java.util.HashMap<>();
        }
        rules.put("items", items);

        adjustment.setAdjustmentRules(rules);
        quotaAdjustmentMapper.updateById(adjustment);
    }

    @Override
    public List<Map<String, Object>> getMaterialItems(Long adjustmentId) {
        QuotaAdjustmentDO adjustment = getQuotaAdjustment(adjustmentId);
        if (adjustment == null) {
            return new java.util.ArrayList<>();
        }

        Map<String, Object> rules = adjustment.getAdjustmentRules();
        if (rules == null || !rules.containsKey("items")) {
            return new java.util.ArrayList<>();
        }

        Object itemsObj = rules.get("items");
        if (itemsObj instanceof List) {
            return (List<Map<String, Object>>) itemsObj;
        }

        return new java.util.ArrayList<>();
    }

    /**
     * 应用单个调整规则
     */
    private BigDecimal applyAdjustment(BigDecimal value, QuotaAdjustmentDO adjustment) {
        String type = adjustment.getAdjustmentType();
        Map<String, Object> rules = adjustment.getAdjustmentRules();

        if (rules == null || rules.isEmpty()) {
            return value;
        }

        QuotaAdjustmentTypeEnum typeEnum = QuotaAdjustmentTypeEnum.valueOfCode(type);
        if (typeEnum == null) {
            log.warn("未知的调整类型: {}", type);
            return value;
        }

        switch (typeEnum) {
            case PERCENTAGE:
                return applyPercentageAdjustment(value, rules);
            case FIXED_VALUE:
                return applyFixedValueAdjustment(value, rules);
            case FORMULA:
                return applyFormulaAdjustment(value, rules);
            case CONDITIONAL:
                return applyConditionalAdjustment(value, rules);
            default:
                return value;
        }
    }

    /**
     * 应用百分比调整
     */
    private BigDecimal applyPercentageAdjustment(BigDecimal value, Map<String, Object> rules) {
        Object valueObj = rules.get("value");
        Object operatorObj = rules.get("operator");

        if (valueObj == null || operatorObj == null) {
            return value;
        }

        BigDecimal percentage = new BigDecimal(valueObj.toString());
        String operator = operatorObj.toString();

        if ("increase".equals(operator)) {
            // 增加：value * (1 + percentage/100)
            return value.multiply(BigDecimal.ONE.add(percentage.divide(new BigDecimal("100"), 6, RoundingMode.HALF_UP)));
        } else if ("decrease".equals(operator)) {
            // 减少：value * (1 - percentage/100)
            return value.multiply(BigDecimal.ONE.subtract(percentage.divide(new BigDecimal("100"), 6, RoundingMode.HALF_UP)));
        }

        return value;
    }

    /**
     * 应用固定值调整
     */
    private BigDecimal applyFixedValueAdjustment(BigDecimal value, Map<String, Object> rules) {
        Object valueObj = rules.get("value");
        Object operatorObj = rules.get("operator");

        if (valueObj == null || operatorObj == null) {
            return value;
        }

        BigDecimal fixedValue = new BigDecimal(valueObj.toString());
        String operator = operatorObj.toString();

        if ("increase".equals(operator)) {
            return value.add(fixedValue);
        } else if ("decrease".equals(operator)) {
            return value.subtract(fixedValue);
        }

        return value;
    }

    /**
     * 应用公式调整（简化实现）
     */
    private BigDecimal applyFormulaAdjustment(BigDecimal value, Map<String, Object> rules) {
        // TODO: 实现复杂的公式计算逻辑
        log.warn("公式调整暂未实现");
        return value;
    }

    /**
     * 应用条件调整（简化实现）
     */
    private BigDecimal applyConditionalAdjustment(BigDecimal value, Map<String, Object> rules) {
        // TODO: 实现条件判断逻辑
        log.warn("条件调整暂未实现");
        return value;
    }

    /**
     * 应用材料调整
     */
    private BigDecimal applyMaterialAdjustment(BigDecimal dosage, String resourceCode, QuotaAdjustmentDO adjustment) {
        Map<String, Object> rules = adjustment.getAdjustmentRules();
        if (rules == null || !rules.containsKey("items")) {
            return dosage;
        }

        Object itemsObj = rules.get("items");
        if (!(itemsObj instanceof List)) {
            return dosage;
        }

        List<Map<String, Object>> items = (List<Map<String, Object>>) itemsObj;
        for (Map<String, Object> item : items) {
            String itemCode = (String) item.get("resourceCode");
            if (resourceCode.equals(itemCode)) {
                Object adjustValueObj = item.get("adjustValue");
                if (adjustValueObj != null) {
                    BigDecimal adjustValue = new BigDecimal(adjustValueObj.toString());
                    return dosage.add(adjustValue);
                }
            }
        }

        return dosage;
    }

    /**
     * 验证材料明细
     */
    private void validateMaterialItems(List<Map<String, Object>> items) {
        if (items == null || items.isEmpty()) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_RULES_INVALID);
        }

        // 检查重复的工料机编码
        java.util.Set<String> codes = new java.util.HashSet<>();
        for (Map<String, Object> item : items) {
            String resourceCode = (String) item.get("resourceCode");
            if (resourceCode == null || resourceCode.trim().isEmpty()) {
                throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_RULES_INVALID);
            }

            if (codes.contains(resourceCode)) {
                throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_MATERIAL_CODE_DUPLICATE, resourceCode);
            }
            codes.add(resourceCode);

            // 验证调整值
            Object adjustValueObj = item.get("adjustValue");
            if (adjustValueObj == null) {
                throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_RULES_INVALID);
            }

            try {
                new BigDecimal(adjustValueObj.toString());
            } catch (NumberFormatException e) {
                throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_RULES_INVALID);
            }
        }
    }

    @Override
    public List<Map<String, Object>> getAvailableCategories(Long quotaItemId) {
        // 1. 获取定额子目
        QuotaItemDO quotaItem = quotaItemMapper.selectById(quotaItemId);
        if (quotaItem == null) {
            throw exception(ErrorCodeConstants.QUOTA_ITEM_NOT_EXISTS);
        }

        // 2. 获取工料机专业ID
        Long categoryTreeId = getCategoryTreeIdByQuotaItem(quotaItemId);
        if (categoryTreeId == null) {
            throw exception(ErrorCodeConstants.QUOTA_SPECIALTY_NOT_BOUND);
        }

        // 3. 获取工料机专业节点
        ResourceCategoryTreeDO categoryTree = resourceCategoryTreeMapper.selectById(categoryTreeId);
        if (categoryTree == null) {
            throw exception(ErrorCodeConstants.RESOURCE_CATEGORY_TREE_NOT_EXISTS);
        }

        // 4. 获取类别列表（通过映射表）
        List<ResourceCategoryTreeMappingDO> mappings = resourceCategoryTreeMappingMapper.selectList(
            "category_tree_id", categoryTreeId
        );
        if (mappings == null || mappings.isEmpty()) {
            return new java.util.ArrayList<>();
        }

        List<Long> categoryIds = mappings.stream()
            .map(ResourceCategoryTreeMappingDO::getCategoryId)
            .collect(java.util.stream.Collectors.toList());

        List<ResourceCategoryDO> categories = resourceCategoryMapper.selectList(
            "id", categoryIds
        );
        
        // 5. 转换为VO
        List<Map<String, Object>> result = new java.util.ArrayList<>();
        for (ResourceCategoryDO category : categories) {
            Map<String, Object> map = new java.util.HashMap<>();
            map.put("categoryId", category.getId());
            map.put("categoryName", category.getName());
            map.put("categoryType", getCategoryType(category.getCode()));
            map.put("categoryCode", category.getCode());
            result.add(map);
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveDynamicConfig(Long adjustmentId, List<Map<String, Object>> categories) {
        // 验证调整设置存在
        QuotaAdjustmentDO adjustment = getQuotaAdjustment(adjustmentId);
        if (adjustment == null) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_NOT_EXISTS);
        }

        // 验证调整类型
        if (!"dynamic_adjustment".equals(adjustment.getAdjustmentType())) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_TYPE_INVALID);
        }

        // 验证配置数据
        validateDynamicConfig(categories);

        // 更新调整规则
        Map<String, Object> rules = adjustment.getAdjustmentRules();
        if (rules == null) {
            rules = new java.util.HashMap<>();
        }
        rules.put("categories", categories);

        adjustment.setAdjustmentRules(rules);
        quotaAdjustmentMapper.updateById(adjustment);
    }

    @Override
    public List<Map<String, Object>> getDynamicConfig(Long adjustmentId) {
        QuotaAdjustmentDO adjustment = getQuotaAdjustment(adjustmentId);
        if (adjustment == null) {
            return new java.util.ArrayList<>();
        }

        Map<String, Object> rules = adjustment.getAdjustmentRules();
        if (rules == null || !rules.containsKey("categories")) {
            return new java.util.ArrayList<>();
        }

        Object categoriesObj = rules.get("categories");
        if (categoriesObj instanceof List) {
            return (List<Map<String, Object>>) categoriesObj;
        }

        return new java.util.ArrayList<>();
    }

    @Override
    public Map<String, BigDecimal> calculateDynamic(Long adjustmentId, Map<String, BigDecimal> inputValues) {
        // 获取动态调整配置
        List<Map<String, Object>> categories = getDynamicConfig(adjustmentId);
        if (categories.isEmpty()) {
            return new java.util.HashMap<>();
        }

        Map<String, BigDecimal> results = new java.util.HashMap<>();

        for (Map<String, Object> category : categories) {
            String categoryId = category.get("categoryId").toString();
            BigDecimal inputValue = inputValues.get(categoryId);

            if (inputValue == null) {
                continue;
            }

            // 计算调整结果
            BigDecimal result = calculateDynamicForCategory(category, inputValue);
            results.put(categoryId, result);
        }

        return results;
    }

    /**
     * 计算单个类别的动态调整结果
     */
    private BigDecimal calculateDynamicForCategory(Map<String, Object> category, BigDecimal inputValue) {
        // 获取配置参数
        BigDecimal coefficient = new BigDecimal(category.get("coefficient").toString());
        BigDecimal minValue = new BigDecimal(category.get("minValue").toString());
        BigDecimal maxValue = new BigDecimal(category.get("maxValue").toString());
        BigDecimal denominator = new BigDecimal(category.get("denominator").toString());
        BigDecimal baseValue = new BigDecimal(category.get("baseValue").toString());
        String roundingRule = (String) category.get("roundingRule");

        // 1. 验证输入值范围
        if (inputValue.compareTo(minValue) < 0 || inputValue.compareTo(maxValue) > 0) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_INPUT_VALUE_OUT_OF_RANGE, 
                    inputValue, minValue, maxValue);
        }

        // 2. 计算中间值：(输入值 - 基础值) / 分母
        BigDecimal intermediate = inputValue.subtract(baseValue).divide(denominator, 6, RoundingMode.HALF_UP);

        // 3. 应用取值规则
        BigDecimal rounded = applyRoundingRule(intermediate, roundingRule);

        // 4. 乘以系数
        BigDecimal result = rounded.multiply(coefficient);

        // 5. 负数结果视为0
        if (result.compareTo(BigDecimal.ZERO) < 0) {
            result = BigDecimal.ZERO;
        }

        return result.setScale(6, RoundingMode.HALF_UP);
    }

    /**
     * 应用取值规则
     */
    private BigDecimal applyRoundingRule(BigDecimal value, String ruleCode) {
        RoundingRuleEnum rule = RoundingRuleEnum.valueOfCode(ruleCode);
        if (rule == null) {
            return value;
        }

        switch (rule) {
            case ROUND_UP:
                // 向上取整
                return value.setScale(0, RoundingMode.UP);
            case ROUND_DOWN:
                // 向下取整
                return value.setScale(0, RoundingMode.DOWN);
            case ROUND_HALF_UP:
                // 四舍五入
                return value.setScale(0, RoundingMode.HALF_UP);
            case NO_ROUNDING:
            default:
                // 不取整
                return value;
        }
    }

    /**
     * 获取定额子目对应的工料机专业ID
     */
    private Long getCategoryTreeIdByQuotaItem(Long quotaItemId) {
        // 1. 查询定额子目
        QuotaItemDO quotaItem = quotaItemMapper.selectById(quotaItemId);
        if (quotaItem == null) {
            return null;
        }

        // 2. 查询内容节点
        QuotaCatalogItemDO contentNode = quotaCatalogItemMapper.selectById(quotaItem.getCatalogItemId());
        if (contentNode == null) {
            return null;
        }

        // 3. 向上追溯到定额专业节点
        QuotaCatalogItemDO current = contentNode;
        while (current != null) {
            Map<String, Object> attributes = current.getAttributes();
            if (attributes != null && "specialty".equals(attributes.get("node_type"))) {
                return current.getCategoryTreeId();
            }
            if (current.getParentId() == null) {
                break;
            }
            current = quotaCatalogItemMapper.selectById(current.getParentId());
        }

        return null;
    }

    /**
     * 根据类别代码获取类别类型
     */
    private String getCategoryType(String code) {
        if (code == null) {
            return "unknown";
        }
        // 简单映射，实际可能需要更复杂的逻辑
        if (code.contains("人") || code.equalsIgnoreCase("RG")) {
            return "labor";
        } else if (code.contains("材") || code.equalsIgnoreCase("CL")) {
            return "material";
        } else if (code.contains("机") || code.equalsIgnoreCase("JX")) {
            return "machine";
        }
        return "other";
    }

    /**
     * 验证动态调整配置
     */
    private void validateDynamicConfig(List<Map<String, Object>> categories) {
        if (categories == null || categories.isEmpty()) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_RULES_INVALID);
        }

        // 检查重复的类别ID
        java.util.Set<String> categoryIds = new java.util.HashSet<>();
        for (Map<String, Object> category : categories) {
            String categoryId = category.get("categoryId").toString();
            if (categoryIds.contains(categoryId)) {
                throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_CATEGORY_DUPLICATE, categoryId);
            }
            categoryIds.add(categoryId);

            // 验证参数
            validateDynamicCategoryParams(category);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveCoefficientConfig(Long adjustmentId, List<Map<String, Object>> categories) {
        // 验证调整设置存在
        QuotaAdjustmentDO adjustment = getQuotaAdjustment(adjustmentId);
        if (adjustment == null) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_NOT_EXISTS);
        }

        // 验证调整类型
        if (!"coefficient_adjustment".equals(adjustment.getAdjustmentType())) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_TYPE_INVALID);
        }

        // 验证配置数据
        validateCoefficientConfig(categories);

        // 更新调整规则
        Map<String, Object> rules = adjustment.getAdjustmentRules();
        if (rules == null) {
            rules = new java.util.HashMap<>();
        }
        rules.put("categories", categories);

        adjustment.setAdjustmentRules(rules);
        quotaAdjustmentMapper.updateById(adjustment);
    }

    @Override
    public List<Map<String, Object>> getCoefficientConfig(Long adjustmentId) {
        QuotaAdjustmentDO adjustment = getQuotaAdjustment(adjustmentId);
        if (adjustment == null) {
            return new java.util.ArrayList<>();
        }

        Map<String, Object> rules = adjustment.getAdjustmentRules();
        if (rules == null || !rules.containsKey("categories")) {
            return new java.util.ArrayList<>();
        }

        Object categoriesObj = rules.get("categories");
        if (categoriesObj instanceof List) {
            return (List<Map<String, Object>>) categoriesObj;
        }

        return new java.util.ArrayList<>();
    }

    @Override
    public List<Map<String, Object>> getAvailableResources(Long quotaItemId) {
        // 1. 获取定额子目的所有工料机组成
        List<QuotaResourceDO> quotaResources = quotaResourceMapper.selectListByQuotaItemId(quotaItemId);
        if (quotaResources == null || quotaResources.isEmpty()) {
            return new java.util.ArrayList<>();
        }

        // 2. 获取工料机详情
        List<Long> resourceItemIds = quotaResources.stream()
            .map(QuotaResourceDO::getResourceItemId)
            .collect(java.util.stream.Collectors.toList());

        List<ResourceItemDO> resourceItems = resourceItemMapper.selectList(
            "id", resourceItemIds
        );

        // 3. 转换为VO（从快照中获取编码和名称）
        List<Map<String, Object>> result = new java.util.ArrayList<>();
        for (QuotaResourceDO quotaResource : quotaResources) {
            Map<String, Object> map = new java.util.HashMap<>();
            map.put("resourceId", quotaResource.getResourceItemId());
            map.put("resourceCode", quotaResource.getResourceCode());
            map.put("resourceName", quotaResource.getResourceName());
            result.add(map);
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveMergeConfig(Long adjustmentId, List<Map<String, Object>> resources) {
        // 验证调整设置存在
        QuotaAdjustmentDO adjustment = getQuotaAdjustment(adjustmentId);
        if (adjustment == null) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_NOT_EXISTS);
        }

        // 验证调整类型
        if (!"dynamic_merge_quota".equals(adjustment.getAdjustmentType())) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_TYPE_INVALID);
        }

        // 验证配置数据
        validateMergeConfig(resources);

        // 更新调整规则
        Map<String, Object> rules = adjustment.getAdjustmentRules();
        if (rules == null) {
            rules = new java.util.HashMap<>();
        }
        rules.put("resources", resources);

        adjustment.setAdjustmentRules(rules);
        quotaAdjustmentMapper.updateById(adjustment);
    }

    @Override
    public List<Map<String, Object>> getMergeConfig(Long adjustmentId) {
        QuotaAdjustmentDO adjustment = getQuotaAdjustment(adjustmentId);
        if (adjustment == null) {
            return new java.util.ArrayList<>();
        }

        Map<String, Object> rules = adjustment.getAdjustmentRules();
        if (rules == null || !rules.containsKey("resources")) {
            return new java.util.ArrayList<>();
        }

        Object resourcesObj = rules.get("resources");
        if (resourcesObj instanceof List) {
            return (List<Map<String, Object>>) resourcesObj;
        }

        return new java.util.ArrayList<>();
    }

    @Override
    public Map<String, BigDecimal> calculateMerge(Long adjustmentId, Map<String, BigDecimal> inputValues) {
        // 获取动态合并配置
        List<Map<String, Object>> resources = getMergeConfig(adjustmentId);
        if (resources.isEmpty()) {
            return new java.util.HashMap<>();
        }

        Map<String, BigDecimal> results = new java.util.HashMap<>();

        for (Map<String, Object> resource : resources) {
            String resourceId = resource.get("resourceId").toString();
            BigDecimal inputValue = inputValues.get(resourceId);

            if (inputValue == null) {
                continue;
            }

            // 计算调整结果（复用动态调整的计算逻辑）
            BigDecimal result = calculateDynamicForCategory(resource, inputValue);
            results.put(resourceId, result);
        }

        return results;
    }

    /**
     * 验证系数调整配置
     */
    private void validateCoefficientConfig(List<Map<String, Object>> categories) {
        if (categories == null || categories.isEmpty()) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_RULES_INVALID);
        }

        // 检查重复的类别ID
        java.util.Set<String> categoryIds = new java.util.HashSet<>();
        for (Map<String, Object> category : categories) {
            String categoryId = category.get("categoryId").toString();
            if (categoryIds.contains(categoryId)) {
                throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_CATEGORY_DUPLICATE, categoryId);
            }
            categoryIds.add(categoryId);

            // 验证系数
            try {
                BigDecimal coefficient = new BigDecimal(category.get("coefficient").toString());
                if (coefficient.compareTo(BigDecimal.ZERO) <= 0) {
                    throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_COEFFICIENT_INVALID);
                }
            } catch (NumberFormatException e) {
                throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_RULES_INVALID);
            }
        }
    }

    /**
     * 验证动态合并配置
     */
    private void validateMergeConfig(List<Map<String, Object>> resources) {
        if (resources == null || resources.isEmpty()) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_RULES_INVALID);
        }

        // 检查重复的工料机ID
        java.util.Set<String> resourceIds = new java.util.HashSet<>();
        for (Map<String, Object> resource : resources) {
            String resourceId = resource.get("resourceId").toString();
            if (resourceIds.contains(resourceId)) {
                throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_RESOURCE_DUPLICATE, resourceId);
            }
            resourceIds.add(resourceId);

            // 验证参数（与动态调整相同）
            validateDynamicCategoryParams(resource);
        }
    }

    /**
     * 验证动态调整类别参数
     */
    private void validateDynamicCategoryParams(Map<String, Object> category) {
        try {
            BigDecimal coefficient = new BigDecimal(category.get("coefficient").toString());
            BigDecimal minValue = new BigDecimal(category.get("minValue").toString());
            BigDecimal maxValue = new BigDecimal(category.get("maxValue").toString());
            BigDecimal denominator = new BigDecimal(category.get("denominator").toString());
            BigDecimal baseValue = new BigDecimal(category.get("baseValue").toString());
            String roundingRule = (String) category.get("roundingRule");

            // 系数必须大于0
            if (coefficient.compareTo(BigDecimal.ZERO) <= 0) {
                throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_COEFFICIENT_INVALID);
            }

            // 最小值必须小于最大值
            if (minValue.compareTo(maxValue) >= 0) {
                throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_MIN_MAX_INVALID);
            }

            // 分母不能为0
            if (denominator.compareTo(BigDecimal.ZERO) == 0) {
                throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_DENOMINATOR_ZERO);
            }

            // 基础值必须在范围内
            if (baseValue.compareTo(minValue) < 0 || baseValue.compareTo(maxValue) > 0) {
                throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_BASE_VALUE_OUT_OF_RANGE);
            }

            // 验证取值规则
            if (RoundingRuleEnum.valueOfCode(roundingRule) == null) {
                throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_ROUNDING_RULE_INVALID);
            }
        } catch (NumberFormatException e) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_RULES_INVALID);
        }
    }

    private void validateQuotaAdjustmentExists(Long id) {
        if (quotaAdjustmentMapper.selectById(id) == null) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_NOT_EXISTS);
        }
    }

    private void validateQuotaItemExists(Long quotaItemId) {
        QuotaItemDO quotaItem = quotaItemMapper.selectById(quotaItemId);
        if (quotaItem == null) {
            throw exception(ErrorCodeConstants.QUOTA_ITEM_NOT_EXISTS);
        }
    }

    private void validateAdjustmentType(String adjustmentType) {
        QuotaAdjustmentTypeEnum typeEnum = QuotaAdjustmentTypeEnum.valueOfCode(adjustmentType);
        if (typeEnum == null) {
            throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_TYPE_INVALID);
        }
    }

    private void validateAdjustmentRules(String adjustmentType, Map<String, Object> rules) {
        if (rules == null || rules.isEmpty()) {
            return;
        }

        QuotaAdjustmentTypeEnum typeEnum = QuotaAdjustmentTypeEnum.valueOfCode(adjustmentType);
        if (typeEnum == null) {
            return;
        }

        // 根据不同类型验证规则结构
        switch (typeEnum) {
            case PERCENTAGE:
            case FIXED_VALUE:
                if (!rules.containsKey("value") || !rules.containsKey("operator")) {
                    throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_RULES_INVALID);
                }
                break;
            case FORMULA:
                if (!rules.containsKey("expression")) {
                    throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_RULES_INVALID);
                }
                break;
            case CONDITIONAL:
                if (!rules.containsKey("conditions")) {
                    throw exception(ErrorCodeConstants.QUOTA_ADJUSTMENT_RULES_INVALID);
                }
                break;
        }
    }
}
