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 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;

    public List<GoblinGoods> shelvesInquiry() {
        LocalDateTime now = LocalDateTime.now();
        LambdaQueryWrapper<GoblinGoods> queryWrapper = Wrappers.lambdaQuery(GoblinGoods.class);
        queryWrapper.eq(GoblinGoods::getDelFlg, "0");
        queryWrapper.eq(GoblinGoods::getStatus, "3");
        queryWrapper.eq(GoblinGoods::getSpuAppear, "0");
        queryWrapper.eq(GoblinGoods::getShelvesHandle, "3");
        queryWrapper.le(GoblinGoods::getShelvesTime, now);
//        queryWrapper.eq(GoblinGoods::getShelvesStatus, "0");
        queryWrapper.in(GoblinGoods::getShelvesStatus, "0", "1");
        queryWrapper.orderByAsc(GoblinGoods::getShelvesTime);

        queryWrapper.select(GoblinGoods::getSpuId);
        return this.list(queryWrapper);
    }

    @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");

            LiquidnetServiceException liquidnetServiceException = new LiquidnetServiceException();
            if (goblinGoodsSkuMapper.update(updateSku, updateSkuWrapper) > 0) {
                Object nowTimeMdbObj = mongoTemplate.getConverter().convertToMongoType(now);
                UpdateResult updateSpuResult = mongoTemplate.getCollection(GoblinGoodsInfoVo.class.getSimpleName()).updateMany(
                        Query.query(Criteria.where("spuId").in(spuIdList).and("delFlg").is("0").and("shelvesStatus").in("0", "1").and("shelvesHandle").is("3")).getQueryObject(),
                        Update.update("shelvesStatus", "3").set("shelvesAt", nowTimeMdbObj).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", nowTimeMdbObj).getUpdateObject()
                    );
                    if (updateSkuResult.getModifiedCount() > 0) {
                        AbstractRedisUtil redisGoblinUtil = redisDataSourceUtil.getRedisGoblinUtil();

                        {// 精选商品:商品上架、下架、删除 调用的方法
                            redisGoblinUtil.del(GoblinRedisConst.SELECT_GOODS_SPUIDS);
                            redisGoblinUtil.del(GoblinRedisConst.SELECT_GOODS_PAGE1);
                        }

                        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));
                            redisGoblinUtil.del(GoblinRedisConst.BASIC_GOODS_UNSHELVES.concat(spuId));
                        });
                        skuIdList.forEach(skuId -> {
                            redisGoblinUtil.del(GoblinRedisConst.BASIC_GOODS_SKU.concat(skuId));
                            redisGoblinUtil.del(GoblinRedisConst.BASIC_GOODS_SKU_UNSHELVES.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()
                        );
                        liquidnetServiceException.setMessage("更新失败:Mongo.GoblinGoodsSkuInfoVo");
                    }
                } else {
                    liquidnetServiceException.setMessage("更新失败:Mongo.GoblinGoodsInfoVo");
                }
            } else {
                liquidnetServiceException.setMessage("更新失败:Mysql.GoblinGoodsSku");
            }
            throw liquidnetServiceException;
        }
    }
}
