package com.gree.mall.miniapp.logic.seckill;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gree.mall.miniapp.bean.PayDetail;
import com.gree.mall.miniapp.bean.order.OrderBuyBean;
import com.gree.mall.miniapp.bean.seckill.SecKillBean;
import com.gree.mall.miniapp.bean.seckill.SecKillExtends;
import com.gree.mall.miniapp.bean.user.CurrentCompanyWechat;
import com.gree.mall.miniapp.commonmapper.AppMapper;
import com.gree.mall.miniapp.commonmapper.GoodsFlagUpdateMapper;
import com.gree.mall.miniapp.commonmapper.SecActivityStageMapper;
import com.gree.mall.miniapp.constant.Constant;
import com.gree.mall.miniapp.enums.OrderStatusEnum;
import com.gree.mall.miniapp.exception.RemoteServiceException;
import com.gree.mall.miniapp.helper.ResponseHelper;
import com.gree.mall.miniapp.logic.common.CommonLogic;
import com.gree.mall.miniapp.logic.order.OrderLogic;
import com.gree.mall.miniapp.plus.entity.*;
import com.gree.mall.miniapp.plus.service.*;
import com.gree.mall.miniapp.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.sql.Savepoint;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SecKillLogic {

    @Autowired
    AppMapper appMapper;
    @Autowired
    SecActivityStageMapper secActivityStageMapper;
    @Autowired
    private SecKillActivityService secKillActivityService;
    @Autowired
    private RedisLockRegistry redisLockRegistry;
    @Autowired
    private GoodsFlagUpdateMapper goodsFlagUpdateMapper;
    @Autowired
    private SecKillTokenService secKillTokenService;
    @Autowired
    private CommonLogic commonLogic;

    /**
     * 秒杀时间段
     *
     * @return
     */
    public List<SecKillExtends> queryTimeList(HttpServletRequest request) {
        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat(request);

        List<SecKillExtends> secKillExtends = appMapper.queryTimeList(currentCompanyWechat.getCurrentCompanyWechatId());
        List<SecKillExtends> notYjs = secKillExtends.stream().filter(v -> !v.getType().equals("yjs")).collect(Collectors.toList());
        if(notYjs.size() == 0){
            return new ArrayList<>();
        }
        return secKillExtends;
    }


    public IPage<SecKillActivitySpec> page(String secKillId, Integer pageNum, Integer pageSize) {
        return secActivityStageMapper.querySecGoods(new Page(pageNum, pageSize), secKillId);
    }

    public boolean isSecing(String secKillId) {
        int count = secKillActivityService.lambdaQuery()
                .eq(SecKillActivity::getSecKillId, secKillId)
                .eq(SecKillActivity::getDel, false)
                .eq(SecKillActivity::getStatus, true)
                .le(SecKillActivity::getStartTime, new Date())
                .ge(SecKillActivity::getEndTime, new Date())
                .count();
        Integer stageCount = secActivityStageMapper.queryStageCount(secKillId);

        return count > 0 && stageCount > 0;
    }


    @Transactional
    public String secKillStart(String secKillId) {
        String token = "";
        SecKillStage secKillStage = secActivityStageMapper.queryStage(secKillId);
        //没有场次,返回空
        if (secKillStage == null) {
            return token;
        }
        token = UUID.randomUUID().toString();
//        SecKillToken secKillToken = secKillTokenService.lambdaQuery()
//                .eq(SecKillToken::getSecKillId, secKillId)
//                .eq(SecKillToken::getSecStageId, secKillStage.getSecKillStageId())
//                .one();
//        if (secKillToken == null) {
//            secKillToken = new SecKillToken();
//            token = UUID.randomUUID().toString();
//            secKillToken.setToken(token);
//            secKillToken.setSecKillId(secKillId);
//            secKillToken.setSecStageId(secKillStage.getSecKillStageId());
//            secKillToken.setCreateTime(new Date());
//            secKillToken.setCompanyWechatId(secKillStage.getCompanyWechatId());
//            secKillToken.setCompanyName(secKillStage.getCompanyName());
//            secKillTokenService.save(secKillToken);
//        } else {
//            token = secKillToken.getToken();
//        }
        return token;
    }


    public SecKillActivitySpec getStock(String secKillId,String goodsSpecId,int num) throws InterruptedException {
        SecKillActivity secKillActivity = secKillActivityService.lambdaQuery()
                .eq(SecKillActivity::getSecKillId, secKillId)
                .eq(SecKillActivity::getStatus, true)
                .eq(SecKillActivity::getDel, false)
                .ge(SecKillActivity::getEndTime, new Date())
                .le(SecKillActivity::getStartTime, new Date())
                .one();
        Integer stageCount = secActivityStageMapper.queryStageCount(secKillId);
        if (secKillActivity == null || stageCount == 0) {
            throw new RemoteServiceException("活动未开始或已经结束");
        }
        if(num == 0){
            return secActivityStageMapper.getSecKillSpecByGoodsSpecId(goodsSpecId);
        }

        String key = secKillId+"_"+goodsSpecId;
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER_STOCK + key);
        try {
            if (!obtain.tryLock(10, TimeUnit.SECONDS)) {
                log.error("还原秒杀库存获取锁失败");
                throw new RemoteServiceException("系统繁忙，请稍后再试");
            }
            SecKillActivitySpec secKillActivitySpec = secActivityStageMapper.getSecKillSpecByGoodsSpecId(goodsSpecId);

            if (secKillActivitySpec != null && secKillActivitySpec.getSecStockNum() < num) {
                throw new RemoteServiceException("库存不足");
            }
            //修改库存
            secKillActivitySpec.setSecStockNum(secKillActivitySpec.getSecStockNum() - num);
            secKillActivitySpec.updateById();
            return secKillActivitySpec;
        } catch (InterruptedException e) {
            log.error("还原秒杀库存获取锁失败",e);
        } finally {
            obtain.unlock();
        }
        return null;
    }


    public void goodsSecFlagUpdate() {
        goodsFlagUpdateMapper.updateSecFlag();
    }

}
