package com.xy.xyaicpzs.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xy.xyaicpzs.common.ErrorCode;
import com.xy.xyaicpzs.common.ResultUtils;
import com.xy.xyaicpzs.common.requset.DltPredictRecordQueryRequest;
import com.xy.xyaicpzs.common.response.ApiResponse;
import com.xy.xyaicpzs.common.response.PageResponse;
import com.xy.xyaicpzs.domain.entity.DltPredictRecord;
import com.xy.xyaicpzs.domain.entity.User;
import com.xy.xyaicpzs.domain.vo.PrizeEstimateVO;
import com.xy.xyaicpzs.domain.vo.RedBallHitRateVO;
import com.xy.xyaicpzs.domain.vo.UserPredictStatVO;
import com.xy.xyaicpzs.service.DataAnalysisService;
import com.xy.xyaicpzs.service.DltDataAnalysisService;
import com.xy.xyaicpzs.service.DltPredictRecordService;
import com.xy.xyaicpzs.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

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

/**
 * 大乐透预测记录控制器
 * 提供大乐透预测记录查询相关的API接口
 */
@Slf4j
@RestController
@RequestMapping("/dlt-predict")
@Tag(name = "大乐透预测记录", description = "大乐透预测记录查询API")
public class DltPredictController {

    @Autowired
    private DltPredictRecordService dltPredictRecordService;

    @Autowired
    private UserService userService;

    @Autowired
    private DltDataAnalysisService dltDataAnalysisService;

    @Autowired
    private DataAnalysisService dataAnalysisService;

    /**
     * 根据用户ID获取大乐透预测记录
     * @param userId 用户ID
     * @return 用户的所有大乐透预测记录列表
     */
    @GetMapping("/predict-records/{userId}")
    @Operation(summary = "获取用户大乐透预测记录", description = "根据用户ID分页获取该用户的大乐透预测记录，按预测时间倒序排列，每页5条")
    public ApiResponse<PageResponse<DltPredictRecord>> getDltPredictRecordsByUserId(
            @Parameter(description = "用户ID，例如：1001", required = true)
            @PathVariable Long userId,
            @Parameter(description = "页码，从1开始，默认为1", required = false)
            @RequestParam(value = "page", defaultValue = "1") Integer page,
            HttpServletRequest request) {
        
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "用户未登录");
        }
        
        // 检查VIP权限
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }

        try {
            log.info("接收到获取用户大乐透预测记录请求：用户ID={}，页码={}", userId, page);
            
            // 参数校验
            if (page < 1) {
                page = 1;
            }
            
            // 获取总记录数
            Long total = dltPredictRecordService.getDltPredictRecordsCountByUserId(userId);
            
            // 调用服务获取用户预测记录（分页，每页5条）
            List<DltPredictRecord> records = dltPredictRecordService.getDltPredictRecordsByUserIdWithPaging(userId, page, 5);
            
            // 创建分页响应对象
            PageResponse<DltPredictRecord> pageResponse = PageResponse.of(records, total, page, 5);
            
            log.info("获取用户大乐透预测记录完成，用户ID：{}，页码：{}，返回{}条记录，总记录数：{}", userId, page, records.size(), total);
            return ResultUtils.success(pageResponse);
            
        } catch (Exception e) {
            log.error("获取用户大乐透预测记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取用户大乐透预测记录失败：" + e.getMessage());
        }
    }

    /**
     * 按条件查询大乐透预测记录
     * @param request 查询条件
     * @return 分页预测记录
     */
    @PostMapping("/query-predict-records")
    @Operation(summary = "按条件查询大乐透预测记录", description = "根据用户ID和预测状态(待开奖/已开奖)以及预测结果筛选大乐透预测记录，支持分页查询")
    public ApiResponse<PageResponse<DltPredictRecord>> queryDltPredictRecords(@RequestBody DltPredictRecordQueryRequest request,
                                                                             HttpServletRequest httpRequest) {
        
        User loginUser = userService.getLoginUser(httpRequest);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "用户未登录");
        }

        try {
            log.info("接收到按条件查询大乐透预测记录请求：userId={}, predictStatus={}, predictResult={}, current={}, pageSize={}", 
                    request.getUserId(), request.getPredictStatus(), request.getPredictResult(),
                    request.getCurrent(), request.getPageSize());
            
            // 构建查询条件
            QueryWrapper<DltPredictRecord> queryWrapper = new QueryWrapper<>();
            
            // 添加用户ID筛选条件
            if (request.getUserId() != null) {
                queryWrapper.eq("userId", request.getUserId());
            }
            
            // 添加预测状态筛选条件
            if (StringUtils.isNotBlank(request.getPredictStatus())) {
                queryWrapper.eq("predictStatus", request.getPredictStatus());
            }
            
            // 添加预测结果筛选条件
            if (StringUtils.isNotBlank(request.getPredictResult())) {
                queryWrapper.eq("predictResult", request.getPredictResult());
            }
            
            // 按预测时间降序排序
            queryWrapper.orderByDesc("predictTime");
            
            // 执行分页查询
            Page<DltPredictRecord> page = new Page<>(request.getCurrent(), request.getPageSize());
            Page<DltPredictRecord> resultPage = dltPredictRecordService.page(page, queryWrapper);
            
            // 构建分页响应对象
            PageResponse<DltPredictRecord> result = PageResponse.of(
                    resultPage.getRecords(), 
                    resultPage.getTotal(), 
                    (int) resultPage.getCurrent(), 
                    (int) resultPage.getSize()
            );
            
            log.info("按条件查询大乐透预测记录完成，总记录数：{}", result.getTotal());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("按条件查询大乐透预测记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "查询大乐透预测记录失败：" + e.getMessage());
        }
    }

    /**
     * 获取用户大乐透预测统计数据
     * @param userId 用户ID
     * @return 用户大乐透预测统计数据
     */
    @GetMapping("/user-predict-stat/{userId}")
    @Operation(summary = "获取用户大乐透预测统计数据", description = "根据用户ID获取该用户的大乐透预测次数、待开奖次数、命中次数、命中率等统计数据")
    public ApiResponse<UserPredictStatVO> getUserDltPredictStat(
            @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, "用户未登录");
        }
        
        // 检查VIP权限
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        
        try {
            log.info("接收到获取用户大乐透预测统计数据请求：用户ID={}", userId);
            
            // 调用服务获取用户大乐透预测统计数据
            UserPredictStatVO result = dltDataAnalysisService.getUserDltPredictStat(userId);
            
            log.info("获取用户大乐透预测统计数据完成，用户ID：{}，预测次数：{}，待开奖次数：{}，命中次数：{}，命中率：{}", 
                    userId, result.getPredictCount(), result.getPendingCount(), 
                    result.getHitCount(), result.getHitRate());
            
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取用户大乐透预测统计数据失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取用户大乐透预测统计数据失败：" + e.getMessage());
        }
    }

    /**
     * 大乐透奖金统计
     * @return 奖金统计信息（各中奖等级、中奖次数、单奖金额、奖金合计）
     */
    @GetMapping("/prize-statistics")
    @Operation(summary = "大乐透奖金统计", description = "统计用户所有大乐透中奖记录，按等级汇总各等级的中奖次数和奖金")
    public ApiResponse<PrizeEstimateVO> getDltPrizeStatistics(HttpServletRequest request) {
        
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        
        // 检查VIP权限
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        
        try {
            log.info("接收到大乐透奖金统计请求");
            
            // 调用服务进行大乐透奖金统计
            PrizeEstimateVO result = dltDataAnalysisService.getDltPrizeStatistics(loginUser.getId(), null);
            
            log.info("大乐透奖金统计完成，总奖金：{}", result.getTotalPrize());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("大乐透奖金统计失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "大乐透奖金统计失败：" + e.getMessage());
        }
    }

    /**
     * 手动触发处理待开奖记录（双色球+大乐透）
     * @return 处理结果
     */
    @PostMapping("/process-pending")
    @Operation(summary = "手动处理待开奖记录", description = "手动触发处理双色球和大乐透的待开奖预测记录，匹配开奖结果并更新中奖状态")
    public ApiResponse<String> processPendingPredictions(HttpServletRequest request) {
        
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "用户未登录");
        }
        
        // 检查管理员权限
        if (!userService.isAdmin(loginUser)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "无管理员权限");
        }
        
        try {
            log.info("接收到手动处理待开奖记录请求（双色球+大乐透）");
            
            int ssqProcessedCount = 0;
            int dltProcessedCount = 0;
            
            // 处理双色球待开奖记录
            try {
                log.info("开始处理双色球待开奖记录");
                ssqProcessedCount = dataAnalysisService.processPendingPredictions();
                log.info("双色球待开奖记录处理完成，共处理{}条", ssqProcessedCount);
            } catch (Exception e) {
                log.error("处理双色球待开奖记录时发生错误：{}", e.getMessage(), e);
            }
            
            // 处理大乐透待开奖记录
            try {
                log.info("开始处理大乐透待开奖记录");
                dltProcessedCount = dltDataAnalysisService.processPendingDltPredictions();
                log.info("大乐透待开奖记录处理完成，共处理{}条", dltProcessedCount);
            } catch (Exception e) {
                log.error("处理大乐透待开奖记录时发生错误：{}", e.getMessage(), e);
            }
            
            int totalProcessedCount = ssqProcessedCount + dltProcessedCount;
            String message = String.format("待开奖记录处理完成！双色球：%d条，大乐透：%d条，总计：%d条", 
                                          ssqProcessedCount, dltProcessedCount, totalProcessedCount);
            log.info("手动处理待开奖记录完成：{}", message);
            
            return ResultUtils.success(message);
            
        } catch (Exception e) {
            log.error("手动处理待开奖记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "处理待开奖记录失败：" + e.getMessage());
        }
    }

    /**
     * 获取大乐透前区首球命中率统计
     * @return 前区首球命中次数和命中率统计
     */
    @GetMapping("/front-first-ball-hit-rate")
    @Operation(summary = "获取大乐透前区首球命中率统计", description = "统计用户的大乐透前区首球命中次数和命中率")
    public ApiResponse<RedBallHitRateVO> getFrontFirstBallHitRate(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        try {
            log.info("接收到获取大乐透前区首球命中率统计请求");
            
            // 调用服务获取前区首球命中率
            RedBallHitRateVO result = dltDataAnalysisService.getFrontFirstBallHitRate(loginUser.getId());
            
            log.info("获取大乐透前区首球命中率统计完成，命中总数：{}，预测总数：{}，命中率：{}", 
                     result.getTotalHitCount(), result.getTotalPredictedCount(), result.getHitRate());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取大乐透前区首球命中率统计失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取大乐透前区首球命中率统计失败：" + e.getMessage());
        }
    }

    /**
     * 获取大乐透前区球号命中率统计
     * @return 前区球号命中总数和命中率统计
     */
    @GetMapping("/front-ball-hit-rate")
    @Operation(summary = "获取大乐透前区球号命中率统计", description = "统计用户的大乐透前区球号命中总数和命中率")
    public ApiResponse<RedBallHitRateVO> getFrontBallHitRate(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        try {
            log.info("接收到获取大乐透前区球号命中率统计请求");
            
            // 调用服务获取前区球号命中率
            RedBallHitRateVO result = dltDataAnalysisService.getFrontBallHitRate(loginUser.getId());
            
            log.info("获取大乐透前区球号命中率统计完成，命中总数：{}，预测总数：{}，命中率：{}", 
                     result.getTotalHitCount(), result.getTotalPredictedCount(), result.getHitRate());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取大乐透前区球号命中率统计失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取大乐透前区球号命中率统计失败：" + e.getMessage());
        }
    }

    /**
     * 获取大乐透后区首球命中率统计
     * @return 后区首球命中次数和命中率统计
     */
    @GetMapping("/back-first-ball-hit-rate")
    @Operation(summary = "获取大乐透后区首球命中率统计", description = "统计用户的大乐透后区首球命中次数和命中率")
    public ApiResponse<RedBallHitRateVO> getBackFirstBallHitRate(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        try {
            log.info("接收到获取大乐透后区首球命中率统计请求");
            
            // 调用服务获取后区首球命中率
            RedBallHitRateVO result = dltDataAnalysisService.getBackFirstBallHitRate(loginUser.getId());
            
            log.info("获取大乐透后区首球命中率统计完成，命中总数：{}，预测总数：{}，命中率：{}", 
                     result.getTotalHitCount(), result.getTotalPredictedCount(), result.getHitRate());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取大乐透后区首球命中率统计失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取大乐透后区首球命中率统计失败：" + e.getMessage());
        }
    }

    /**
     * 获取大乐透后区球号命中率统计
     * @return 后区球号命中次数和命中率统计
     */
    @GetMapping("/back-ball-hit-rate")
    @Operation(summary = "获取大乐透后区球号命中率统计", description = "统计用户的大乐透后区球号命中次数和命中率")
    public ApiResponse<RedBallHitRateVO> getBackBallHitRate(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        try {
            log.info("接收到获取大乐透后区球号命中率统计请求");
            
            // 调用服务获取后区球号命中率
            RedBallHitRateVO result = dltDataAnalysisService.getBackBallHitRate(loginUser.getId());
            
            log.info("获取大乐透后区球号命中率统计完成，命中总数：{}，预测总数：{}，命中率：{}", 
                     result.getTotalHitCount(), result.getTotalPredictedCount(), result.getHitRate());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取大乐透后区球号命中率统计失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取大乐透后区球号命中率统计失败：" + e.getMessage());
        }
    }

    /**
     * 管理员获取所有大乐透推测记录（支持分页和用户ID筛选）
     * @param userId 用户ID（可选）
     * @param current 当前页码，默认为1
     * @param pageSize 每页大小，默认为10
     * @param request HTTP请求
     * @return 分页的大乐透预测记录
     */
    @GetMapping("/admin/all-records")
    @Operation(summary = "管理员获取所有推测记录", description = "管理员获取所有大乐透推测记录，支持分页和根据用户ID、中奖等级筛选")
    public ApiResponse<PageResponse<DltPredictRecord>> getAllRecordsForAdmin(
            @Parameter(description = "用户ID（可选），用于筛选指定用户的记录") 
            @RequestParam(value = "userId", required = false) Long userId,
            @Parameter(description = "中奖等级（可选），例如：一等奖、二等奖、未中奖")
            @RequestParam(value = "predictResult", required = false) String predictResult,
            @Parameter(description = "当前页码，从1开始，默认为1") 
            @RequestParam(value = "current", defaultValue = "1") Integer current,
            @Parameter(description = "每页大小，默认为10") 
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
            HttpServletRequest request) {
        
        // 验证管理员权限
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "用户未登录");
        }
        
        if (!userService.isAdmin(loginUser)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "无权限访问，仅管理员可用");
        }
        
        try {
            log.info("管理员获取所有大乐透推测记录，userId={}，predictResult={}，current={}，pageSize={}", 
                    userId, predictResult, current, pageSize);
            
            // 调用Service层方法
            PageResponse<DltPredictRecord> result = dltPredictRecordService.getAllRecordsForAdmin(userId, predictResult, current, pageSize);
            
            log.info("管理员获取大乐透推测记录完成，总记录数：{}", result.getTotal());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("管理员获取大乐透推测记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取推测记录失败：" + e.getMessage());
        }
    }

    /**
     * 管理员获取大乐透中奖记录统计（返回每一条中奖记录）
     * @param userId 用户ID（可选）
     * @param prizeGrade 奖项等级（可选）
     * @param current 当前页码
     * @param pageSize 每页大小
     * @param request HTTP请求
     * @return 分页的中奖记录列表
     */
    @GetMapping("/admin/prize-statistics")
    @Operation(summary = "管理员获取中奖记录明细", description = "管理员获取所有用户的大乐透中奖记录明细，支持根据用户ID和奖项等级筛选")
    public ApiResponse<PageResponse<DltPredictRecord>> getAdminDltPrizeStatistics(
            @Parameter(description = "用户ID（可选）") 
            @RequestParam(value = "userId", required = false) Long userId,
            @Parameter(description = "奖项等级（可选），例如：一等奖、二等奖") 
            @RequestParam(value = "prizeGrade", required = false) String prizeGrade,
            @Parameter(description = "当前页码，从1开始，默认为1") 
            @RequestParam(value = "current", defaultValue = "1") Integer current,
            @Parameter(description = "每页大小，默认为10") 
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
            HttpServletRequest request) {
        
        // 验证管理员权限
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "用户未登录");
        }
        
        if (!userService.isAdmin(loginUser)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "无权限访问，仅管理员可用");
        }
        
        try {
            log.info("管理员获取大乐透中奖记录请求：userId={}，prizeGrade={}，current={}，pageSize={}", 
                    userId, prizeGrade, current, pageSize);
            
            // 调用服务获取中奖记录列表
            PageResponse<DltPredictRecord> result = dltPredictRecordService.getWinningRecordsForAdmin(userId, prizeGrade, current, pageSize);
            
            log.info("管理员获取大乐透中奖记录完成，总记录数：{}", result.getTotal());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("管理员获取大乐透中奖记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "管理员获取大乐透中奖记录失败：" + e.getMessage());
        }
    }
}

