package com.xy.xyaicpzs.jt.jtssq;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xy.xyaicpzs.domain.entity.*;
import com.xy.xyaicpzs.domain.vo.SSQThirdStepResultVO;
import com.xy.xyaicpzs.mapper.*;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 精推双色球第三步算法分析
 */
@Slf4j
@Component
public class BlueBallAnalysis {
    
    @Autowired
    private T6Mapper t6Mapper;
    
    @Autowired
    private T5Mapper t5Mapper;
    
    @Autowired
    private T8Mapper t8Mapper;
    
    @Autowired
    private BlueHistoryTopMapper blueHistoryTopMapper;
    
    @Autowired
    private BlueHistoryTop100Mapper blueHistoryTop100Mapper;
    
    /**
     * 球号和系数的关联类
     */
    @Data
    public static class BallWithCoefficient {
        private Integer ballNumber;
        private Double coefficient;
        private Integer masterBallNumber; // 主球号，用于标识来源

        public BallWithCoefficient(Integer ballNumber, Double coefficient, Integer masterBallNumber) {
            this.ballNumber = ballNumber;
            this.coefficient = coefficient;
            this.masterBallNumber = masterBallNumber;
        }
    }
    
    /**
     * 精推双色球第三步算法主方法
     * @param level 位置级别（H-高位/M-中位/L-低位）
     * @param redBalls 前6个红球号码
     * @param blueBall 蓝球号码
     * @param nextRedBalls 下期6个红球号码
     * @return 分析结果
     */
    public SSQThirdStepResultVO analyze(String level, List<Integer> redBalls, Integer blueBall, List<Integer> nextRedBalls) {
        // 参数验证
        validateInputParams(level, redBalls, blueBall, nextRedBalls);
        
        log.info("开始精推双色球第三步分析，策略：{}，红球：{}，蓝球：{}，下期红球：{}", 
                level, redBalls, blueBall, nextRedBalls);
        
        // 用于存储所有候选球号和对应的系数
        Map<Integer, List<BallWithCoefficient>> ballCoefficientMap = new HashMap<>();
        List<Integer> allCandidateBalls = new ArrayList<>();
        
        // Step 1: 根据6个红球号码获取候选球（T6表前12个）
        for (Integer redBall : redBalls) {
            List<BallWithCoefficient> ballsWithCoefficients = getTop12FromT6(redBall);
            for (BallWithCoefficient ball : ballsWithCoefficients) {
                ballCoefficientMap.computeIfAbsent(ball.getBallNumber(), k -> new ArrayList<>()).add(ball);
                allCandidateBalls.add(ball.getBallNumber());
            }
        }
        
        // Step 2: 从blue_history_top_100百期排行获取前2个球号
        List<Integer> top2HistoryTop100 = getTop2FromHistoryTop100();
        allCandidateBalls.addAll(top2HistoryTop100);
        
        // Step 3: 根据蓝球号码获取候选球（T5表前12个）
        List<BallWithCoefficient> blueBallsWithCoefficients = getTop12FromT5(blueBall);
        for (BallWithCoefficient ball : blueBallsWithCoefficients) {
            ballCoefficientMap.computeIfAbsent(ball.getBallNumber(), k -> new ArrayList<>()).add(ball);
            allCandidateBalls.add(ball.getBallNumber());
        }
        
        // Step 4: 根据下期6个红球号码获取候选球（T8表，根据策略不同）
        for (Integer nextRedBall : nextRedBalls) {
            List<BallWithCoefficient> nextRedBallsWithCoefficients = getT8BallsByLevel(nextRedBall, level);
            for (BallWithCoefficient ball : nextRedBallsWithCoefficients) {
                ballCoefficientMap.computeIfAbsent(ball.getBallNumber(), k -> new ArrayList<>()).add(ball);
                allCandidateBalls.add(ball.getBallNumber());
            }
        }
        
        // Step 5: 统计分析并生成结果
        List<SSQThirdStepResultVO.BallAnalysisResult> results = analyzeResults(allCandidateBalls, ballCoefficientMap);
        
        return SSQThirdStepResultVO.builder()
                .results(results)
                .strategy(level)
                .redBalls(redBalls)
                .blueBall(blueBall)
                .nextRedBalls(nextRedBalls)
                .build();
    }
    
    /**
     * 从T6表获取前12个球号和系数（如果第12个系数相同则一并加入）
     */
    private List<BallWithCoefficient> getTop12FromT6(Integer masterBallNumber) {
        List<T6> t6List = t6Mapper.selectList(
            new QueryWrapper<T6>()
                .eq("masterBallNumber", masterBallNumber)
                .orderByDesc("lineCoefficient"));
        
        if (CollectionUtils.isEmpty(t6List)) {
            log.warn("T6表中主球{}没有数据", masterBallNumber);
            return new ArrayList<>();
        }
        
        List<BallWithCoefficient> result = new ArrayList<>();
        
        if (t6List.size() <= 12) {
            // 如果总数不超过12个，全部加入
            for (T6 t6 : t6List) {
                result.add(new BallWithCoefficient(t6.getSlaveBallNumber(), t6.getLineCoefficient(), masterBallNumber));
            }
            return result;
        }
        
        // 先加入前12个
        for (int i = 0; i < 12; i++) {
            T6 t6 = t6List.get(i);
            result.add(new BallWithCoefficient(t6.getSlaveBallNumber(), t6.getLineCoefficient(), masterBallNumber));
        }
        
        // 获取第12个球号的系数
        Double boundaryCoefficient = t6List.get(11).getLineCoefficient();
        
        // 继续查找后面系数相同的球号
        for (int i = 12; i < t6List.size(); i++) {
            T6 t6 = t6List.get(i);
            if (t6.getLineCoefficient().equals(boundaryCoefficient)) {
                result.add(new BallWithCoefficient(t6.getSlaveBallNumber(), t6.getLineCoefficient(), masterBallNumber));
            } else {
                break; // 系数不同，停止查找
            }
        }
        
        return result;
    }
    
    /**
     * 从T5表获取前12个球号和系数（如果第12个系数相同则一并加入）
     */
    private List<BallWithCoefficient> getTop12FromT5(Integer masterBallNumber) {
        List<T5> t5List = t5Mapper.selectList(
            new QueryWrapper<T5>()
                .eq("masterBallNumber", masterBallNumber)
                .orderByDesc("lineCoefficient"));
        
        if (CollectionUtils.isEmpty(t5List)) {
            log.warn("T5表中主球{}没有数据", masterBallNumber);
            return new ArrayList<>();
        }
        
        List<BallWithCoefficient> result = new ArrayList<>();
        
        if (t5List.size() <= 12) {
            // 如果总数不超过12个，全部加入
            for (T5 t5 : t5List) {
                result.add(new BallWithCoefficient(t5.getSlaveBallNumber(), t5.getLineCoefficient(), masterBallNumber));
            }
            return result;
        }
        
        // 先加入前12个
        for (int i = 0; i < 12; i++) {
            T5 t5 = t5List.get(i);
            result.add(new BallWithCoefficient(t5.getSlaveBallNumber(), t5.getLineCoefficient(), masterBallNumber));
        }
        
        // 获取第12个球号的系数
        Double boundaryCoefficient = t5List.get(11).getLineCoefficient();
        
        // 继续查找后面系数相同的球号
        for (int i = 12; i < t5List.size(); i++) {
            T5 t5 = t5List.get(i);
            if (t5.getLineCoefficient().equals(boundaryCoefficient)) {
                result.add(new BallWithCoefficient(t5.getSlaveBallNumber(), t5.getLineCoefficient(), masterBallNumber));
            } else {
                break; // 系数不同，停止查找
            }
        }
        
        return result;
    }
    
    /**
     * 从blue_history_top_100获取前2个球号（按点系数排行，处理边界相同系数）
     */
    private List<Integer> getTop2FromHistoryTop100() {
        List<BlueHistoryTop100> blueHistoryTop100List = blueHistoryTop100Mapper.selectList(
            new QueryWrapper<BlueHistoryTop100>()
                .orderByDesc("pointCoefficient"));
        
        if (CollectionUtils.isEmpty(blueHistoryTop100List)) {
            log.warn("蓝球百期排行表数据为空");
            return new ArrayList<>();
        }
        
        List<Integer> result = new ArrayList<>();
        int index = 0;
        int addedCount = 0;
        
        while (addedCount < 2 && index < blueHistoryTop100List.size()) {
            double currentCoefficient = blueHistoryTop100List.get(index).getPointCoefficient();
            List<Integer> sameCoefficientBalls = new ArrayList<>();
            
            // 收集所有相同系数的球号
            while (index < blueHistoryTop100List.size() && 
                   blueHistoryTop100List.get(index).getPointCoefficient().equals(currentCoefficient)) {
                sameCoefficientBalls.add(blueHistoryTop100List.get(index).getBallNumber());
                index++;
            }
            
            // 计算还需要多少个球
            int needCount = Math.min(2 - addedCount, sameCoefficientBalls.size());
            
            if (sameCoefficientBalls.size() == 1) {
                // 只有一个球号，直接加入
                result.add(sameCoefficientBalls.get(0));
                addedCount++;
            } else if (needCount == sameCoefficientBalls.size()) {
                // 需要选择的数量等于可用数量，全部加入
                result.addAll(sameCoefficientBalls);
                addedCount += sameCoefficientBalls.size();
            } else {
                // 需要从多个相同系数的球号中选择部分，处理边界冲突
                List<Integer> selectedBalls = handleBlueHistoryBoundaryConflicts(sameCoefficientBalls, needCount);
                result.addAll(selectedBalls);
                addedCount += selectedBalls.size();
            }
        }
        
        return result;
    }
    
    /**
     * 根据级别从T8表获取候选球号和系数
     */
    private List<BallWithCoefficient> getT8BallsByLevel(Integer masterBallNumber, String level) {
        List<T8> t8List = t8Mapper.selectList(
            new QueryWrapper<T8>()
                .eq("masterBallNumber", masterBallNumber)
                .orderByDesc("faceCoefficient"));
        
        if (CollectionUtils.isEmpty(t8List)) {
            log.warn("T8表中主球{}没有数据", masterBallNumber);
            return new ArrayList<>();
        }
        
        if ("H".equalsIgnoreCase(level)) {
            return getHighLevelBallsFromT8(t8List, masterBallNumber);
        } else if ("M".equalsIgnoreCase(level)) {
            return getMiddleLevelBallsFromT8(t8List, masterBallNumber);
        } else { // L
            return getLowLevelBallsFromT8(t8List, masterBallNumber);
        }
    }
    
    /**
     * 高位策略：从T8表获取系数最大的前5个球号（如果第5个系数相同则一并加入）
     */
    private List<BallWithCoefficient> getHighLevelBallsFromT8(List<T8> t8List, Integer masterBallNumber) {
        List<BallWithCoefficient> result = new ArrayList<>();
        
        if (t8List.size() <= 5) {
            // 如果总数不超过5个，全部加入
            for (T8 t8 : t8List) {
                result.add(new BallWithCoefficient(t8.getSlaveBallNumber(), t8.getFaceCoefficient(), masterBallNumber));
            }
            return result;
        }
        
        // 先加入前5个
        for (int i = 0; i < 5; i++) {
            T8 t8 = t8List.get(i);
            result.add(new BallWithCoefficient(t8.getSlaveBallNumber(), t8.getFaceCoefficient(), masterBallNumber));
        }
        
        // 获取第5个球号的系数
        Double boundaryCoefficient = t8List.get(4).getFaceCoefficient();
        
        // 继续查找后面系数相同的球号
        for (int i = 5; i < t8List.size(); i++) {
            T8 t8 = t8List.get(i);
            if (t8.getFaceCoefficient().equals(boundaryCoefficient)) {
                result.add(new BallWithCoefficient(t8.getSlaveBallNumber(), t8.getFaceCoefficient(), masterBallNumber));
            } else {
                break; // 系数不同，停止查找
            }
        }
        
        return result;
    }
    
    /**
     * 中位策略：从T8表获取平均值附近5个球号（向上2个，向下2个，边界系数相同则一并加入）
     */
    private List<BallWithCoefficient> getMiddleLevelBallsFromT8(List<T8> t8List, Integer masterBallNumber) {
        if (t8List.size() < 5) {
            log.warn("T8表数据不足5条，实际{}条", t8List.size());
            List<BallWithCoefficient> result = new ArrayList<>();
            for (T8 t8 : t8List) {
                result.add(new BallWithCoefficient(t8.getSlaveBallNumber(), t8.getFaceCoefficient(), masterBallNumber));
            }
            return result;
        }
        
        // 计算平均系数（保留两位小数，截断方式）
        double avgCoefficient = t8List.stream()
                .mapToDouble(T8::getFaceCoefficient)
                .average()
                .orElse(0.0);
        // 截断到两位小数
        avgCoefficient = Math.floor(avgCoefficient * 100) / 100;
        
        // 找到第一个比平均值大的位置（从下到上遍历）
        int avgPosition = -1;
        for (int i = t8List.size() - 1; i >= 0; i--) {
            if (t8List.get(i).getFaceCoefficient() >= avgCoefficient) {
                avgPosition = i;
                break;
            }
        }
        
        if (avgPosition == -1) {
            avgPosition = 0; // 如果没找到，取第一个
        }
        
        List<BallWithCoefficient> result = new ArrayList<>();
        
        // 先加入平均值位置的球号
        result.add(new BallWithCoefficient(t8List.get(avgPosition).getSlaveBallNumber(), 
                t8List.get(avgPosition).getFaceCoefficient(), masterBallNumber));
        
        // 向上取2个球号，处理边界系数相同情况  
        int upCount = 0;
        Double upBoundaryCoeff = null;
        for (int i = avgPosition - 1; i >= 0 && upCount < 2; i--) {
            result.add(new BallWithCoefficient(t8List.get(i).getSlaveBallNumber(), 
                    t8List.get(i).getFaceCoefficient(), masterBallNumber));
            upCount++;
            if (upCount == 2) {
                upBoundaryCoeff = t8List.get(i).getFaceCoefficient();
            }
        }
        
        // 向上边界处理：继续添加与第2个球号系数相同的球号
        if (upBoundaryCoeff != null) {
            for (int i = avgPosition - 3; i >= 0; i--) {
                if (t8List.get(i).getFaceCoefficient().equals(upBoundaryCoeff)) {
                    result.add(new BallWithCoefficient(t8List.get(i).getSlaveBallNumber(), 
                            t8List.get(i).getFaceCoefficient(), masterBallNumber));
                } else {
                    break;
                }
            }
        }
        
        // 向下取2个球号，处理边界系数相同情况
        int downCount = 0;
        Double downBoundaryCoeff = null;
        for (int i = avgPosition + 1; i < t8List.size() && downCount < 2; i++) {
            result.add(new BallWithCoefficient(t8List.get(i).getSlaveBallNumber(), 
                    t8List.get(i).getFaceCoefficient(), masterBallNumber));
            downCount++;
            if (downCount == 2) {
                downBoundaryCoeff = t8List.get(i).getFaceCoefficient();
            }
        }
        
        // 向下边界处理：继续添加与第2个球号系数相同的球号
        if (downBoundaryCoeff != null) {
            for (int i = avgPosition + 3; i < t8List.size(); i++) {
                if (t8List.get(i).getFaceCoefficient().equals(downBoundaryCoeff)) {
                    result.add(new BallWithCoefficient(t8List.get(i).getSlaveBallNumber(), 
                            t8List.get(i).getFaceCoefficient(), masterBallNumber));
                } else {
                    break;
                }
            }
        }
        
        return result;
    }
    
    /**
     * 低位策略：从T8表获取最小值向上第2-6个球（共5个球，边界系数相同则一并加入）
     */
    private List<BallWithCoefficient> getLowLevelBallsFromT8(List<T8> t8List, Integer masterBallNumber) {
        if (t8List.size() < 6) {
            log.warn("T8表数据不足6条，实际{}条", t8List.size());
            List<BallWithCoefficient> result = new ArrayList<>();
            for (T8 t8 : t8List) {
                result.add(new BallWithCoefficient(t8.getSlaveBallNumber(), t8.getFaceCoefficient(), masterBallNumber));
            }
            return result;
        }
        
        // 取最小值向上第2-6个球（t8List已按系数降序排列，最后的是最小的）
        // 最小值在最后，向上第2个就是值数组的第 size-2 个，向上第6个就是值数组的第 size-6 个
        List<BallWithCoefficient> result = new ArrayList<>();
        int startIndex = Math.max(0, t8List.size() - 6); // 第2位
        int endIndex = t8List.size() - 2; // 第6位
        
        // 先加入基本的5个球号
        for (int i = startIndex; i <= endIndex; i++) {
            T8 t8 = t8List.get(i);
            result.add(new BallWithCoefficient(t8.getSlaveBallNumber(), t8.getFaceCoefficient(), masterBallNumber));
        }
        
        // 处理起始边界：第1个球号（startIndex）系数相同情况
        if (startIndex > 0) {
            Double startBoundaryCoeff = t8List.get(startIndex).getFaceCoefficient();
            
            // 继续向前查找系数相同的球号
            for (int i = startIndex - 1; i >= 0; i--) {
                if (t8List.get(i).getFaceCoefficient().equals(startBoundaryCoeff)) {
                    result.add(new BallWithCoefficient(t8List.get(i).getSlaveBallNumber(), 
                            t8List.get(i).getFaceCoefficient(), masterBallNumber));
                } else {
                    break; // 系数不同，停止查找
                }
            }
        }
        
        // 处理结束边界：第5个球号（endIndex）系数相同情况
        if (endIndex < t8List.size() - 1) {
            Double endBoundaryCoeff = t8List.get(endIndex).getFaceCoefficient();
            
            // 继续向后查找系数相同的球号
            for (int i = endIndex + 1; i < t8List.size(); i++) {
                if (t8List.get(i).getFaceCoefficient().equals(endBoundaryCoeff)) {
                    result.add(new BallWithCoefficient(t8List.get(i).getSlaveBallNumber(), 
                            t8List.get(i).getFaceCoefficient(), masterBallNumber));
                } else {
                    break; // 系数不同，停止查找
                }
            }
        }
        
        return result;
    }
    
    /**
     * 处理蓝球历史排行边界冲突，选择指定数量的球号
     * @param candidateBalls 候选球号列表
     * @param selectCount 需要选择的数量
     * @return 选中的球号列表
     */
    private List<Integer> handleBlueHistoryBoundaryConflicts(List<Integer> candidateBalls, int selectCount) {
        if (CollectionUtils.isEmpty(candidateBalls) || selectCount <= 0) {
            return new ArrayList<>();
        }
        
        if (selectCount >= candidateBalls.size()) {
            return new ArrayList<>(candidateBalls);
        }
        
        // 使用blue_history_top表进行筛选
        return selectFromBlueHistoryTop(candidateBalls, selectCount);
    }
    
    /**
     * 从blue_history_top表中选择指定数量的球号
     */
    private List<Integer> selectFromBlueHistoryTop(List<Integer> candidateBalls, int selectCount) {
        if (CollectionUtils.isEmpty(candidateBalls) || selectCount <= 0) {
            return new ArrayList<>();
        }
        
        if (selectCount >= candidateBalls.size()) {
            return new ArrayList<>(candidateBalls);
        }
        
        // 获取在blue_history_top表中的系数
        Map<Integer, Double> topCoefficients = new HashMap<>();
        for (Integer ball : candidateBalls) {
            BlueHistoryTop record = blueHistoryTopMapper.selectOne(
                new QueryWrapper<BlueHistoryTop>()
                    .eq("ballNumber", ball));
            if (record != null) {
                topCoefficients.put(ball, record.getPointCoefficient());
            } else {
                topCoefficients.put(ball, 0.0);
            }
        }
        
        // 按系数降序排序，选择前selectCount个
        List<Map.Entry<Integer, Double>> sortedByTop = topCoefficients.entrySet().stream()
                .sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
                .collect(Collectors.toList());
        
        List<Integer> result = new ArrayList<>();
        for (int i = 0; i < Math.min(selectCount, sortedByTop.size()); i++) {
            result.add(sortedByTop.get(i).getKey());
        }
        
        // 如果仍然不够，按原始顺序补充
        while (result.size() < selectCount && result.size() < candidateBalls.size()) {
            for (Integer ball : candidateBalls) {
                if (!result.contains(ball) && result.size() < selectCount) {
                    result.add(ball);
                }
            }
        }
        
        return result;
    }
    
    /**
     * 统计分析并生成结果
     */
    private List<SSQThirdStepResultVO.BallAnalysisResult> analyzeResults(
            List<Integer> allCandidateBalls, 
            Map<Integer, List<BallWithCoefficient>> ballCoefficientMap) {
        
        // 统计球号出现次数
        Map<Integer, Integer> ballFrequencyMap = new HashMap<>();
        for (Integer ball : allCandidateBalls) {
            ballFrequencyMap.put(ball, ballFrequencyMap.getOrDefault(ball, 0) + 1);
        }
        
        // 计算系数和
        Map<Integer, Double> ballCoefficientSumMap = new HashMap<>();
        for (Map.Entry<Integer, List<BallWithCoefficient>> entry : ballCoefficientMap.entrySet()) {
            Integer ballNumber = entry.getKey();
            List<BallWithCoefficient> coefficients = entry.getValue();
            double sum = coefficients.stream()
                    .mapToDouble(BallWithCoefficient::getCoefficient)
                    .sum();
            ballCoefficientSumMap.put(ballNumber, sum);
        }
        
        // 获取所有有排行数据的球号（包括频次为0的球号）
        Set<Integer> allBallsWithRanking = getAllBallsWithRanking();
        
        // 获取百期排位和历史排位
        Map<Integer, Integer> top100RankingMap = getTop100Rankings(allBallsWithRanking);
        Map<Integer, Integer> historyRankingMap = getHistoryRankings(allBallsWithRanking);
        
        // 组装结果
        List<SSQThirdStepResultVO.BallAnalysisResult> results = new ArrayList<>();
        for (Integer ballNumber : allBallsWithRanking) {
            SSQThirdStepResultVO.BallAnalysisResult result = SSQThirdStepResultVO.BallAnalysisResult.builder()
                    .ballNumber(ballNumber)
                    .frequency(ballFrequencyMap.getOrDefault(ballNumber, 0))
                    .coefficientSum(ballCoefficientSumMap.getOrDefault(ballNumber, 0.0))
                    .top100Ranking(top100RankingMap.get(ballNumber))
                    .historyRanking(historyRankingMap.get(ballNumber))
                    .build();
            results.add(result);
        }
        
        // 按出现次数降序排列，次数相同的按球号升序排列
        results.sort((a, b) -> {
            int frequencyCompare = b.getFrequency().compareTo(a.getFrequency());
            if (frequencyCompare != 0) {
                return frequencyCompare;
            }
            return a.getBallNumber().compareTo(b.getBallNumber());
        });
        
        return results;
    }
    
    /**
     * 获取所有有排行数据的球号（包括频次为0的球号）
     */
    private Set<Integer> getAllBallsWithRanking() {
        Set<Integer> allBalls = new HashSet<>();
        
        // 从蓝球百期排行表获取所有球号
        List<BlueHistoryTop100> blueHistoryTop100List = blueHistoryTop100Mapper.selectList(
            new QueryWrapper<BlueHistoryTop100>());
        for (BlueHistoryTop100 item : blueHistoryTop100List) {
            allBalls.add(item.getBallNumber());
        }
        
        // 从蓝球历史排行表获取所有球号
        List<BlueHistoryTop> blueHistoryTopList = blueHistoryTopMapper.selectList(
            new QueryWrapper<BlueHistoryTop>());
        for (BlueHistoryTop item : blueHistoryTopList) {
            allBalls.add(item.getBallNumber());
        }
        
        return allBalls;
    }
    
    /**
     * 获取球号在蓝球百期排行表中的排位
     */
    private Map<Integer, Integer> getTop100Rankings(Set<Integer> ballNumbers) {
        Map<Integer, Integer> result = new HashMap<>();
        
        // 直接查询指定球号的排行数据，使用表中的no字段作为排名
        List<BlueHistoryTop100> blueHistoryTop100List = blueHistoryTop100Mapper.selectList(
            new QueryWrapper<BlueHistoryTop100>()
                .in("ballNumber", ballNumbers));
        
        // 使用表中的no字段作为排名
        for (BlueHistoryTop100 item : blueHistoryTop100List) {
            result.put(item.getBallNumber(), item.getNo());
        }
        
        // 对于没有在蓝球百期排行表中的球号，设置为null
        for (Integer ballNumber : ballNumbers) {
            if (!result.containsKey(ballNumber)) {
                result.put(ballNumber, null);
            }
        }
        
        return result;
    }
    
    /**
     * 获取球号在蓝球历史排行表中的排位
     */
    private Map<Integer, Integer> getHistoryRankings(Set<Integer> ballNumbers) {
        Map<Integer, Integer> result = new HashMap<>();
        
        // 直接查询指定球号的排行数据，使用表中的no字段作为排名
        List<BlueHistoryTop> blueHistoryTopList = blueHistoryTopMapper.selectList(
            new QueryWrapper<BlueHistoryTop>()
                .in("ballNumber", ballNumbers));
        
        // 使用表中的no字段作为排名
        for (BlueHistoryTop item : blueHistoryTopList) {
            result.put(item.getBallNumber(), item.getNo());
        }
        
        // 对于没有在蓝球历史排行表中的球号，设置为null
        for (Integer ballNumber : ballNumbers) {
            if (!result.containsKey(ballNumber)) {
                result.put(ballNumber, null);
            }
        }
        
        return result;
    }
    
    /**
     * 参数验证
     */
    private void validateInputParams(String level, List<Integer> redBalls, Integer blueBall, List<Integer> nextRedBalls) {
        if (!"H".equalsIgnoreCase(level) && !"M".equalsIgnoreCase(level) && !"L".equalsIgnoreCase(level)) {
            throw new IllegalArgumentException("位置级别必须是H/M/L之一");
        }
        
        if (CollectionUtils.isEmpty(redBalls) || redBalls.size() != 6) {
            throw new IllegalArgumentException("红球号码必须为6个");
        }
        
        if (blueBall == null || blueBall < 1 || blueBall > 16) {
            throw new IllegalArgumentException("蓝球号码范围应为1-16");
        }
        
        if (CollectionUtils.isEmpty(nextRedBalls) || nextRedBalls.size() != 6) {
            throw new IllegalArgumentException("下期红球号码必须为6个");
        }
        
        for (Integer redBall : redBalls) {
            if (redBall < 1 || redBall > 33) {
                throw new IllegalArgumentException("红球号码范围应为1-33");
            }
        }
        
        for (Integer nextRedBall : nextRedBalls) {
            if (nextRedBall < 1 || nextRedBall > 33) {
                throw new IllegalArgumentException("下期红球号码范围应为1-33");
            }
        }
    }
}
