package com.liquidnet.service.platform.utils;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.liquidnet.common.cache.redis.util.AbstractRedisUtil;
import com.liquidnet.common.cache.redis.util.RedisDataSourceUtil;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.constant.GoblinRedisConst;
import com.liquidnet.service.goblin.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.GoblinQueueBizIntegralDto;
import com.liquidnet.service.goblin.dto.GoblinStoreMarketDto;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.entity.GoblinGoodsSku;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

@Component
public class GoblinRedisUtils {
    @Autowired
    private RedisDataSourceUtil redisDataSourceUtil;
    @Autowired
    QueueUtils queueUtils;

    public int randomMax = 10;

    private AbstractRedisUtil getRedis() {
        return redisDataSourceUtil.getRedisGoblinUtil();
    }

    public void del(String... keys) {
        getRedis().del(keys);
    }
    public boolean set(String key, Object val) {
        return getRedis().set(key, val);
    }

    // 获取 订单相关vo
    public GoblinStoreOrderVo getGoblinOrder(String orderId) {
        String redisKey = GoblinRedisConst.REDIS_GOBLIN_ORDER.concat(orderId);
        Object obj = getRedis().get(redisKey);
        if (obj == null) {
            return null;
        } else {
            return (GoblinStoreOrderVo) obj;
        }
    }

    // 获取 订单相关Skuvo
    public GoblinOrderSkuVo getGoblinOrderSkuVo(String orderSkuId) {
        String redisKey = GoblinRedisConst.REDIS_GOBLIN_ORDER_SKU.concat(orderSkuId);
        Object obj = getRedis().get(redisKey);
        if (obj == null) {
            return null;
        } else {
            return (GoblinOrderSkuVo) obj;
        }
    }
    //获取 spu销量
    public Integer getSpuSaleCount(String spuId) {
        String redisKey = GoblinRedisConst.REDIS_GOBLIN_SALE_SPU_COUNT.concat(spuId);
        Object obj = getRedis().get(redisKey);
        if (obj == null) {
            return null;
        } else {
            return (Integer) obj;
        }
    }

    //获取 未支付的订单redis列表
    public List<String> getUnPayGoblinOrderList(String randomKey) {
        String redisKey = GoblinRedisConst.REDIS_GOBLIN_ORDER_UN_PAY.concat(randomKey);
        Object obj = getRedis().get(redisKey);
        if (obj == null) {
            return CollectionUtil.arrayListString();
        } else {
            return (List<String>) getRedis().get(redisKey);
        }
    }

    // 删除 未支付订单id列表
    public void removeGoblinOrder(String randomKey, String orderId) {
        if (randomKey == null) {
            for (int i = 0; i < randomMax; i++) {
                String redisKey = GoblinRedisConst.REDIS_GOBLIN_ORDER_UN_PAY.concat(i + "");
                List<String> list = getUnPayGoblinOrderList(randomKey);
                if (list.contains(orderId)) {
                    list.remove(orderId);
                    getRedis().set(redisKey, list);
                    break;
                }
            }
        } else {
            String redisKey = GoblinRedisConst.REDIS_GOBLIN_ORDER_UN_PAY.concat(randomKey + "");
            List<String> list = getUnPayGoblinOrderList(randomKey);
            list.remove(orderId);
            getRedis().set(redisKey, list);
        }
    }

    //添加库存
    public int incrSkuStock(String marketPre, String skuId, Integer stock) {
        String rk = GoblinRedisConst.REAL_STOCK_SKU;
        if (marketPre != null && !marketPre.equals("null")) {
            rk = rk.concat(marketPre + ":");
        }
        rk = rk.concat(skuId);
        return (int) getRedis().incr(rk, stock);
    }

    // 获取sku库存


    // 减少库存
    public int decrSkuStock(String marketPre, String skuId, Integer stock){
        String rk = GoblinRedisConst.REAL_STOCK_SKU;
        if (marketPre != null && !marketPre.equals("null")) {
            rk = rk.concat(marketPre + ":");
        }
        rk = rk.concat(skuId);
        return (int) getRedis().decr(rk, stock);
    }

    // 减少 用户sku购买个数
    public int decrSkuCountByUid(String uid, String skuId, int number) {
        String redisKey = GoblinRedisConst.REDIS_GOBLIN_BUY_COUNT.concat(uid + ":skuId:" + skuId);
        return (int) getRedis().decr(redisKey, number);
    }

    // 赋值 订单相关vo
    public void setGoblinOrder(String orderId, GoblinStoreOrderVo vo) {
        String redisKey = GoblinRedisConst.REDIS_GOBLIN_ORDER.concat(orderId);
        getRedis().set(redisKey, vo);
    }

    // 赋值 订单相关Skuvo
    public void setGoblinOrderSku(String orderSkuId, GoblinOrderSkuVo vo) {
        String redisKey = GoblinRedisConst.REDIS_GOBLIN_ORDER_SKU.concat(orderSkuId);
        getRedis().set(redisKey, vo);
    }

    /* ---------------------------------------- 商铺活动 ---------------------------------------- */

    public List<GoblinStoreMarketDto> getStoreMarketDtos(String storeId) {
        String rk = GoblinRedisConst.STORE_MARKETS.concat(storeId);
        String valStr = (String) getRedis().get(rk);
        List<GoblinStoreMarketDto> dtos = null;
        if (StringUtils.isEmpty(valStr)) {
            // TODO: 2022/2/17 zhanggb mongodb 查取该商品所有参与的活动并整理集合
            dtos = ObjectUtil.getGoblinStoreMarketDtoArrayList();
        } else {
            dtos = JsonUtils.fromJson(valStr, new TypeReference<List<GoblinStoreMarketDto>>() {
            });
        }
        return dtos;
    }

    public boolean addStoreMarketDto(String storeId, GoblinStoreMarketDto dto) {
        List<GoblinStoreMarketDto> dtos = this.getStoreMarketDtos(storeId);
        dtos.removeIf(r -> r.getType().equals(dto.getType()) && r.getId().equals(dto.getId()));
        dtos.add(dto);
        return getRedis().set(GoblinRedisConst.STORE_MARKETS.concat(storeId), JsonUtils.toJson(dtos));
//        if (dtos.stream().noneMatch(r -> (r.getType().equals(dto.getType()) && r.getId().equals(dto.getId())))) {
//            dtos.add(dto);
//            return getRedis().set(GoblinRedisConst.STORE_MARKETS.concat(storeId), JsonUtils.toJson(dtos));
//        }
//        return false;
    }

    public void delStoreMarketDto(String storeId, GoblinStoreMarketDto dto) {
        String rk = GoblinRedisConst.STORE_MARKETS.concat(storeId);
        List<GoblinStoreMarketDto> dtos = this.getStoreMarketDtos(storeId);
        if (!CollectionUtils.isEmpty(dtos)) {
            int beforeSize = dtos.size();
            dtos.removeIf(r -> r.getId().equals(dto.getId()) && r.getType().equals(dto.getType()));
            if (beforeSize > dtos.size()) {
                getRedis().set(GoblinRedisConst.STORE_MARKETS.concat(storeId), JsonUtils.toJson(dtos));
            }
        }
    }

    public void integral(String uid, BigDecimal price, String content, int type) {
        if (price.intValue() > 0) {
            GoblinQueueBizIntegralDto goblinQueueBizIntegralDto = GoblinQueueBizIntegralDto.getNew();
            goblinQueueBizIntegralDto.setUid(uid);
            goblinQueueBizIntegralDto.setScore(price);
            goblinQueueBizIntegralDto.setContent(content);
            goblinQueueBizIntegralDto.setType(type);
            queueUtils.sendMsgByGoblinRedis(MQConst.GoblinQueue.BIZ_INTEGRAL.getKey(), goblinQueueBizIntegralDto.toJson());
        }
    }


    /**
     * 添加code码  添加过期时间
     * @param code
     * @param goblinNftExCodeVo
     * @param millisNum
     * @return
     */
    public boolean addCode(String code, GoblinNftExCodeVo goblinNftExCodeVo, long millisNum) {
        String key = GoblinRedisConst.ACTIVITY_SKU_CODE.concat(code);
        return getRedis().set(key,goblinNftExCodeVo,millisNum);
    }

    /**
     * 兑换码
     */
    public GoblinNftExCodeVo getGoblinNftExCodeVo(String code) {
        String redisKey = GoblinRedisConst.ACTIVITY_SKU_CODE.concat(code);
        Object obj = getRedis().get(redisKey);
        if (obj == null) {
            return null;
        } else {
            return (GoblinNftExCodeVo) obj;
        }
    }

    // 获取盲盒下藏品的库存 各种状态下不能算库存的排除掉
    public int getSkuAllStatusStock(GoblinGoodsSku info) {
        if (
                info != null
                        // && LocalDateTime.now().isAfter(info.getSaleStartTime())
                        && (null == info.getSoldoutStatus() || info.getSoldoutStatus().equals("0"))
                        && (null == info.getHitRatio() || info.getHitRatio().compareTo(BigDecimal.ZERO) > 0)
        ) {// 可以返回库存

            String rk = GoblinRedisConst.REAL_STOCK_SKU.concat(info.getSkuId());
            return (int)getRedis().get(rk);
        } else {// 不计入库存
            return 0;
        }
    }

    /**
     * redis codes主动失效
     * @param code
     */
    public void removeCode(String code) {
        String key = GoblinRedisConst.ACTIVITY_SKU_CODE.concat(code);
        getRedis().del(key);
    }

    /**
     * 获取sku时间
     * @param skuId
     * @return
     */
    public GoblinNftExSkuVo getSkuTime(String skuId) {
        String key = GoblinRedisConst.ACTIVITY_SKU_TIME.concat(skuId);
        GoblinNftExSkuVo goblinNftExSkuVo = null;
        if (!StringUtil.isEmpty(getRedis().get(key))){
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.convertValue (getRedis().get(key), GoblinNftExSkuVo.class);
        }
        return goblinNftExSkuVo;
    }

    /**
     * sku时间赋值
     * @param skuId
     * @param obj
     * @return
     */
    public boolean addSkuTime(String skuId,GoblinNftExSkuVo goblinNftExSkuVo) {
        String key = GoblinRedisConst.ACTIVITY_SKU_TIME.concat(skuId);
        return getRedis().set(key,goblinNftExSkuVo);
    }

    /**
     * 获取sku库存
     * @param skuId
     * @return
     */
    public int getSkuStock(String skuId) {
        String rk = GoblinRedisConst.REAL_STOCK_SKU.concat(skuId);
        Object obj = getRedis().get(rk);
        if (obj == null) {
            return 0;
        } else {
            return (int) obj;
        }
    }

    // 获取sku配置库存




    /* ----------------------------------------  ---------------------------------------- */
    /* ----------------------------------------  ---------------------------------------- */
    /* ----------------------------------------  ---------------------------------------- */
}
