package beilv.competition.task;

import beilv.admissionticket.domain.AdmissionTicket;
import beilv.admissionticket.mapper.AdmissionTicketMapper;
import beilv.carinformation.mapper.CarInformationMapper;
import beilv.common.utils.DateUtils;
import beilv.competition.domain.Competition;
import beilv.competition.domain.RedisTask;
import beilv.competition.mapper.CompetitionMapper;
import beilv.stadium.domain.Stadium;
import beilv.vipCard.domain.VipCard;
import beilv.vipCard.mapper.VipCardMapper;
import beilv.vipCardAmountLog.domain.VipCardAmountLog;
import beilv.vipCardAmountLog.mapper.VipCardAmountLogMapper;
import beilv.vipCardLog.domain.VipCardLog;
import beilv.vipCardLog.mapper.VipCardLogMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

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

import static beilv.competition.domain.Constant.*;

@Component
public class RedisTaskChecker {

    // 日志记录器
    private static final Logger logger = LoggerFactory.getLogger(RedisTaskChecker.class);

    // 注入 Redis 模板
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // 注入比赛 Mapper
    @Resource
    private CompetitionMapper competitionMapper;

    // 注入会员卡日志 Mapper
    @Resource
    private VipCardLogMapper vipCardLogMapper;

    @Resource
    private VipCardMapper vipCardMapper;

    // 注入门票 Mapper
    @Resource
    private AdmissionTicketMapper ticketMapper;

    // 注入 ObjectMapper 用于 JSON 转换
    @Autowired
    private ObjectMapper objectMapper;

    @Resource
    private VipCardAmountLogMapper amountLogMapper;


    @Resource
    private CarInformationMapper carInformationMapper;

    /**
     * 定时任务，每秒检查一次，处理报名结束的任务
     */
    @Scheduled(fixedRate = 1000)
    public void checkTasks() {
        processTasks(TASK_QUEUE_QUERY_APPLY, this::handleTaskApply);
    }

    /**
     * 定时任务，每秒检查一次，处理比赛开始的任务
     */
    @Scheduled(fixedRate = 1000)
    public void checkTasksStart() {
        processTasks(TASK_QUEUE_QUERY_START, this::handleTaskStart);
    }

    /**
     * 定时任务，每秒检查一次，处理比赛结束的任务
     */
    @Scheduled(fixedRate = 1000)
    public void checkTasksEnd() {
        processTasks(TASK_QUEUE_QUERY_END, this::handleTaskEnd);
    }

    /**
     * 定时任务，每秒检查一次，处理门票相关任务
     */
    @Scheduled(fixedRate = 1000)
    public void checkTicket() {
        processTasks(TICKET_QUEUE_ALL, this::handleTicketTask);
    }

    /**
     * 定时任务，每秒检查一次，处理订单相关任务
     */
    @Scheduled(fixedRate = 1000)
    public void checkOrder() {
        processTasks(ORDER_QUEUE_ALL, this::handleOrderTask);
    }

    /**
     * 通用的任务处理方法
     * @param keyPattern Redis 键的模式
     * @param taskHandler 具体的任务处理逻辑
     */
    private void processTasks(String keyPattern, TaskHandler taskHandler) {
        long currentTime = System.currentTimeMillis() / 1000; // 当前时间戳（秒）

        // 获取所有匹配的 Redis 键
        Set<String> keys = stringRedisTemplate.keys(keyPattern);
        if (keys != null && !keys.isEmpty()) {
            for (String key : keys) {
                // 获取当前时间之前的所有任务
                Set<String> tasks = stringRedisTemplate.opsForZSet().rangeByScore(key, 0, currentTime);
                if (tasks != null && !tasks.isEmpty()) {
                    for (String taskJson : tasks) {
                        try {
                            // 将 JSON 字符串转换为 RedisTask 对象
                            RedisTask task = objectMapper.readValue(taskJson, RedisTask.class);
                            // 调用具体的任务处理逻辑
                            taskHandler.handle(task);
                            // 从 Redis 中移除已处理的任务
                            stringRedisTemplate.opsForZSet().remove(key, taskJson);
                            logger.info("Removed task: {}", taskJson);
                        } catch (Exception e) {
                            // 记录异常信息
                            logger.error("Error processing task: {}", taskJson, e);
                        }
                    }
                }
            }
        }
    }

    /**
     * 处理报名结束的任务
     * @param task RedisTask 对象
     */
    private void handleTaskApply(RedisTask task) {
        // 更新比赛状态
        updateCompetitionState(task.getCompetitionId(), task.getCompetitionState());
        // 更新会员卡日志
        updateVipCardLog(task.getCompetitionId(), "cansai", task.getPaymentStatus());
    }

    /**
     * 处理比赛开始的任务
     * @param task RedisTask 对象
     */
    private void handleTaskStart(RedisTask task) {
        // 更新比赛状态
        updateCompetitionState(task.getCompetitionId(), task.getCompetitionState());
        // 更新会员卡日志
        updateVipCardLog(task.getCompetitionId(), "menpiao", task.getPaymentStatus());
    }

    /**
     * 处理比赛结束的任务
     * @param task RedisTask 对象
     */
    private void handleTaskEnd(RedisTask task) {
        // 更新比赛状态
        updateCompetitionState(task.getCompetitionId(), task.getCompetitionState());
    }

    /**
     * 处理门票相关任务
     * @param task RedisTask 对象
     */
    private void handleTicketTask(RedisTask task) {
        // 更新会员卡日志
        updateVipCardLog(task.getCompetitionId(), "yueqiu", task.getPaymentStatus());
        // 更新门票状态
        updateAdmissionTicketStatus(task.getCompetitionId(), task.getCompetitionState());
    }

    /**
     * 处理订单相关任务
     * @param task RedisTask 对象
     */
    private void handleOrderTask(RedisTask task) {
        // 更新会员卡日志
        updateVipCardLog(task.getCompetitionId(), task.getPaymentStatus());
        // 如果是约球订单，重置球场信息
        if ("yueqiu".equals(task.getOrderType())) {
            resetAdmissionTicketStatus(task.getBusId());
        }
    }

    /**
     * 更新比赛状态
     * @param competitionId 比赛 ID
     * @param competitionState 比赛状态
     */
    private void updateCompetitionState(String competitionId, String competitionState) {
        Competition competition = new Competition();
        competition.setId(competitionId);
        competition.setCompetitionState(competitionState);
        competitionMapper.updateCompetition(competition);
    }

    /**
     * 更新会员卡日志
     * @param competitionId 比赛 ID
     * @param orderType 订单类型
     * @param paymentStatus 支付状态
     */
    private void updateVipCardLog(String competitionId, String orderType, String paymentStatus) {
        VipCardLog vipCardLog = new VipCardLog(String.valueOf(competitionId), orderType, paymentStatus, DateUtils.getNowDate());

        //报名结束, 参赛门票核验状态, 有会员卡的加积分  1111
        //根据订单类型和业务id获取订单集合
        List<VipCardLog> orderList = vipCardLogMapper.selectVipCardLogByBusId(competitionId, orderType);

        //遍历订单集合
        orderList.forEach(orderInfo->{
            //根据下单人员查询会员卡
            VipCard vipCard = vipCardMapper.selectVipCardByUserId(orderInfo.getUserId());
            if(null != vipCard){

                BigDecimal addScore;//增加的积分
                if("numCard".equals(orderInfo.getPaymentType())){
                    //如果使用的次卡, 则查询次卡对应的单次积分
                    addScore =  carInformationMapper.selectScoreByCard(orderInfo.getPaymentId()).setScale(0, RoundingMode.FLOOR);
                }else{
                    //如果使用的微信支付, 或者会员卡支付, 则增加的积分为支付的钱数
                    addScore = orderInfo.getOriginalPrice().setScale(0, RoundingMode.FLOOR);
                }

                //存在会员卡, 增加积分流水
                VipCardAmountLog vipCardAmountLog = new VipCardAmountLog(orderInfo.getUserId(), vipCard.getId(), orderInfo.getId(), vipCard.getScore(), addScore, "2");
                amountLogMapper.insertVipCardAmountLog(vipCardAmountLog);

                //存在会员卡, 增加积分
                vipCard.setScore(vipCardAmountLog.getRemainingAmount());
                vipCardMapper.updateVipCard(vipCard);

            }
        });
        vipCardLogMapper.updateVipCardLogByBusId(vipCardLog);
    }

    /**
     * 更新会员卡日志（仅支付状态）
     * @param competitionId 比赛 ID
     * @param paymentStatus 支付状态
     */
    private void updateVipCardLog(String competitionId, String paymentStatus) {
        VipCardLog vipCardLog = new VipCardLog();
        vipCardLog.setId(competitionId);
        vipCardLog.setPaymentStatus(paymentStatus);
        vipCardLog.setCancellationTime(DateUtils.getNowDate());
        vipCardLogMapper.updateVipCardLog(vipCardLog);
    }

    /**
     * 更新门票状态
     * @param ticketId 门票 ID
     * @param status 状态
     */
    private void updateAdmissionTicketStatus(String ticketId, String status) {
        AdmissionTicket admissionTicket = new AdmissionTicket();
        admissionTicket.setId(ticketId);
        admissionTicket.setAdmissionTicketStatus(status);
        ticketMapper.updateBeilvAdmissionTicket(admissionTicket);
    }

    /**
     * 重置门票状态
     * @param ticketId 门票 ID
     */
    private void resetAdmissionTicketStatus(String ticketId) {
        AdmissionTicket admissionTicket = new AdmissionTicket();
        admissionTicket.setId(ticketId);
        admissionTicket.setAdmissionTicketStatus("0");
        ticketMapper.updateBeilvAdmissionTicket(admissionTicket);
    }


    /**
     * 根据业务id, 和订单类型获取, 订单集合
     * @return
     */
    private List<VipCardLog> getOrderList(){
        return null;
    }

    /**
     * 定义任务处理逻辑的函数式接口
     */
    @FunctionalInterface
    interface TaskHandler {
        void handle(RedisTask task);
    }
}
