
package com.tmerclub.cloud.seckill.feign;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSONObject;
import com.tmerclub.cloud.api.order.constant.OrderStatus;
import com.tmerclub.cloud.api.product.feign.SpuFeignClient;
import com.tmerclub.cloud.api.seckill.feign.SeckillFeignClient;
import com.tmerclub.cloud.api.seckill.vo.SeckillApiVO;
import com.tmerclub.cloud.common.cache.config.MultiRedisConfig;
import com.tmerclub.cloud.common.cache.enums.MultiStockEnum;
import com.tmerclub.cloud.common.cache.util.RedisUtil;
import com.tmerclub.cloud.common.constant.SeckillOrderCacheConstant;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.order.vo.OrderCountVO;
import com.tmerclub.cloud.common.order.vo.ShopCartOrderMergerVO;
import com.tmerclub.cloud.common.product.vo.SekillActivitySpuVO;
import com.tmerclub.cloud.common.product.vo.SkuVO;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.seckill.service.SeckillService;
import com.tmerclub.cloud.seckill.vo.SeckillVO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author tmerclub
 * @date 2020/12/8
 */
@DubboService
public class SeckillFeignController implements SeckillFeignClient {

    @Autowired
    private SeckillService seckillService;


    @DubboReference
    private SpuFeignClient spuFeignClient;
    @Autowired
    private MultiRedisConfig multiRedisConfig;


    @Override
    public ServerResponseEntity<List<SekillActivitySpuVO>> seckillSpuListBySpuIds(Integer selectedLot, List<Long> spuIds) {
        if (CollUtil.isEmpty(spuIds)) {
            return ServerResponseEntity.success(new ArrayList<>(0));
        }
        List<SekillActivitySpuVO> groupActivitySpuList = seckillService.listBySelectLotAndSpuIds(selectedLot, spuIds);
        // 获取sku原价
        List<Long> skuIds = groupActivitySpuList.stream().map(SekillActivitySpuVO::getSkuId).collect(Collectors.toList());
        ServerResponseEntity<List<SkuVO>> skuResponse = spuFeignClient.listSkuPriceByIds(skuIds);
        if (!skuResponse.isSuccess()) {
            throw new LuckException(skuResponse.getMsg());
        }
        if (CollUtil.isNotEmpty(skuResponse.getData())) {
            Map<Long, Long> skuMap = skuResponse.getData().stream().collect(Collectors.toMap(SkuVO::getSkuId, SkuVO::getPriceFee));
            for (SekillActivitySpuVO sekillActivitySpuVO : groupActivitySpuList) {
                sekillActivitySpuVO.setPriceFee(skuMap.get(sekillActivitySpuVO.getSkuId()));
            }
        }
        return ServerResponseEntity.success(groupActivitySpuList);
    }

    @Override
    public ServerResponseEntity<SeckillApiVO> getSeckillInfoById(Long activityId) {
        SeckillVO seckillVO = seckillService.getBySeckillId(activityId);

        return ServerResponseEntity.success(BeanUtil.map(seckillVO, SeckillApiVO.class));
    }

    @Override
    public ServerResponseEntity<Void> offlineSeckillBySpuIds(List<Long> spuIds, Boolean updateSpu) {
        seckillService.offlineSeckillBySpuIds(spuIds);
        if(updateSpu) {
            // 将spu改为正常状态
            spuFeignClient.changeToNormalSpu(spuIds);
        }
        return ServerResponseEntity.success();
    }

    @Override
    public ServerResponseEntity<Void> offlineSeckillByShopId(Long shopId) {
        seckillService.offlineSeckillByShopId(shopId);
        return ServerResponseEntity.success();
    }

    @Override
    public ServerResponseEntity<ShopCartOrderMergerVO> getSeckillOrderByRedis(Long orderId, Long userId) {
        // 查询一下redis有没有数据,因为秒杀订单还存在redis
        ShopCartOrderMergerVO mergerOrder = null;
        String key = MultiStockEnum.SECKILL.value() + "order:" + userId;
        String orderKey = "info:" + orderId;
        // 获取是哪台redis
        int redisIndex = multiRedisConfig.getIndex(userId);
        StringRedisTemplate stringRedisTemplate = multiRedisConfig.getRedisByIndex(redisIndex);
        Object orderInfo = RedisUtil.hGet(stringRedisTemplate,key, orderKey);
        if (Objects.nonNull(orderInfo)) {
            mergerOrder = JSONObject.parseObject((String) orderInfo, ShopCartOrderMergerVO.class);
            // 获取订单状态
            String statusKey = "status:" + orderId;
            Object status = RedisUtil.hGet(stringRedisTemplate, key, statusKey);
            Integer orderStatus = Integer.valueOf(status.toString());
            mergerOrder.setStatus(orderStatus);
        }
        return ServerResponseEntity.success(mergerOrder);
    }

    @Override
    public ServerResponseEntity<Map<Object, Object>> mapSeckillOrderByUserIdAndRedis(Long userId) {
        int redisIndex = multiRedisConfig.getIndex(userId);
        StringRedisTemplate stringRedisTemplate = multiRedisConfig.getRedisByIndex(redisIndex);
        String key = MultiStockEnum.SECKILL.value() + "order:" + userId;
        Long size = RedisUtil.hSize(stringRedisTemplate,key);
        if(size <= 0) {
            return ServerResponseEntity.success();
        }
        // 获取redis中用户的所有订单
        return ServerResponseEntity.success(RedisUtil.entries(stringRedisTemplate,key));
    }

    @Override
    public void updateRedisSeckillOrderStatus(Long orderId, Long userId, Integer status) {
        // 查询一下redis有没有数据,因为秒杀订单还存在redis
        String key = MultiStockEnum.SECKILL.value() + "order:" + userId;
        String statusKey = "status:" + orderId;
        // 获取是哪台redis
        int redisIndex = multiRedisConfig.getIndex(userId);
        StringRedisTemplate stringRedisTemplate = multiRedisConfig.getRedisByIndex(redisIndex);
        RedisUtil.hSet(stringRedisTemplate,key, statusKey,status.toString());
    }

    @Override
    public ServerResponseEntity<OrderCountVO> countRedisSeckillOrder(Long userId) {
        int redisIndex = multiRedisConfig.getIndex(userId);
        StringRedisTemplate stringRedisTemplate = multiRedisConfig.getRedisByIndex(redisIndex);
        String key = MultiStockEnum.SECKILL.value() + "order:" + userId;
        Long size = RedisUtil.hSize(stringRedisTemplate,key);
        if(size <= 0) {
            return ServerResponseEntity.success();
        }
        OrderCountVO orderCountVO = new OrderCountVO();
        Integer payed = 0;
        Integer unPay = 0;
        Map<Object, Object> orderMap = RedisUtil.entries(stringRedisTemplate, key);
        for (Object orderKey : orderMap.keySet()) {
            String orderKeyStr = orderKey.toString();
            if(orderKeyStr.startsWith(SeckillOrderCacheConstant.STATUS)) {
                Object statusObj = orderMap.get(orderKeyStr);
                Integer orderStatus = Integer.valueOf(statusObj.toString());
                if(Objects.equals(orderStatus, OrderStatus.PAYED.value())) {
                    payed++;
                }
                if(Objects.equals(orderStatus, OrderStatus.UNPAY.value())) {
                    unPay++;
                }
            }
        }
        orderCountVO.setPayed(payed);
        orderCountVO.setUnPay(unPay);
        return ServerResponseEntity.success(orderCountVO);
    }

    @Override
    public ServerResponseEntity<Void> deleteRedisOrderByUserIdAndOrderId(Long userId, Long orderId) {
        int redisIndex = multiRedisConfig.getIndex(userId);
        StringRedisTemplate stringRedisTemplate = multiRedisConfig.getRedisByIndex(redisIndex);
        RedisUtil.hDelete(stringRedisTemplate, MultiStockEnum.SECKILL.value() + "order:" + userId,
                SeckillOrderCacheConstant.STATUS + orderId.toString(),
                SeckillOrderCacheConstant.ORDER_INFO + orderId.toString());
        return ServerResponseEntity.success();
    }
}
