package com.liquidnet.service.kylin.utils;

import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.service.goblin.constant.GoblinRedisConst;
import com.liquidnet.service.goblin.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.manage.vo.GoblinGoodsAnticipateValueVo;
import com.liquidnet.service.goblin.dto.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Component
public class KylinRedisUtils {
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    GoblinMongodbUtils goblinMongoUtils;

    private int randomMax = 10;

    public void del(String... keys) {
        redisUtil.del(keys);
    }

    /**
     * 商品基础信息
     *
     * @param spuId 商品ID
     * @return GoblinGoodsInfoVo
     */
    public GoblinGoodsInfoVo getGoodsInfoVo(String spuId) {
        String pre = GoblinStatusConst.MarketPreStatus.getPre(spuId);
        if (pre != null && pre.equals(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue())) {
            String[] spuSplitArr = spuId.split(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue());
            String rk = GoblinRedisConst.BASIC_GOODS.concat(spuSplitArr[0]);
            GoblinGoodsInfoVo vo = (GoblinGoodsInfoVo) redisUtil.get(rk);
            if (null == vo && null != (vo = goblinMongoUtils.getGoodsInfoVo(spuId))) {
                redisUtil.set(rk, vo);
            }
            if (vo == null) {
                return vo;
            }
            String marketrk = GoblinRedisConst.BASIC_GOODS.concat(spuId);
            GoblinGoodsInfoVo marketVo = (GoblinGoodsInfoVo) redisUtil.get(marketrk);
            if (null == marketVo && null != (marketVo = goblinMongoUtils.getGoodsInfoVo(spuId))) {
                redisUtil.set(marketrk, marketVo);
            }
            if (marketVo == null) {
                return marketVo;
            }
            vo.setSpuId(marketVo.getSpuId());
            List<String> skuIdList = CollectionUtil.linkedListString();
            for (String skuIds : vo.getSkuIdList()) {
                skuIdList.add(skuIds.concat(pre).concat(spuSplitArr[1]));
            }
            vo.setSkuIdList(skuIdList);
            vo.setPriceGe(marketVo.getPriceGe());
            vo.setPriceLe(marketVo.getPriceLe());
            vo.setMarketId(marketVo.getMarketId());
            vo.setDelFlg(marketVo.getDelFlg().equals("1") ? marketVo.getDelFlg() : vo.getDelFlg());
            return vo;
        } else {
            String rk = GoblinRedisConst.BASIC_GOODS.concat(spuId);
            GoblinGoodsInfoVo vo = (GoblinGoodsInfoVo) redisUtil.get(rk);
            if (null == vo && null != (vo = goblinMongoUtils.getGoodsInfoVo(spuId))) {
                redisUtil.set(rk, vo);
            }
            return vo;
        }
    }

    /**
     * 获取 包含分段购的sku详情 HASHMAP
     *
     * @param now   当前时间
     * @param skuId skuId
     * @return
     */
    public HashMap<String, Object> getGoodsSkuInfoVo(LocalDateTime now, String skuId) {
        GoblinGoodsSkuInfoVo vo = getGoodsSkuInfoVo(skuId);
        if (null == vo) {
            return null;
        }
        HashMap<String, Object> map = CollectionUtil.mapStringObject();
        LocalDateTime nextSaleStartTime = null;
        if (null == vo.getSaleStartTime() || now.isAfter(vo.getSaleStartTime())) {//普通商品已开售
            map.put("vo", vo);
            map.put("tagType", null);
            map.put("listId", null);
            map.put("whiteType", null);
            map.put("baseSaleStartTime", vo.getSaleStartTime());
            map.put("nextSaleStartTime", null);
        } else {//未开售
            GoblinListCollectVo collectVo = getCollectByNow(now, skuId);
            Integer tagType = null;
            Integer whiteType = null;
            String listId = null;
            LocalDateTime baseSaleStartTime = vo.getSaleStartTime();
            if (collectVo != null) {
                vo.setPrice(collectVo.getPrice());
                vo.setPriceV(collectVo.getPriceV());
                vo.setProductId(collectVo.getProductId());
                vo.setSaleStartTime(collectVo.getTimeStart());
                vo.setSaleStopTime(collectVo.getTimeEnd());
                listId = collectVo.getListId();
                whiteType = collectVo.getWhiteType();
                tagType = collectVo.getTagType();
            }
            GoblinListCollectVo collectNext = getCollectByNowNext(now, skuId);
            if (collectNext != null) {
                if (tagType == null) {
                    tagType = collectNext.getTagType();
                }
                //todo 逻辑修改 开售时间
                if (collectVo == null) {
                    vo.setSaleStartTime(collectNext.getTimeStart());
                    vo.setSaleStopTime(collectNext.getTimeEnd());
                }
                nextSaleStartTime = collectNext.getTimeStart();
            }
            map.put("vo", vo);
            map.put("tagType", tagType);
            map.put("listId", listId);
            map.put("whiteType", whiteType);
            map.put("baseSaleStartTime", baseSaleStartTime);
            map.put("nextSaleStartTime", nextSaleStartTime);
        }
        return map;
    }

    /**
     * 单品信息
     *
     * @param skuId 单品ID
     * @return GoblinGoodsSkuInfoVo
     */
    public GoblinGoodsSkuInfoVo getGoodsSkuInfoVo(String skuId) {
        String pre = GoblinStatusConst.MarketPreStatus.getPre(skuId);
        if (pre != null && pre.equals(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue())) {

            String rk = GoblinRedisConst.BASIC_GOODS_SKU.concat(skuId.split(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue())[0]);
            GoblinGoodsSkuInfoVo vo = (GoblinGoodsSkuInfoVo) redisUtil.get(rk);
            if (null == vo && null != (vo = goblinMongoUtils.getGoodsSkuInfoVo(skuId))) {
                redisUtil.set(rk, vo);
            }
            if (vo == null) {
                return vo;
            }
            String marketrk = GoblinRedisConst.BASIC_GOODS_SKU.concat(skuId);
            GoblinGoodsSkuInfoVo marketVo = (GoblinGoodsSkuInfoVo) redisUtil.get(marketrk);
            if (null == marketVo && null != (marketVo = goblinMongoUtils.getGoodsSkuInfoVo(skuId))) {
                redisUtil.set(marketrk, marketVo);
            }
            if (marketVo == null) {
                return marketVo;
            }

            vo.setSpuId(marketVo.getSpuId());
            vo.setSkuId(marketVo.getSkuId());
            vo.setPrice(marketVo.getPrice());
            vo.setPriceMember(marketVo.getPriceMember());
            vo.setSkuStock(marketVo.getSkuStock());
            vo.setBuyLimit(marketVo.getBuyLimit());
            vo.setBuyRoster(marketVo.getBuyRoster());
            vo.setBuyFactor(marketVo.getBuyFactor());
//            vo.setDelFlg("0");
            vo.setDelFlg(marketVo.getDelFlg().equals("1") ? marketVo.getDelFlg() : vo.getDelFlg());
            vo.setMarketId(marketVo.getMarketId());
            vo.setCreatedAt(LocalDateTime.now());
            return vo;
        } else {
            String rk = GoblinRedisConst.BASIC_GOODS_SKU.concat(skuId);
            GoblinGoodsSkuInfoVo vo = (GoblinGoodsSkuInfoVo) redisUtil.get(rk);
            if (null == vo && null != (vo = goblinMongoUtils.getGoodsSkuInfoVo(skuId))) {
                redisUtil.set(rk, vo);
            }
            return vo;
        }
    }
    /**
     * 根据时间获取当前分段购vo
     *
     * @param now
     * @param skuId
     * @return
     */
    public GoblinListCollectVo getCollectByNow(LocalDateTime now, String skuId) {
        GoblinListCollectVo collectVo = null;
        GoblinListCollectVo collectTemp = null;
        List<GoblinListCollectVo> collectVos = getGoblinListCollect(skuId);
        for (int i = 0; i < collectVos.size(); i++) {
            GoblinListCollectVo collectVoItem = collectVos.get(i);
            if (now.isAfter(collectVoItem.getTimeStart()) && collectVoItem.getTimeEnd() == null) {
                if (collectTemp == null || collectTemp.getTimeStart().isBefore(collectVoItem.getTimeStart())) {
                    collectTemp = collectVoItem;
                }
            } else if (now.isAfter(collectVoItem.getTimeStart()) && now.isBefore(collectVoItem.getTimeEnd())) {
                collectVo = collectVoItem;
                break;
            } else if (collectVoItem.getTimeEnd() != null && now.isAfter(collectVoItem.getTimeEnd())) {
                collectTemp = null;
            }
        }
        if (collectVo == null) {
            collectVo = collectTemp;
        }
        return collectVo;
    }
    public List<GoblinListCollectVo> getGoblinListCollect(String skuId) {
        Object obj = redisUtil.get(GoblinRedisConst.LIST_COLLECT.concat(skuId));
        if (obj == null) {
            return ObjectUtil.getGoblinListCollectVo();
        } else {
            List<GoblinListCollectVo> list = (List<GoblinListCollectVo>) obj;
            list = list.stream().sorted(Comparator.comparing(GoblinListCollectVo::getTimeStart)).collect(Collectors.toList());
            return list;
        }
    }
    /**
     * 根据时间获取当前分段购vo 如果当前没有返回下一个
     *
     * @param now
     * @param skuId
     * @return
     */
    public GoblinListCollectVo getCollectByNowNext(LocalDateTime now, String skuId) {
        GoblinListCollectVo collectVo = null;
        GoblinListCollectVo collectTemp = null;
        GoblinListCollectVo collectNext = null;
        List<GoblinListCollectVo> collectVos = getGoblinListCollect(skuId);
        for (int i = 0; i < collectVos.size(); i++) {
            GoblinListCollectVo collectVoItem = collectVos.get(i);
            if (now.isAfter(collectVoItem.getTimeStart()) && collectVoItem.getTimeEnd() == null) {
                if (collectTemp == null || collectTemp.getTimeStart().isBefore(collectVoItem.getTimeStart())) {
                    collectTemp = collectVoItem;
                }
            } else if (now.isAfter(collectVoItem.getTimeStart()) && now.isBefore(collectVoItem.getTimeEnd())) {
                collectVo = collectVoItem;
            } else if (now.isBefore(collectVoItem.getTimeStart())) {
                if (collectNext == null || collectNext.getTimeStart().isAfter(collectNext.getTimeStart())) {
                    collectNext = collectVoItem;
                }
            } else if (collectVoItem.getTimeEnd() != null && now.isAfter(collectVoItem.getTimeEnd())) {
                collectTemp = null;
            }
        }
//        if (collectVo == null && collectTemp != null) {
//            collectVo = collectTemp;
//        } else
//        if (collectVo == null) {
//            collectVo = collectNext;
//        }
//        return collectVo;
        return collectNext;
    }
    // 各种状态下判断藏品是否可以展示
    public boolean getSkuAllStatusShow(GoblinGoodsSkuInfoVo info) {
        if (
                info != null
                        && info.getSkuType() == 1
                        && info.getStatus().equals("3")
                        && info.getShelvesStatus().equals("3")
                        && (info.getSkuAppear() == null || info.getSkuAppear().equals("0"))
                        && info.getDelFlg().equals("0")
                        && ((info.getUnbox().equals("0") && info.getUpchain() == 1) || info.getUnbox().equals("1"))
            // && (info.getUnbox().equals("1") || info.getUpchain() == 1)
        ) {
            return true;
        } else {
            return false;
        }
    }
    /**
     * 根据skuId获取valueVo
     */
    public GoblinGoodsAnticipateValueVo getValueBySkuId(String skuId) {
        return (GoblinGoodsAnticipateValueVo) redisUtil.get(GoblinRedisConst.ANTICIPATE_VALUE_SKUID.concat(skuId));
    }
    //获取 用户sku购买个数
    public Integer getSkuCountByUid(String uid, String skuId) {
        String redisKey = GoblinRedisConst.REDIS_GOBLIN_BUY_COUNT.concat(uid + ":skuId:" + skuId);
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            return 0;
        } else {
            return (Integer) obj;
        }
    }
    public int getIsExchange(String skuId) {
        String redisKey = GoblinRedisConst.ACTIVITY_SKU_TIME.concat(skuId);
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            return 1;
        } else {
            GoblinNftExSkuVo exSkuVo = (GoblinNftExSkuVo) obj;
            if ((null == exSkuVo.getExStartTime() || LocalDateTime.now().isAfter(exSkuVo.getExStartTime())) && (null == exSkuVo.getExStopTime() || LocalDateTime.now().isBefore(exSkuVo.getExStopTime()))) {
                return 2;
            } else {
                return 1;
            }
        }
    }
    public int getNotPayNum(String skuId, String listId) {
        String redisKey = GoblinRedisConst.REDIS_GOBLIN_NFT_NOT_PAY_NUM.concat(skuId);
        if (null != listId) {
            redisKey = redisKey.concat(":").concat(listId);
        }
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            return 1;
        } else {
            return (int) obj;
        }
    }
    // 获取盲盒下藏品的库存 各种状态下不能算库存的排除掉
    public int getSkuAllStatusStock(GoblinGoodsSkuInfoVo info, String listId) {
        if (
                info != null
//                        && LocalDateTime.now().isAfter(info.getSaleStartTime())
                        && (null == info.getSoldoutStatus() || info.getSoldoutStatus().equals("0"))
                        && (null == info.getHitRatio() || info.getHitRatio().compareTo(BigDecimal.ZERO) > 0)
                        && (null == info.getSkuCanbuy() || info.getSkuCanbuy().equals("1"))
        ) {// 可以返回库存
            // 外面只有盲盒才能请求进来 里面只有不是分批购才判断盲盒里藏品的开售时间
            if (null == listId) {
//                if (LocalDateTime.now().isAfter(info.getSaleStartTime())) {
                return getSkuStock(listId, info.getSkuId());
//                } else {
//                    return 0;
//                }
            } else {
                return getSkuStock(listId, info.getSkuId());
            }
        } else {// 不计入库存
            return 0;
        }
    }
    // 各种状态下判断藏品总库存
    public Integer getSkuTotalStock(GoblinGoodsSkuInfoVo 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)
        ) {// 可以返回库存
            return info.getSkuStock();
        } else {// 不计入库存
            return 0;
        }
    }



    /**
     * 获取用户预约头像
     */
    public List<String> getUserAvatar(String skuId) {
        String rdk = GoblinRedisConst.ANTICIPATE_SKUID_AVATAR.concat(skuId);
        Object obj = redisUtil.get(rdk);
        if (obj == null) {
            return CollectionUtil.arrayListString();
        } else {
            return (List<String>) obj;
        }
    }

    // 获取 组合售数据
    public GoblinMixDetailsVo getMixDetails(String mixId) {
        String rdk = GoblinRedisConst.GOBLIN_MIX_DETAILS.concat(mixId);
        Object obj = redisUtil.get(rdk);
        if (obj == null) {
            return GoblinMixDetailsVo.getNew();
        } else {
            return (GoblinMixDetailsVo) obj;
        }
    }
    //根据用户uid和混合mixId查询用户预约
    public GoblinMixReserveVo getReserveMixByUid(String uid, String mixId) {
        Object obj = redisUtil.get(GoblinRedisConst.GOBLIN_MIX_RESERVE_UID.concat(mixId).concat(":").concat(uid));
        if (obj == null) {
            return null;
        } else {
            return (GoblinMixReserveVo) obj;
        }
    }
    /**
     * 获取 盲盒skuId 关联 的skuId
     */
    public ArrayList<String> getGoblinMixRelationBox(String skuId, String mixId) {
        String rdk = GoblinRedisConst.GOBLIN_MIX_RELATION_BOX.concat(skuId).concat(":" + mixId);
        Object obj = redisUtil.get(rdk);
        if (obj == null) {
            return CollectionUtil.arrayListString();
        } else {
            return (ArrayList<String>) obj;
        }
    }
    public int getSkuStock(String marketPre, String skuId) {
        String rk = GoblinRedisConst.REAL_STOCK_SKU;
        if (marketPre != null && !marketPre.equals("null")) {
            rk = rk.concat(marketPre + ":");
        }
        rk = rk.concat(skuId);
        Object obj = redisUtil.get(rk);
        if (obj == null) {
            return 0;
        } else {
            return (int) obj;
        }
    }

}
