package com.yd.csf.service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yd.csf.service.dto.GradeQueryParam;
import com.yd.csf.service.model.MemberGradeConfig;
import com.yd.csf.service.dao.MemberGradeConfigMapper;
import com.yd.csf.service.service.IMemberGradeConfigService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 会员等级配置表 服务实现类
 * </p>
 *
 * @author zxm
 * @since 2025-10-15
 */
@Slf4j
@Service
public class MemberGradeConfigServiceImpl extends ServiceImpl<MemberGradeConfigMapper, MemberGradeConfig> implements IMemberGradeConfigService {

    /**
     * 批量根据积分值查询对应的等级配置
     * @param paramList 业务员积分参数列表
     * @return Map<业务员ID, 匹配的等级配置>（未匹配到的不包含在Map中）
     */
    @Override
    public Map<String, MemberGradeConfig> batchGetGradeByPromotion(List<GradeQueryParam> paramList) {
        if (CollectionUtils.isEmpty(paramList)) {
            return Collections.emptyMap();
        }

        // 一次性查询所有启用且未删除的等级配置
        List<MemberGradeConfig> allGrades = this.lambdaQuery()
                .eq(MemberGradeConfig::getStatus, 1)
                .eq(MemberGradeConfig::getIsDeleted, 0)
                .list();

        if (CollectionUtils.isEmpty(allGrades)) {
            log.warn("未查询到任何启用的等级配置");
            return Collections.emptyMap();
        }

        // 打印 min_value 为空的数据告警（业务上 min_value 应有值）
        allGrades.stream()
                .filter(g -> g.getMinValue() == null)
                .forEach(g -> log.error("等级配置 {} 的 min_value 为空，请检查数据！", g.getId()));

        // 按 min_value 升序，max_value 为 null 的排在最后（null 视为无穷大）
        allGrades.sort(
                Comparator.comparing(MemberGradeConfig::getMinValue,
                        Comparator.nullsFirst(BigDecimal::compareTo))
                        .thenComparing(MemberGradeConfig::getMaxValue,
                                Comparator.nullsLast(BigDecimal::compareTo))
        );

        // 构建结果 Map
        Map<String, MemberGradeConfig> resultMap = new HashMap<>();
        for (GradeQueryParam param : paramList) {
            String agentId = param.getAgentId();
            BigDecimal promotionValue = param.getPromotionValue();

            if (promotionValue == null) {
                log.warn("业务员 {} 的晋升积分为空，跳过", agentId);
                continue;
            }

            // 在内存中匹配等级（左闭右开区间，null 表示无限制）
            MemberGradeConfig matched = allGrades.stream()
                    .filter(g -> (g.getMinValue() == null || g.getMinValue().compareTo(promotionValue) <= 0)
                            && (g.getMaxValue() == null || g.getMaxValue().compareTo(promotionValue) > 0))
                    .findFirst()
                    .orElse(null);

            if (matched != null) {
                resultMap.put(agentId, matched);
            } else {
                log.warn("业务员 {} 的晋升积分 {} 未匹配到任何等级", agentId, promotionValue);
            }
        }

        // 检测是否有多个配置匹配同一积分（配置错误告警）
        checkGradeOverlap(allGrades, paramList);

        return resultMap;
    }

    @Override
    public MemberGradeConfig queryOne(String gradeCode) {
        return this.getOne(new LambdaQueryWrapper<MemberGradeConfig>()
                .eq(MemberGradeConfig::getGradeCode,gradeCode)
                .last(" limit 1 ")
        );
    }

    /**
     * 检查等级区间是否有重叠
     */
    private void checkGradeOverlap(List<MemberGradeConfig> allGrades, List<GradeQueryParam> paramList) {
        // 遍历参数，统计每个积分值匹配到的配置数量，超过1则告警
        for (GradeQueryParam param : paramList) {
            if (param.getPromotionValue() == null) {
                continue;
            }
            long count = allGrades.stream()
                    .filter(g -> (g.getMinValue() == null || g.getMinValue().compareTo(param.getPromotionValue()) <= 0)
                            && (g.getMaxValue() == null || g.getMaxValue().compareTo(param.getPromotionValue()) > 0))
                    .count();
            if (count > 1) {
                log.error("配置错误：业务员 {} 的积分 {} 匹配到 {} 个等级配置，请检查区间重叠！",
                        param.getAgentId(), param.getPromotionValue(), count);
            }
        }
    }
}