package com.liquidnet.service.goblin.service.impl;

import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.service.base.PagedResult;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.manage.vo.AnticipateValueVo;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.service.GoblinCouponService;
import com.liquidnet.service.goblin.service.IGoblinGoodsAnticipateService;
import com.liquidnet.service.goblin.service.IGoblinNftGoodsAppService;
import com.liquidnet.service.goblin.util.GoblinMongoUtils;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.ObjectUtil;
import com.liquidnet.service.goblin.util.QueueUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@Slf4j
public class GoblinNftGoodsAppServiceImpl implements IGoblinNftGoodsAppService {

    @Autowired
    private GoblinRedisUtils goblinRedisUtils;
    @Autowired
    MongoTemplate mongoTemplate;
    @Autowired
    QueueUtils queueUtils;
    @Autowired
    GoblinMongoUtils mongoUtils;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    GoblinCouponService goblinCouponService;
    @Autowired
    IGoblinGoodsAnticipateService goblinGoodsAnticipateService;

    @Override
    public ResponseDto<PagedResult<GoblinNftGoodsSkuListVo>> goodsList(int page) {

        int size = 10;
        //条件
        Query query = Query.query(
                Criteria.where("skuType").is(1)
                        .and("delFlg").is("0")
                        .and("status").is("3")
                        .and("shelvesStatus").is("3")
                        .and("skuAppear").is("0")
        );
        long count = mongoTemplate.count(query, GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
        List<GoblinNftGoodsSkuListVo> skuList = goblinRedisUtils.getGoblinNftGoodsInfoListVo();
        if (null == skuList || page > 1) {
            skuList = new ArrayList<>();
            // 分页 排序:按照开售时间
            Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.ASC, "saleStartTime"));
            query.with(pageable);

            List<GoblinGoodsSkuInfoVo> skuInfoVos = mongoTemplate.find(query, GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
            for (GoblinGoodsSkuInfoVo info : skuInfoVos) {
                //获取预约相关
                AnticipateValueVo anticipateValueVo = goblinGoodsAnticipateService.getAnticipateValueBySkuId(info.getSkuId()).getData();
                // sku信息
                GoblinNftGoodsSkuListVo nftGoodsSkuInfoVo = GoblinNftGoodsSkuListVo.getNew().copy(info, anticipateValueVo);
                // spu信息
                GoblinGoodsInfoVo goodsInfoVo = goblinRedisUtils.getGoodsInfoVo(info.getSpuId());
                GoblinNftGoodsSpuInfoVo nftGoodsSpuInfoVo = GoblinNftGoodsSpuInfoVo.getNew().copy(goodsInfoVo);
                nftGoodsSkuInfoVo.setGoblinNftGoodsSpuInfoVo(nftGoodsSpuInfoVo);
                // 写入列表
                skuList.add(nftGoodsSkuInfoVo);
            }
            if (page <= 1) {
                goblinRedisUtils.setGoblinNftGoodsInfoListVo(skuList);
            }
        }
        for (GoblinNftGoodsSkuListVo skuInfoVo : skuList) {
            int stock = 0;
            if (skuInfoVo.getUnbox().equals("0")) {
                if (null == skuInfoVo.getSoldoutStatus() || skuInfoVo.getSoldoutStatus().equals("0")) {
                    stock = goblinRedisUtils.getSkuStock(null, skuInfoVo.getSkuId());
                }
            } else {
                String spuId = skuInfoVo.getSpuId();
                List<String> skuArray = goblinRedisUtils.getGoodsInfoVo(spuId).getSkuIdList();
                for (String skuIdItem : skuArray) {
                    GoblinGoodsSkuInfoVo itemVo = goblinRedisUtils.getGoodsSkuInfoVo(skuIdItem);
                    stock += goblinRedisUtils.getSkuAllStatusStock(itemVo);
                }
            }
            if (stock <= 0 || (null != skuInfoVo.getSoldoutStatus() && skuInfoVo.getSoldoutStatus().equals("1"))) {
                skuInfoVo.setIsStock(0);
            } else {
                skuInfoVo.setIsStock(1);
            }
        }
        List<GoblinNftGoodsSkuListVo> listSort = skuList.stream().sorted(Comparator.comparing(GoblinNftGoodsSkuListVo::getIsStock).reversed()).collect(Collectors.toList());

        PagedResult<GoblinNftGoodsSkuListVo> listVoPagedResult = ObjectUtil.getGoblinNftGoodsSkuListVoPagedResult();
        listVoPagedResult.setList(listSort).setTotal(count, size).setPageSize(size).setCurrentPage(page);
        return ResponseDto.success(listVoPagedResult);
    }

    @Override
    public GoblinNftGoodsSkuInfoVo goodsDetail(String skuId) {
        GoblinGoodsSkuInfoVo goodsSkuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(skuId);
        if (goblinRedisUtils.getSkuAllStatusShow(goodsSkuInfoVo)) {
            //获取预约相关
            AnticipateValueVo anticipateValueVo = goblinGoodsAnticipateService.getAnticipateValueBySkuId(skuId).getData();

            GoblinNftGoodsSkuInfoVo nftGoodsSkuInfoVo = GoblinNftGoodsSkuInfoVo.getNew().copy(goodsSkuInfoVo, anticipateValueVo);
            // 限购数量
            Integer buyCount = 0;
            String userId = CurrentUtil.getCurrentUid();
            if (StringUtils.isNotBlank(userId)) {
                buyCount = goblinRedisUtils.getSkuCountByUid(userId, skuId);
            }
            if (null != goodsSkuInfoVo.getBuyLimit() && 0 != goodsSkuInfoVo.getBuyLimit()) {
                nftGoodsSkuInfoVo.setCanBuyNum(goodsSkuInfoVo.getBuyLimit() - buyCount);
            }
            // 库存 盲盒计算所有sku库存总数
            int stock = 0;
            if (goodsSkuInfoVo.getUnbox().equals("0")) {
                if (null == goodsSkuInfoVo.getSoldoutStatus() || goodsSkuInfoVo.getSoldoutStatus().equals("0")) {
                    stock = goblinRedisUtils.getSkuStock(null, skuId);
                }
            } else {
                String spuId = goodsSkuInfoVo.getSpuId();
                List<String> skuArray = goblinRedisUtils.getGoodsInfoVo(spuId).getSkuIdList();
                for (String skuIdItem : skuArray) {
                    GoblinGoodsSkuInfoVo itemVo = goblinRedisUtils.getGoodsSkuInfoVo(skuIdItem);
                    stock += goblinRedisUtils.getSkuAllStatusStock(itemVo);
                }
            }
            log.info("skuId:{}, 库存数量:{}", skuId, stock);
            if (stock <= 0) {
                nftGoodsSkuInfoVo.setIsStock(0);
            } else {
                nftGoodsSkuInfoVo.setIsStock(1);
            }
            // spu信息
            GoblinGoodsInfoVo goodsInfoVo = goblinRedisUtils.getGoodsInfoVo(goodsSkuInfoVo.getSpuId());
            GoblinNftGoodsSpuInfoVo nftGoodsSpuInfoVo = GoblinNftGoodsSpuInfoVo.getNew().copy(goodsInfoVo);
            nftGoodsSkuInfoVo.setGoblinNftGoodsSpuInfoVo(nftGoodsSpuInfoVo);
            nftGoodsSkuInfoVo.setSystime(LocalDateTime.now());
            return nftGoodsSkuInfoVo;
        } else {
            return null;
        }
    }

    @Override
    public Boolean exchange(String code) {
        /*// 验证
        // 使用
        // 下单
        return true;*/
        try {
//            int dbs = 255;
            int dbs = 15;
            String redisKey2 = "goblin:nftOrder:orderCode*";
            String redisKey3 = "goblin:nftOrder:idList:user*";
            String redisKey4 = "goblin:nftOrder:refund*";
            String redisKey5 = "goblin:nftOrder:lock:userId*";
            String redisKey6 = "goblin:nftGoodsList*";
            String redisKey7 = "goblin:nftNumAccount*";
            String redisKey1 = "goblin:nftOrder*";

            String redisKey11 = "goblin:nft:order:id:";
            String redisKey22 = "goblin:nft:order:code:";
            String redisKey33 = "goblin:nft:order:idList:";
            String redisKey44 = "goblin:nft:order:refund:";
            String redisKey55 = "goblin:nft:order:lock:";
            String redisKey66 = "goblin:nft:goodsList";
            String redisKey77 = "goblin:nft:account:";


            for (int i = 0; i < dbs; i++) {

                Set<String> keys2 = redisUtil.getRedisTemplateByDb(i).keys(redisKey2);
                for (String key : keys2) {
                    String[] split = key.split(":");
                    String keyId = split[split.length - 1];
                    String value = (String) redisUtil.get(key);
                    redisUtil.set(redisKey22.concat(keyId), value);
                    redisUtil.del(key);
                }

                Set<String> keys3 = redisUtil.getRedisTemplateByDb(i).keys(redisKey3);
                for (String key : keys3) {
                    String[] split = key.split(":");
                    String keyId = split[split.length - 1];
                    List<String> value = (List<String>) redisUtil.get(key);
                    redisUtil.set(redisKey33.concat(keyId), value);
                    redisUtil.del(key);
                }

                Set<String> keys4 = redisUtil.getRedisTemplateByDb(i).keys(redisKey4);
                for (String key : keys4) {
                    String[] split = key.split(":");
                    String keyId = split[split.length - 1];
                    GoblinNftOrderRefundVo value = (GoblinNftOrderRefundVo) redisUtil.get(key);
                    redisUtil.set(redisKey44.concat(keyId), value);
                    redisUtil.del(key);
                }

                Set<String> keys6 = redisUtil.getRedisTemplateByDb(i).keys(redisKey6);
                for (String key : keys6) {
                    String[] split = key.split(":");
                    String keyId = split[split.length - 1];
                    List<GoblinNftGoodsSkuListVo> value = (List<GoblinNftGoodsSkuListVo>) redisUtil.get(key);
                    redisUtil.set(redisKey66.concat(keyId), value);
                    redisUtil.del(key);
                }

                Set<String> keys7 = redisUtil.getRedisTemplateByDb(i).keys(redisKey7);
                for (String key : keys7) {
                    String[] split = key.split(":");
                    String keyId = split[split.length - 1];
                    Integer value = (Integer) redisUtil.get(key);
                    redisUtil.set(redisKey77.concat(keyId), value);
                    redisUtil.del(key);
                }

                Set<String> keys1 = redisUtil.getRedisTemplateByDb(i).keys(redisKey1);
                for (String key : keys1) {
                    String[] split = key.split(":");
                    String keyId = split[split.length - 1];
                    GoblinNftOrderVo value = (GoblinNftOrderVo) redisUtil.get(key);
                    redisUtil.set(redisKey11.concat(keyId), value);
                    redisUtil.del(key);
                }
            }

            return true;
        } catch (Exception e) {
            log.error("cityVote5Error", e);
            return false;
        }
    }

}
