package com.qs.mp.quartz.task;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.qs.mp.admin.domain.Marketing;
import com.qs.mp.admin.service.IMarketingAwardsService;
import com.qs.mp.admin.service.IMarketingService;
import com.qs.mp.common.core.redis.DistributedLocker;
import com.qs.mp.common.core.redis.RedisCache;
import com.qs.mp.common.enums.MarketingStatusEnum;
import com.qs.mp.common.enums.UserTypeEnum;
import com.qs.mp.common.utils.DateUtils;
import com.qs.mp.common.utils.LogUtil;
import com.qs.mp.framework.domain.WxSubscribeMessage;
import com.qs.mp.framework.redis.RedisKey;
import com.qs.mp.framework.redis.RedisLockKey;
import com.qs.mp.framework.service.IWxSubscribeMessage;
import com.qs.mp.user.domain.MarketingUserCode;
import com.qs.mp.user.service.IMarketingUserCodeService;
import org.redisson.Redisson;
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.io.IOException;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 营销活动相关任务
 *
 * @author Cup
 * @date 2022/5/18
 */
@Component("marketingTask")
public class MarketingTask {


    @Autowired
    private DistributedLocker distributedLocker;

    @Autowired
    private IMarketingService marketingService;

    @Autowired
    private IWxSubscribeMessage wxSubscribeMessage;

    @Autowired
    private IMarketingUserCodeService marketingUserCodeService;

    protected final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());


    /**
     * 开奖任务方法
     */
    public void lottery() {
        // 获取结束时间小于等于当前时间且未开奖的活动
        Date now = DateUtils.getNowDate();
        List<Marketing> marketingList = marketingService.list(new LambdaQueryWrapper<Marketing>()
                .eq(Marketing::getTriggerStatus, 0)
                .eq(Marketing::getIsOn, MarketingStatusEnum.ON.getValue())
                .le(Marketing::getEndTime, now));
        if (CollectionUtils.isEmpty(marketingList)) {
            return;
        }

        for (Marketing marketing : marketingList) {
            String lockKey = RedisLockKey.build(RedisLockKey.MARKETING_LOTTERY_KEY, marketing.getId());
            // 加锁,自动续期
            if (!distributedLocker.tryLock(lockKey,0,-1,TimeUnit.SECONDS)) {
                continue;
            }
            try {
                // 开奖
                marketingService.lottery(marketing);

                // 获取所有的参与用户的用户id去重
                List<MarketingUserCode> userCodeList = marketingUserCodeService.list(new LambdaQueryWrapper<MarketingUserCode>()
                        .select(MarketingUserCode::getUserId)
                        .eq(MarketingUserCode::getMarketingId, marketing.getId())
                        .eq(MarketingUserCode::getUserType, UserTypeEnum.ORDINARY.getValue())
                        .groupBy(MarketingUserCode::getUserId));
                for (MarketingUserCode marketingUserCode : userCodeList) {
                    // 发送开奖订阅通知
                    wxSubscribeMessage.sendMarketingLottery(marketingUserCode.getUserId(), marketing);
                }
            } catch (Exception e) {
                LogUtil.error(logger, e, "活动开奖异常。marketingId:{0}", marketing.getId());
            } finally {
                // 释放锁
                distributedLocker.unlock(lockKey);
            }
        }

    }


    /**
     * 发送活动开始通知
     */
    public void sendMessage() {
        // 获取开始时间小于等于当前时间且未发开始通知的活动
        Date now = DateUtils.getNowDate();
        List<Marketing> marketingList = marketingService.list(new LambdaQueryWrapper<Marketing>()
                .eq(Marketing::getTriggerStatus, 0)
                .eq(Marketing::getIsOn, MarketingStatusEnum.ON.getValue())
                .eq(Marketing::getIsSend, 0)
                .le(Marketing::getStartTime, now));
        if (CollectionUtils.isEmpty(marketingList)) {
            return;
        }

        // 获取所有参与过活动的普通用户根据用户id去重
        List<MarketingUserCode> userCodeList = marketingUserCodeService.list(new LambdaQueryWrapper<MarketingUserCode>()
                .select(MarketingUserCode::getUserId)
                .eq(MarketingUserCode::getUserType, UserTypeEnum.ORDINARY.getValue())
                .groupBy(MarketingUserCode::getUserId));
        if (CollectionUtils.isEmpty(userCodeList)) {
            return;
        }

        for (Marketing marketing : marketingList) {
            for (MarketingUserCode marketingUserCode : userCodeList) {
                // 发送开始订阅通知
                wxSubscribeMessage.sendMarketingStart(marketingUserCode.getUserId(), marketing);
            }

            // 更新活动通知发送状态
            marketingService.update(new LambdaUpdateWrapper<Marketing>()
                    .set(Marketing::getIsSend, 1)
                    .eq(Marketing::getId, marketing.getId()));
        }
    }

    /**
     * 增加活动参与的虚拟人数
     */
    public void addFake() {
        // 获取开始时间大于等于当前时间且未结束和开奖的活动
        Date now = DateUtils.getNowDate();
        List<Marketing> marketingList = marketingService.list(new LambdaQueryWrapper<Marketing>()
                .eq(Marketing::getTriggerStatus, 0)
                .eq(Marketing::getIsOn, MarketingStatusEnum.ON.getValue())
                .lt(Marketing::getStartTime, now)
                .gt(Marketing::getEndTime, now));
        if (CollectionUtils.isEmpty(marketingList)) {
            return;
        }

        for (Marketing marketing : marketingList) {
            // 随机加1-10
            marketingService.update(new LambdaUpdateWrapper<Marketing>()
                    .set(Marketing::getFakeNum, marketing.getFakeNum() + RandomUtil.randomInt(1,10))
                    .eq(Marketing::getId, marketing.getId()));
        }
    }

}
