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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liquidnet.common.cache.redis.util.AbstractRedisUtil;
import com.liquidnet.common.cache.redis.util.RedisDataSourceUtil;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.service.goblin.constant.GoblinRedisConst;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSkuInfoVo;
import com.liquidnet.service.goblin.entity.GoblinGoods;
import com.liquidnet.service.goblin.entity.GoblinGoodsSku;
import com.liquidnet.service.goblin.mapper.GoblinGoodsMapper;
import com.liquidnet.service.goblin.mapper.GoblinGoodsSkuMapper;
import com.mongodb.client.result.UpdateResult;
import org.springframework.beans.factory.annotation.Autowired;
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.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class PlatformGoblinGoodsSkuService extends ServiceImpl<GoblinGoodsSkuMapper, GoblinGoodsSku> {
    @Autowired
    private RedisDataSourceUtil redisDataSourceUtil;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private GoblinGoodsMapper goblinGoodsMapper;

    public List<GoblinGoodsSku> shelvesInquiry() {
        LocalDateTime now = LocalDateTime.now();
        LambdaQueryWrapper<GoblinGoodsSku> queryWrapper = Wrappers.lambdaQuery(GoblinGoodsSku.class);
        queryWrapper.eq(GoblinGoodsSku::getSkuType, 1);// 1-数字藏品
        queryWrapper.eq(GoblinGoodsSku::getDelFlg, "0");
        queryWrapper.eq(GoblinGoodsSku::getStatus, "3");
        queryWrapper.eq(GoblinGoodsSku::getShelvesHandle, "3");
        queryWrapper.le(GoblinGoodsSku::getShelvesTime, now);
        queryWrapper.in(GoblinGoodsSku::getShelvesStatus, "0");
        queryWrapper.orderByAsc(GoblinGoodsSku::getShelvesTime);

        queryWrapper.select(GoblinGoodsSku::getSkuId, GoblinGoodsSku::getSpuId);
        return this.list(queryWrapper);
    }

    @Transactional
    public void shelvesProcessing(List<String> skuIdList, List<String> spuIdList) {
        LocalDateTime now = LocalDateTime.now();
        LambdaUpdateWrapper<GoblinGoodsSku> updateSkuWrapper = Wrappers.lambdaUpdate(GoblinGoodsSku.class);
        updateSkuWrapper.in(GoblinGoodsSku::getSkuId, skuIdList);

        updateSkuWrapper.set(GoblinGoodsSku::getShelvesStatus, "3");
        updateSkuWrapper.set(GoblinGoodsSku::getShelvesAt, now);
        if (this.update(updateSkuWrapper)) {
            GoblinGoods updateSpu = new GoblinGoods();
            updateSpu.setShelvesAt(now);
            updateSpu.setShelvesStatus("3");
            LambdaUpdateWrapper<GoblinGoods> updateSpuWrapper = Wrappers.lambdaUpdate(GoblinGoods.class);
            updateSpuWrapper.in(GoblinGoods::getSpuId, spuIdList);
            updateSpuWrapper.eq(GoblinGoods::getDelFlg, "0");

            LiquidnetServiceException liquidnetServiceException = new LiquidnetServiceException();
            if (goblinGoodsMapper.update(updateSpu, updateSpuWrapper) > 0) {
                UpdateResult updateSkuResult = mongoTemplate.getCollection(GoblinGoodsSkuInfoVo.class.getSimpleName()).updateMany(
                        Query.query(Criteria.where("skuId").in(skuIdList).and("delFlg").is("0").and("shelvesStatus").in("0").and("shelvesHandle").is("3")).getQueryObject(),
                        Update.update("shelvesStatus", "3").set("shelvesAt", now).set("updatedAt", now).getUpdateObject()
                );
                if (updateSkuResult.getModifiedCount() > 0) {
                    UpdateResult updateSpuResult = mongoTemplate.getCollection(GoblinGoodsInfoVo.class.getSimpleName()).updateMany(
                            Query.query(Criteria.where("spuId").in(spuIdList).and("delFlg").is("0")).getQueryObject(),
                            Update.update("shelvesStatus", "3").set("shelvesAt", now).set("updatedAt", now).getUpdateObject()
                    );
                    if (updateSpuResult.getModifiedCount() > 0) {
                        AbstractRedisUtil redisGoblinUtil = redisDataSourceUtil.getRedisGoblinUtil();

                        skuIdList.forEach(skuId -> {
                            redisGoblinUtil.del(GoblinRedisConst.BASIC_GOODS_SKU.concat(skuId));
//                            redisGoblinUtil.del(GoblinRedisConst.BASIC_GOODS_SKU_UNSHELVES.concat(skuId));
                        });
                        spuIdList.forEach(spuId -> {
                            redisGoblinUtil.del(GoblinRedisConst.BASIC_GOODS.concat(spuId));
//                            redisGoblinUtil.del(GoblinRedisConst.BASIC_GOODS_UNSHELVES.concat(spuId));
                        });
                        return;
                    } else {
                        mongoTemplate.getCollection(GoblinGoodsSkuInfoVo.class.getSimpleName()).updateMany(
                                Query.query(Criteria.where("skuId").in(skuIdList).and("shelvesAt").is(now)).getQueryObject(),
                                Update.update("shelvesStatus", "0").getUpdateObject()
                        );
                        liquidnetServiceException.setMessage("更新失败:Mongo.GoblinGoodsInfoVo");
                    }
                } else {
                    liquidnetServiceException.setMessage("更新失败:Mongo.GoblinGoodsSkuInfoVo");
                }
            } else {
                liquidnetServiceException.setMessage("更新失败:Mysql.GoblinGoods");
            }
            throw liquidnetServiceException;
        }
    }
}
