package com.xy.xyaicpzs.controller;

import com.xy.xyaicpzs.common.ErrorCode;
import com.xy.xyaicpzs.common.ResultUtils;
import com.xy.xyaicpzs.common.response.ApiResponse;
import com.xy.xyaicpzs.domain.entity.LotteryDraws;
import com.xy.xyaicpzs.domain.entity.PredictRecord;
import com.xy.xyaicpzs.service.BallAnalysisService;
import com.xy.xyaicpzs.service.LotteryDrawsService;
import com.xy.xyaicpzs.service.PredictRecordService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 球号分析控制器
 * 提供球号分析算法的API接口
 */
@Slf4j
@RestController
@RequestMapping("/ball-analysis")
@Tag(name = "球号分析", description = "球号分析算法API")
public class BallAnalysisController {

    @Autowired
    private BallAnalysisService ballAnalysisService;

    @Autowired
    private LotteryDrawsService lotteryDrawsService;

    @Autowired
    private PredictRecordService predictRecordService;

        @GetMapping("/predict-records/{userId}")
    @Operation(summary = "获取用户推测记录", description = "根据用户ID获取该用户的所有推测记录，按推测时间倒序排列")
    public ApiResponse<List<PredictRecord>> getPredictRecordsByUserId(
            @Parameter(description = "用户ID，例如：1001", required = true)
            @PathVariable Long userId
            , HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "用户未登录");
        }

        try {
            log.info("接收到获取用户推测记录请求：用户ID={}", userId);
            
            // 调用服务获取用户推测记录
            List<PredictRecord> result = predictRecordService.getPredictRecordsByUserId(userId);
            
            log.info("获取用户推测记录完成，用户ID：{}，返回{}条记录", userId, result.size());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取用户推测记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取用户推测记录失败：" + e.getMessage());
        }
    }


    /**
     * 获取近期开奖信息
     * @param limit 获取条数，可选参数，默认15条
     * @return 近期开奖信息列表
     */
    @GetMapping("/recent-draws")
    @Operation(summary = "获取近期开奖信息", description = "获取最近的开奖信息，默认返回15条，按开奖期号倒序排列")
    public ApiResponse<List<LotteryDraws>> getRecentDraws(
            @Parameter(description = "获取条数，默认15条", required = false)
            @RequestParam(required = false, defaultValue = "15") Integer limit) {
        
        try {
            log.info("接收到获取近期开奖信息请求：条数={}", limit);
            
            // 调用服务获取近期开奖信息
            List<LotteryDraws> result = lotteryDrawsService.getRecentDraws(limit);
            
            log.info("获取近期开奖信息完成，返回{}条记录", result.size());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取近期开奖信息失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取近期开奖信息失败：" + e.getMessage());
        }
    }

    /**
     * 根据日期范围查询开奖信息
     * @param startDate 开始日期（可选，格式：yyyy-MM-dd）
     * @param endDate 结束日期（可选，格式：yyyy-MM-dd）
     * @return 开奖信息列表
     */
    @GetMapping("/query-draws")
    @Operation(summary = "按日期范围查询开奖信息", description = "根据日期范围查询开奖信息，支持单边日期查询")
    public ApiResponse<List<LotteryDraws>> queryDraws(
            @Parameter(description = "开始日期，格式：yyyy-MM-dd，例如：2025-01-01", required = false)
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
            
            @Parameter(description = "结束日期，格式：yyyy-MM-dd，例如：2025-01-31", required = false)
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate) {
        
        try {
            log.info("接收到按日期范围查询开奖信息请求：开始日期={}，结束日期={}", startDate, endDate);
            
            // 日期范围验证
            if (startDate != null && endDate != null && startDate.after(endDate)) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "开始日期不能晚于结束日期");
            }
            
            // 调用服务按日期范围查询开奖信息
            List<LotteryDraws> result = lotteryDrawsService.getByDateRange(startDate, endDate);
            
            log.info("按日期范围查询开奖信息完成，返回{}条记录", result.size());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("按日期范围查询开奖信息失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "查询开奖信息失败：" + e.getMessage());
        }
    }

    /**
     * 根据期号精准查询单条开奖信息
     * @param drawId 开奖期号
     * @return 开奖信息
     */
    @GetMapping("/draw/{drawId}")
    @Operation(summary = "根据期号查询开奖信息", description = "根据期号精准查询单条开奖信息")
    public ApiResponse<LotteryDraws> getDrawById(
            @Parameter(description = "开奖期号，例如：2025056", required = true)
            @PathVariable Long drawId) {
        
        try {
            log.info("接收到根据期号查询开奖信息请求：期号={}", drawId);
            
            // 调用服务查询开奖信息
            LotteryDraws result = lotteryDrawsService.getByDrawId(drawId);
            
            if (result == null) {
                log.warn("未找到期号为{}的开奖信息", drawId);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, "未找到期号为" + drawId + "的开奖信息");
            }
            
            log.info("根据期号查询开奖信息完成：{}", result.getDrawId());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("根据期号查询开奖信息失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "查询开奖信息失败：" + e.getMessage());
        }
    }

    /**
     * 创建推测记录
     * @param userId 用户ID
     * @param drawId 开奖期号
     * @param drawDate 开奖日期
     * @param redBalls 6个红球号码，用逗号分隔
     * @param blueBall 蓝球号码
     * @return 创建的推测记录
     */
    @PostMapping("/create-predict")
    @Operation(summary = "创建推测记录", description = "向predict_record表插入一条推测记录数据")
    public ApiResponse<PredictRecord> createPredictRecord(
            @Parameter(description = "用户ID，例如：1001", required = true)
            @RequestParam Long userId,
            
            @Parameter(description = "开奖期号，例如：2025056", required = true)
            @RequestParam Long drawId,
            
            @Parameter(description = "开奖日期，格式：yyyy-MM-dd", required = true)
            @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date drawDate,
            
            @Parameter(description = "6个红球号码，用逗号分隔，例如：1,5,12,18,25,33", required = true)
            @RequestParam String redBalls,
            
            @Parameter(description = "蓝球号码，例如：8", required = true)
            @RequestParam Integer blueBall) {
        
        try {
            log.info("接收到创建推测记录请求：用户ID={}，期号={}，开奖日期={}，红球={}，蓝球={}", 
                    userId, drawId, drawDate, redBalls, blueBall);
            
            // 解析红球号码
            List<Integer> redBallList = parseRedBalls(redBalls, 6, "红球");
            
            // 调用服务创建推测记录
            PredictRecord result = predictRecordService.createPredictRecord(userId, drawId, drawDate, redBallList, blueBall);
            
            log.info("创建推测记录完成，用户ID：{}，记录ID：{}", userId, result.getId());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("创建推测记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "创建推测记录失败：" + e.getMessage());
        }
    }

    /**
     * 球号分析算法
     * @param level 高位/中位/低位标识 (H/M/L)
     * @param redBalls 6个红球号码，用逗号分隔
     * @param blueBall 蓝球号码
     * @return 分析结果：出现频率最高的前11位数字
     */
    @PostMapping("/analyze")
    @Operation(summary = "首球算法", description = "根据输入的级别、红球和蓝球，分析出现频率最高的前11位数字")
    public ApiResponse<List<Integer>> analyzeBalls(
            @Parameter(description = "级别：H(高位)/M(中位)/L(低位)", required = true)
            @RequestParam String level,
            
            @Parameter(description = "6个红球号码，用逗号分隔，例如：1,5,12,18,25,33", required = true)
            @RequestParam String redBalls,
            
            @Parameter(description = "蓝球号码，例如：8", required = true)
            @RequestParam Integer blueBall) {
        
        try {
            log.info("接收到球号分析请求：级别={}，红球={}，蓝球={}", level, redBalls, blueBall);
            
            // 解析红球号码
            List<Integer> redBallList = parseRedBalls(redBalls, 6, "红球");
            
            // 调用分析服务
            List<Integer> result = ballAnalysisService.analyzeBalls(level, redBallList, blueBall);
            
            log.info("球号分析完成，结果：{}", result);
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("球号分析失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "球号分析失败：" + e.getMessage());
        }
    }

    /**
     * 跟随球号分析算法
     * @param level 高位/中位/低位标识 (H/M/L)
     * @param firstThreeRedBalls 前3个红球号码，用逗号分隔
     * @param lastSixRedBalls 后6个红球号码，用逗号分隔
     * @param blueBall 蓝球号码
     * @return 分析结果：出现频率最高的前8位数字
     */
    @PostMapping("/fallow")
    @Operation(summary = "跟随球号分析算法", description = "根据输入的级别、前3个红球、后6个红球和蓝球，分析出现频率最高的前8位数字")
    public ApiResponse<List<Integer>> fallowBallAnalysis(
            @Parameter(description = "级别：H(高位)/M(中位)/L(低位)", required = true)
            @RequestParam String level,
            
            @Parameter(description = "前3个红球号码，用逗号分隔，例如：7,24,27", required = true)
            @RequestParam String firstThreeRedBalls,
            
            @Parameter(description = "后6个红球号码，用逗号分隔，例如：21,10,5,15,23,28", required = true)
            @RequestParam String lastSixRedBalls,
            
            @Parameter(description = "蓝球号码，例如：16", required = true)
            @RequestParam Integer blueBall) {
        
        try {
            log.info("接收到跟随球号分析请求：级别={}，前3个红球={}，后6个红球={}，蓝球={}", 
                    level, firstThreeRedBalls, lastSixRedBalls, blueBall);
            
            // 解析红球号码
            List<Integer> firstThreeRedBallList = parseRedBalls(firstThreeRedBalls, 3, "前3个红球");
            List<Integer> lastSixRedBallList = parseRedBalls(lastSixRedBalls, 6, "后6个红球");
            
            // 调用分析服务
            List<Integer> result = ballAnalysisService.fallowBallAnalysis(level, firstThreeRedBallList, lastSixRedBallList, blueBall);
            
            log.info("跟随球号分析完成，结果：{}", result);
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("跟随球号分析失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "跟随球号分析失败：" + e.getMessage());
        }
    }

    /**
     * 解析红球号码字符串
     */
    private List<Integer> parseRedBalls(String redBalls, int expectedCount, String ballType) {
        if (redBalls == null || redBalls.trim().isEmpty()) {
            throw new IllegalArgumentException(ballType + "号码不能为空");
        }
        
        try {
            String[] parts = redBalls.split(",");
            if (parts.length != expectedCount) {
                throw new IllegalArgumentException(ballType + "数量必须为" + expectedCount + "个，实际：" + parts.length);
            }
            
            List<Integer> result = Arrays.stream(parts)
                    .map(String::trim)
                    .map(Integer::parseInt)
                    .collect(java.util.stream.Collectors.toList());
            
            // 验证红球号码范围
            for (Integer ball : result) {
                if (ball < 1 || ball > 33) {
                    throw new IllegalArgumentException(ballType + "号码必须在1-33范围内，错误值：" + ball);
                }
            }
            
            return result;
            
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException(ballType + "号码格式错误，请使用逗号分隔的数字");
        }
    }

    /**
     * 蓝球分析算法
     * @param level 高位/中位/低位标识 (H/M/L)
     * @param predictedRedBalls 6个推测红球号码，用逗号分隔
     * @param predictedBlueBalls 2个推测蓝球号码，用逗号分隔
     * @param lastRedBalls 6个上期红球号码，用逗号分隔
     * @param lastBlueBall 上期蓝球号码
     * @return 分析结果：频率最高的前4个蓝球号码
     */
    @PostMapping("/blue-ball")
    @Operation(summary = "蓝球分析算法", description = "根据输入的级别、推测红球、推测蓝球、上期红球和上期蓝球，分析出频率最高的前4个蓝球号码")
    public ApiResponse<List<Integer>> blueBallAnalysis(
            @Parameter(description = "级别：H(高位)/M(中位)/L(低位)", required = true)
            @RequestParam String level,
            
            @Parameter(description = "6个推测红球号码，用逗号分隔，例如：26,20,18,32,10,14", required = true)
            @RequestParam String predictedRedBalls,
            
            @Parameter(description = "2个推测蓝球号码，用逗号分隔，例如：5,8", required = true)
            @RequestParam String predictedBlueBalls,
            
            @Parameter(description = "6个上期红球号码，用逗号分隔，例如：7,24,27,21,10,5", required = true)
            @RequestParam String lastRedBalls,
            
            @Parameter(description = "上期蓝球号码，例如：16", required = true)
            @RequestParam Integer lastBlueBall) {
        
        try {
            log.info("接收到蓝球分析请求：级别={}，推测红球={}，推测蓝球={}，上期红球={}，上期蓝球={}", 
                    level, predictedRedBalls, predictedBlueBalls, lastRedBalls, lastBlueBall);
            
            // 解析球号
            List<Integer> predictedRedBallList = parseRedBalls(predictedRedBalls, 6, "推测红球");
            List<Integer> predictedBlueBallList = parseBlueBalls(predictedBlueBalls, 2, "推测蓝球");
            List<Integer> lastRedBallList = parseRedBalls(lastRedBalls, 6, "上期红球");
            
            // 调用分析服务
            List<Integer> result = ballAnalysisService.blueBallAnalysis(
                level, predictedRedBallList, predictedBlueBallList, lastRedBallList, lastBlueBall);
            
            log.info("蓝球分析完成，结果：{}", result);
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("蓝球分析失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "蓝球分析失败：" + e.getMessage());
        }
    }

    /**
     * 解析蓝球号码字符串
     */
    private List<Integer> parseBlueBalls(String blueBalls, int expectedCount, String ballType) {
        if (blueBalls == null || blueBalls.trim().isEmpty()) {
            throw new IllegalArgumentException(ballType + "号码不能为空");
        }
        
        try {
            String[] parts = blueBalls.split(",");
            if (parts.length != expectedCount) {
                throw new IllegalArgumentException(ballType + "数量必须为" + expectedCount + "个，实际：" + parts.length);
            }
            
            List<Integer> result = Arrays.stream(parts)
                    .map(String::trim)
                    .map(Integer::parseInt)
                    .collect(java.util.stream.Collectors.toList());
            
            // 验证蓝球号码范围
            for (Integer ball : result) {
                if (ball < 1 || ball > 16) {
                    throw new IllegalArgumentException(ballType + "号码必须在1-16范围内，错误值：" + ball);
                }
            }
            
            return result;
            
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException(ballType + "号码格式错误，请使用逗号分隔的数字");
        }
    }

} 