
package com.tmerclub.cloud.seckill.task;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.tmerclub.cloud.api.product.feign.StockPointFeignClient;
import com.tmerclub.cloud.common.cache.config.MultiRedisConfig;
import com.tmerclub.cloud.common.cache.constant.LockCacheNames;
import com.tmerclub.cloud.common.cache.constant.SeckillCacheNames;
import com.tmerclub.cloud.common.cache.enums.MultiStockEnum;
import com.tmerclub.cloud.common.cache.manager.MultiRedisStockManager;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.seckill.model.Seckill;
import com.tmerclub.cloud.seckill.service.SeckillService;
import com.tmerclub.cloud.seckill.service.SeckillSkuService;
import com.tmerclub.cloud.seckill.vo.SeckillSkuVO;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;


/**
 * 秒杀订单的定时任务
 *
 * @author tmerclub
 */
@Component
public class SeckillTask {

    private static final Logger log = LoggerFactory.getLogger(SeckillTask.class);

    @Autowired
    private SeckillService seckillService;

    @Autowired
    private SeckillSkuService seckillSkuService;

    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private MultiRedisConfig multiRedisConfig;
    @Autowired
    private StockPointFeignClient stockPointFeignClient;

    /**
     * 秒杀结束，改变商品类型
     */
    @XxlJob("activityFinishAndProdChange")
    public void activityFinishAndProdChange() {
        XxlJobHelper.log("秒杀活动结束，秒杀商品恢复为普通商品。。。");
        // 获取活动结束，需要改变商品类型的列表
        List<Seckill> seckillList = seckillService.listUnEndButNeedEndActivity();
        if (CollectionUtil.isEmpty(seckillList)) {
            return;
        }
        seckillService.changeProdTypeBySeckillIdList(seckillList);
    }


    /**
     * 已经结束的秒杀活动落库
     * 每个小时的中间时刻执行一次，获取上一个结束的活动
     * 比如 9点结束的活动，9点半，或者9点xx分的时候查下数据库，有没有还在处理但没有落库的订单
     * 这个9点xx分，通过定时任务查询
     */
    @XxlJob("coldStockPlacement")
    public void coldStockPlacement() {
        XxlJobHelper.log("秒杀库存落库");
        // 获取需要库存落库的秒杀活动
        List<SeckillSkuVO> seckillSkuList = seckillSkuService.listOverJustNow();

        if (CollectionUtil.isEmpty(seckillSkuList)) {
            return;
        }
        int zoneNum = multiRedisConfig.getRedisCount();

        for (SeckillSkuVO seckillSkuVO : seckillSkuList) {
            RLock rLock = redissonClient.getLock(LockCacheNames.LOCK_SECKILL_ZONE_PERFIX + seckillSkuVO.getSeckillSkuId());
            rLock.lock();
            try {
                String key = MultiStockEnum.SECKILL + SeckillCacheNames.STOCK + seckillSkuVO.getSeckillId() + StrUtil.C_UNDERLINE + seckillSkuVO.getSkuId();
                seckillSkuService.flushStockToDb(seckillSkuVO.getSeckillSkuId(), seckillSkuVO.getSeckillId());
                // 获取要存进缓存的每个redis库存信息并删除
                for (int i = 0; i < zoneNum; i++) {
                    multiRedisConfig.getRedisByIndex(i).delete(key);
                }
            } finally {
                rLock.unlock();
            }
        }
    }


    /**
     * 初始化秒杀区域库存
     */
    @XxlJob("initPointSeckillStock")
    public void initPointSeckillStock() {
        // ===================== 初始化商品库存 =====================
        try{
            seckillSkuService.initPointSeckillStock();
            // 秒杀活动库存
        } catch (Exception e) {
            log.error("初始化秒杀商品库存失败", e);
        }
    }
}
