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

import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSkuInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinNftGoodsSkuListJobVo;
import com.liquidnet.service.goblin.service.GoblinCouponService;
import com.liquidnet.service.goblin.service.manage.IGoblinGoodsAnticipateMgService;
import com.liquidnet.service.goblin.util.*;
import lombok.extern.slf4j.Slf4j;
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.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Slf4j
public class GoblinNftJobServiceImpl {

    @Autowired
    private GoblinRedisUtils goblinRedisUtils;
    @Autowired
    MongoTemplate mongoTemplate;
    @Autowired
    QueueUtils queueUtils;
    @Autowired
    GoblinMongoUtils mongoUtils;
    @Autowired
    private GoblinOrderUtils goblinOrderUtils;
    @Autowired
    GoblinCouponService goblinCouponService;
    @Autowired
    IGoblinGoodsAnticipateMgService goblinGoodsAnticipateMgService;

    public ResponseDto<Boolean> goodsList() {
        // mongo初始条件
        Query query1 = Query.query(
                Criteria.where("skuType").is(1).and("delFlg").is("0")
                        .and("status").is("3").and("shelvesStatus").is("3")
                        .and("skuAppear").is("0")
                        .orOperator(Criteria.where("unbox").is("0").and("upchain").is(1), Criteria.where("unbox").is("1"))

        );
        LocalDateTime nowTime = LocalDateTime.now();
        // 未开始的正序20个
        query1.addCriteria(Criteria.where("saleStartTime").gt(nowTime));
        // 分页 排序:按照开售时间
        Pageable pageable = PageRequest.of(0, 20, Sort.by(Sort.Direction.ASC, "saleStartTime"));
        query1.with(pageable);
        // 查询
        List<GoblinNftGoodsSkuListJobVo> notStartSkuInfoVos = mongoTemplate.find(query1, GoblinNftGoodsSkuListJobVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
        // 获取分段购真实的时间
        for (GoblinNftGoodsSkuListJobVo info : notStartSkuInfoVos) {
            HashMap<String, Object> mapData = goblinRedisUtils.getGoodsSkuInfoVo(nowTime, info.getSkuId());
            GoblinGoodsSkuInfoVo skuInfoVo = (GoblinGoodsSkuInfoVo) mapData.get("vo");
            String listId = (String) mapData.get("listId");
            info.setSaleStartTime(skuInfoVo.getSaleStartTime());
            info.setListId(listId);
        }

        // mongo初始条件
        Query query2 = Query.query(
                Criteria.where("skuType").is(1).and("delFlg").is("0")
                        .and("status").is("3").and("shelvesStatus").is("3")
                        .and("skuAppear").is("0")
                        .orOperator(Criteria.where("unbox").is("0").and("upchain").is(1), Criteria.where("unbox").is("1"))
        );
        // 已开始的倒序80个
        query2.addCriteria(Criteria.where("saleStartTime").lte(nowTime));
        // 分页 排序:按照开售时间
        Pageable pageable2 = PageRequest.of(0, 80, Sort.by(Sort.Direction.DESC, "saleStartTime"));
        query2.with(pageable2);
        // 查询
        List<GoblinNftGoodsSkuListJobVo> startSkuInfoVos = mongoTemplate.find(query2, GoblinNftGoodsSkuListJobVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
        // 获取分段购真实的时间
        for (GoblinNftGoodsSkuListJobVo info : startSkuInfoVos) {
            HashMap<String, Object> mapData = goblinRedisUtils.getGoodsSkuInfoVo(nowTime, info.getSkuId());
            GoblinGoodsSkuInfoVo skuInfoVo = (GoblinGoodsSkuInfoVo) mapData.get("vo");
            String listId = (String) mapData.get("listId");
            info.setSaleStartTime(skuInfoVo.getSaleStartTime());
            info.setListId(listId);
        }

        // 根据新的开售时间重新分配俩个list
        List<GoblinNftGoodsSkuListJobVo> notAndStartSkuInfoVos = Stream.of(notStartSkuInfoVos, startSkuInfoVos).flatMap(Collection::stream).collect(Collectors.toList());
        notStartSkuInfoVos = new ArrayList<>();
        startSkuInfoVos = new ArrayList<>();
        for (GoblinNftGoodsSkuListJobVo skuInfoVo : notAndStartSkuInfoVos) {
            if (nowTime.isBefore(skuInfoVo.getSaleStartTime())) {// 未开始的
                notStartSkuInfoVos.add(skuInfoVo);
            } else {// 已开始的
                startSkuInfoVos.add(skuInfoVo);
            }
        }
        notStartSkuInfoVos = notStartSkuInfoVos.stream().sorted(Comparator.comparing(GoblinNftGoodsSkuListJobVo::getSaleStartTime)).collect(Collectors.toList());
        startSkuInfoVos = startSkuInfoVos.stream().sorted(Comparator.comparing(GoblinNftGoodsSkuListJobVo::getSaleStartTime, Comparator.reverseOrder())).collect(Collectors.toList());

        List<String> startSkuIdList = CollectionUtil.arrayListString();
        List<String> notStartSkuIdList = CollectionUtil.arrayListString();
        List<String> soldOutSkuIdList = CollectionUtil.arrayListString();

        List<GoblinNftGoodsSkuListJobVo> jobVoArrayList = ObjectUtil.getGoblinNftGoodsSkuListJobVoArrayList();
        jobVoArrayList.addAll(notStartSkuInfoVos);
        jobVoArrayList.addAll(startSkuInfoVos);

        for (GoblinNftGoodsSkuListJobVo info : jobVoArrayList) {
            if (nowTime.compareTo(info.getSaleStartTime()) > 0) {// 已开卖
                List<String> skuIdList = CollectionUtil.arrayListString();
                if (info.getUnbox().equals("1")) {// 是盲盒，非盲盒少查一次spu
                    skuIdList = goblinRedisUtils.getGoodsInfoVo(info.getSpuId()).getSkuIdList();
                }
                HashMap<String, Integer> stockHashMap = goblinOrderUtils.getIsStock(info.getListId(), info.getSkuId(), info.getUnbox(), info.getSoldoutStatus(), skuIdList);
                if (stockHashMap.get("isStock") == 1) {// 已开卖-未售罄
                    startSkuIdList.add(info.getSkuId());
                } else {// 已开卖-已售罄 时间正序
                    soldOutSkuIdList.add(info.getSkuId());
                }
            } else {// 未开卖 时间正序
                notStartSkuIdList.add(info.getSkuId());
            }
        }
        // 已开卖 时间倒序
        Collections.reverse(soldOutSkuIdList);
        // 写入缓存
        goblinRedisUtils.setGoblinNftGoodsInfoListVo(startSkuIdList, "1");
        goblinRedisUtils.setGoblinNftGoodsInfoListVo(notStartSkuIdList, "2");
        goblinRedisUtils.setGoblinNftGoodsInfoListVo(soldOutSkuIdList, "3");

        return ResponseDto.success();
    }

    /**
     * 处理[未开售/开售]五分钟内的nft[优先购/分批购]库存job
     *
     * @return
     */
    public ResponseDto<Boolean> goblinNftListStock() {
        LocalDateTime now = LocalDateTime.now();
        try {
            // mongo初始条件
            Query query1 = Query.query(
                    Criteria.where("skuType").is(1).and("delFlg").is("0")
                            .and("status").is("3").and("shelvesStatus").is("3")
                            .and("skuAppear").is("0")
                            .orOperator(Criteria.where("unbox").is("0").and("upchain").is(1), Criteria.where("unbox").is("1"))

            );
            query1.addCriteria(Criteria.where("saleStartTime").gt(now.minusMinutes(10)));
            // 查询 未开售 和 开售五分钟内的skuId
            List<GoblinNftGoodsSkuListJobVo> notStartSkuInfoVos = mongoTemplate.find(query1, GoblinNftGoodsSkuListJobVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());

            for (GoblinNftGoodsSkuListJobVo item : notStartSkuInfoVos) {
                goblinRedisUtils.getCollectByNow(now, item.getSkuId());
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseDto.failure();
        }
        return ResponseDto.success();
    }
}
