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

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 java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class PlatformGoblinGoodsService extends ServiceImpl<GoblinGoodsMapper, GoblinGoods> {
    @Autowired
    private RedisDataSourceUtil redisDataSourceUtil;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private GoblinGoodsSkuMapper goblinGoodsSkuMapper;

    @Transactional
    public void shelvesProcessing(List<String> spuIdList) {
        LocalDateTime now = LocalDateTime.now();
        LambdaUpdateWrapper<GoblinGoods> updateSpuWrapper = Wrappers.lambdaUpdate(GoblinGoods.class);
        updateSpuWrapper.in(GoblinGoods::getSpuId, spuIdList);

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

            if (goblinGoodsSkuMapper.update(updateSku, updateSkuWrapper) > 0) {
                UpdateResult updateSpuResult = mongoTemplate.getCollection(GoblinGoodsInfoVo.class.getSimpleName()).updateMany(
                        Query.query(Criteria.where("spuId").in(spuIdList).and("shelvesStatus").is("0").and("shelvesHandle").is("3")).getQueryObject(),
                        Update.update("shelvesStatus", "3").set("shelvesAt", now).getUpdateObject()
                );
                if (updateSpuResult.getModifiedCount() > 0) {
                    UpdateResult updateSkuResult = mongoTemplate.getCollection(GoblinGoodsSkuInfoVo.class.getSimpleName()).updateMany(
                            Query.query(Criteria.where("spuId").in(spuIdList).and("delFlg").is("0")).getQueryObject(),
                            Update.update("shelvesStatus", "3").set("shelvesAt", now).getUpdateObject()
                    );
                    if (updateSkuResult.getModifiedCount() > 0) {
                        AbstractRedisUtil redisGoblinUtil = redisDataSourceUtil.getRedisGoblinUtil();

                        Query query = Query.query(Criteria.where("delFlg").is("0").and("spuId").in(spuIdList));
                        query.fields().include("skuId");
                        List<GoblinGoodsSkuInfoVo> vos = mongoTemplate.find(query, GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
                        List<String> skuIdList = vos.stream().map(GoblinGoodsSkuInfoVo::getSkuId).collect(Collectors.toList());

                        spuIdList.forEach(spuId -> redisGoblinUtil.del(GoblinRedisConst.BASIC_GOODS.concat(spuId)));
                        skuIdList.forEach(skuId -> redisGoblinUtil.del(GoblinRedisConst.BASIC_GOODS_SKU.concat(skuId)));
                        return;
                    } else {
                        LocalDateTime of = LocalDateTime.of(2022, 1, 1, 0, 0);
                        mongoTemplate.getCollection(GoblinGoodsInfoVo.class.getSimpleName()).updateMany(
                                Query.query(Criteria.where("spuId").in(spuIdList).and("shelvesAt").is(now)).getQueryObject(),
                                Update.update("shelvesStatus", "0").set("shelvesAt", of).getUpdateObject()
                        );
                    }
                }
            }
            throw new LiquidnetServiceException();
        }
    }
}
