package com.liquidnet.service.goblin.util;

import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.service.base.PagedResult;
import com.liquidnet.service.goblin.constant.GoblinRedisConst;
import com.liquidnet.service.goblin.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.manage.*;
import com.liquidnet.service.goblin.dto.manage.vo.*;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.entity.GoblinFrontBanner;
import com.liquidnet.service.goblin.entity.GoblinFrontHotWord;
import com.liquidnet.service.goblin.entity.GoblinFrontNavigation;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import com.mongodb.BasicDBObject;
import com.mongodb.client.model.UpdateOneModel;
import com.mongodb.client.model.WriteModel;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
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.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.convert.MongoConverter;
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.Component;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.liquidnet.commons.lang.util.DateUtil.DTF_YMD_HMS;
import static com.liquidnet.commons.lang.util.DateUtil.now;

@Component
public class GoblinMongoUtils {
    @Autowired
    MongoTemplate mongoTemplate;
    @Autowired
    MongoConverter mongoConverter;
    @Autowired
    GoblinRedisUtils redisUtils;

    /* ---------------------------------------- 预约数据源 ---------------------------------------- */

    /**
     * 分页查询
     */
    public HashMap<String, Object> getGoblinGoodsAnticipateValueVos(GoblinGoodsAnticipateValueParam goblinGoodsAnticipateValueParam, String uid) {
        HashMap<String, Object> info = CollectionUtil.mapStringObject();
        Pageable pageable = PageRequest.of(goblinGoodsAnticipateValueParam.getPageNum() - 1, 20, Sort.by(Sort.Direction.DESC, "createdDate"));
        Criteria criteria = Criteria.where("delTag").is(0).and("uid").is(uid);
        if (goblinGoodsAnticipateValueParam.getType() != null) {
            if (goblinGoodsAnticipateValueParam.getType() == 1) {
                //预约提醒
                criteria = criteria.and("type").is(goblinGoodsAnticipateValueParam.getType());
            } else if (goblinGoodsAnticipateValueParam.getType() == 2) {
                //预约购买
                criteria = criteria.and("type").is(2).and("peopleType").is(0);
            } else if (goblinGoodsAnticipateValueParam.getType() == 3) {
                //预约助力
                criteria = criteria.and("type").is(2).and("peopleType").gt(0);
            }
        }
        if (StringUtils.isNotBlank(goblinGoodsAnticipateValueParam.getName())) {
            criteria = criteria.and("skuName").regex(".*?" + goblinGoodsAnticipateValueParam.getName() + ".*");
        }
        if (StringUtils.isNotBlank(goblinGoodsAnticipateValueParam.getCreatedDate())) {
            LocalDateTime createDt = DateUtil.Formatter.yyyyMMddHHmmss.parse(goblinGoodsAnticipateValueParam.getCreatedDate());
            LocalDateTime createdAtBegin = createDt.withHour(0).withMinute(0).withSecond(0).withNano(0);
            LocalDateTime createdAtEnd = createDt.withHour(23).withMinute(59).withSecond(59).withNano(999);

            criteria = criteria.and("createdDate").gte(createdAtBegin).lte(createdAtEnd);
        }
        if (StringUtils.isNotBlank(goblinGoodsAnticipateValueParam.getAboutStartDate())) {
            LocalDateTime createDt = DateUtil.Formatter.yyyyMMddHHmmss.parse(goblinGoodsAnticipateValueParam.getAboutStartDate());
            LocalDateTime createdAtBegin = createDt.withHour(0).withMinute(0).withSecond(0).withNano(0);
            LocalDateTime createdAtEnd = createDt.withHour(23).withMinute(59).withSecond(59).withNano(999);

            criteria = criteria.and("aboutStartDate").gte(createdAtBegin);
        }
        if (StringUtils.isNotBlank(goblinGoodsAnticipateValueParam.getAboutEndDate())) {
            LocalDateTime createDt = DateUtil.Formatter.yyyyMMddHHmmss.parse(goblinGoodsAnticipateValueParam.getAboutEndDate());
            LocalDateTime createdAtBegin = createDt.withHour(0).withMinute(0).withSecond(0).withNano(0);
            LocalDateTime createdAtEnd = createDt.withHour(23).withMinute(59).withSecond(59).withNano(999);

            criteria = criteria.and("aboutEndDate").lte(createdAtEnd);
        }
        Query query = Query.query(criteria);
        //查询总数
        long count = mongoTemplate.count(query, GoblinGoodsAnticipateValueVo.class, GoblinGoodsAnticipateValueVo.class.getSimpleName());
        query.with(pageable);
        List<GoblinGoodsAnticipateValueVo> voList = mongoTemplate.find(query, GoblinGoodsAnticipateValueVo.class, GoblinGoodsAnticipateValueVo.class.getSimpleName());
        info.put("total", count);
        info.put("data", voList);
        return info;
    }


    /**
     * 根据名称查询预约
     */
    public boolean getAnticipateVoByName(String name) {
        return mongoTemplate.findOne(Query.query(Criteria.where("name").is(name)),
                GoblinGoodsAnticipateVo.class, GoblinGoodsAnticipateVo.class.getSimpleName()) != null;
    }

    /**
     * 根据名称查询预约
     */
    public GoblinGoodsAnticipateVo getAnticipateVoBySku(String antId) {
        return mongoTemplate.findOne(Query.query(Criteria.where("antId").is(antId)),
                GoblinGoodsAnticipateVo.class, GoblinGoodsAnticipateVo.class.getSimpleName());
    }

    /**
     * 新增预约
     */
    public void setGoblinGoodsAnticipateVo(GoblinGoodsAnticipateVo vo) {
        mongoTemplate.insert(vo, GoblinGoodsAnticipateVo.class.getSimpleName());
    }

    /**
     * 新增用户预约
     */
    public void setGoblinGoodsAnticipateUserVo(GoblinGoodAnticipateUserVo vo) {
        mongoTemplate.insert(vo, GoblinGoodAnticipateUserVo.class.getSimpleName());
    }

    /**
     * 根据skuId修改  预约人数
     */
    public void updateGoblinGoodsAnticipateValueVoPeople(String skuId, BigInteger people) {
        Query query = Query.query(Criteria.where("skuId").is(skuId));
        Update update = new Update().set("aboutPeople", people.longValue()).set("updateDate", LocalDateTime.now());
//        mongoTemplate.updateFirst(query, update, GoblinGoodsAnticipateValueVo.class.getSimpleName());
        mongoTemplate.getCollection(GoblinGoodsAnticipateValueVo.class.getSimpleName()).updateMany(
                query.getQueryObject(),
                update.getUpdateObject());
    }

    /**
     * 根据amtId删除VO
     */
    public void delGoodsAnticipateValueVo(String skuId) {
        redisUtils.delSkuId(skuId);
        Query query = Query.query(Criteria.where("skuId").is(skuId));
        mongoTemplate.remove(query, GoblinGoodsAnticipateValueVo.class.getSimpleName()).getDeletedCount();
    }

    /**
     * 根据活动id查询关联
     */
    public List<GoblinGoodsAnticipateValueVo> getGoodsAnticipateValues(String antId) {
        Criteria criteria = Criteria.where("antId").is(antId).and("delTag").is(0);
        Query query = Query.query(criteria);
        return mongoTemplate.find(query, GoblinGoodsAnticipateValueVo.class, GoblinGoodsAnticipateValueVo.class.getSimpleName());
    }

    /**
     * 根据用户预约
     */
    public void delGoodsAnticipateUserVo(String uid, String skuId) {
        Query query = Query.query(Criteria.where("uid").is(uid).and("skuId").is(skuId));
        mongoTemplate.remove(query, GoblinGoodsAnticipateVo.class.getSimpleName()).getDeletedCount();
    }

    public void delUserBySkuId(String skuId) {
        Query query = Query.query(Criteria.where("skuId").is(skuId));
        List<GoblinGoodAnticipateUserVo> goblinGoodAnticipateUserVos = mongoTemplate.find(query, GoblinGoodAnticipateUserVo.class, GoblinGoodAnticipateUserVo.class.getSimpleName());
        if (goblinGoodAnticipateUserVos.size() > 0) {
            goblinGoodAnticipateUserVos.forEach(goblinGoodAnticipateUserVo -> {
                redisUtils.del(GoblinRedisConst.USER_ANTICIPATE_STATE.concat(goblinGoodAnticipateUserVo.getSkuId()).concat(goblinGoodAnticipateUserVo.getUid()));
            });
            mongoTemplate.remove(query, GoblinGoodAnticipateUserVo.class.getSimpleName()).getDeletedCount();
        }
    }

    /**
     * 添加预约中间表信息
     */
    public void addAnticipateValues(GoblinGoodsAnticipateValueVo goodsAnticipateValueVo) {
        mongoTemplate.insert(goodsAnticipateValueVo, GoblinGoodsAnticipateValueVo.class.getSimpleName());
    }

    /**
     * 修改sku关联信息
     */
    public void updateAnticipateValueVo(GoblinGoodsAnticipateValueVo goodsAnticipateValueVo) {
        Query query = Query.query(Criteria.where("antId").is(goodsAnticipateValueVo.getAntId()).and("skuId").is(goodsAnticipateValueVo.getSkuId()));
        Update update = new Update().set("aboutStartDate", goodsAnticipateValueVo.getAboutStartDate()).set("aboutEndDate", goodsAnticipateValueVo.getAboutEndDate()).set("updateDate", LocalDateTime.now());
        mongoTemplate.updateFirst(query, update, GoblinGoodsAnticipateValueVo.class.getSimpleName());
    }

    /**
     * 存入用户创建分享 不需要mongodb存储
     */
    public void setGoblinGoodsAnticipateShareVo(GoblinGoodsAnticipateShareVo goblinGoodsAnticipateShareVo) {
        mongoTemplate.insert(goblinGoodsAnticipateShareVo, GoblinGoodsAnticipateShareVo.class.getSimpleName());
    }

    /**
     * 根据创建id查询分享信息
     */
    public GoblinGoodsAnticipateShareVo getShareVoBySid(String sid) {
        return mongoTemplate.findOne(Query.query(Criteria.where("sid").is(sid)),
                GoblinGoodsAnticipateShareVo.class, GoblinGoodsAnticipateShareVo.class.getSimpleName());
    }

    /**
     * 分享id和助力人id 查询助力信息  不存mongodb
     */
    public GoblinGoodsAnticipateHelpVo getHelpVo(String sid, String uid) {
        return mongoTemplate.findOne(Query.query(Criteria.where("sid").is(sid).and("helpUid").is(uid)),
                GoblinGoodsAnticipateHelpVo.class, GoblinGoodsAnticipateHelpVo.class.getSimpleName());
    }

    /**
     * 助力vo   之后删去不需要储存
     *
     * @param goodsAnticipateHelpVo
     */
    public void setHelpVo(GoblinGoodsAnticipateHelpVo goodsAnticipateHelpVo) {
        mongoTemplate.insert(goodsAnticipateHelpVo, GoblinGoodsAnticipateHelpVo.class.getSimpleName());
    }

    /* ---------------------------------------- 平台分类数据源 ---------------------------------------- */

    public List<GoblinSelfGoodsCategoryVo> getSelfGoodsCategoryVos() {
        return mongoTemplate.findAll(GoblinSelfGoodsCategoryVo.class, GoblinSelfGoodsCategoryVo.class.getSimpleName());
    }

    /* ---------------------------------------- 店铺分类数据源 ---------------------------------------- */

    public void setStoreGoodsCategoryVos(List<GoblinStoreGoodsCategoryVo> vos) {
        mongoTemplate.insert(vos, GoblinStoreGoodsCategoryVo.class.getSimpleName());
    }

    public boolean updateStoreGoodsCategoryVo(GoblinStoreGoodsCategoryVo vo) {
        return mongoTemplate.getCollection(GoblinStoreGoodsCategoryVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("storeId").is(vo.getStoreId()).and("cateId").is(vo.getCateId())).getQueryObject(),
                ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(vo))
        ).getModifiedCount() > 0;
    }

    public List<GoblinStoreGoodsCategoryVo> getStoreGoodsCategoryVos(String storeId) {
        return mongoTemplate.find(Query.query(Criteria.where("storeId").is(storeId)),
                GoblinStoreGoodsCategoryVo.class, GoblinStoreGoodsCategoryVo.class.getSimpleName());
    }

    /* ---------------------------------------- 平台分类规格数据源 ---------------------------------------- */

    public void setCategorySpecVo(GoblinMgtCategorySpecVo vo) {
        mongoTemplate.insert(vo, GoblinMgtCategorySpecVo.class.getSimpleName());
    }

    public boolean updateCategorySpecVo(GoblinMgtCategorySpecVo vo) {
        return mongoTemplate.getCollection(GoblinMgtCategorySpecVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("cateId").is(vo.getCateId())).getQueryObject(),
                Update.update("specNameList", vo.getSpecNameList()).getUpdateObject()
        ).getModifiedCount() > 0;
    }

    public GoblinMgtCategorySpecVo getCategorySpecVo(String cateId) {
        return mongoTemplate.findOne(Query.query(Criteria.where("cateId").is(cateId)),
                GoblinMgtCategorySpecVo.class, GoblinMgtCategorySpecVo.class.getSimpleName());
    }

    /* ---------------------------------------- 标签数据源 ---------------------------------------- */

    public List<GoblinSelfTagVo> getSelfTagVos(String keyword, String belong, Object[] typeRange) {
        Criteria criteria = Criteria.where("delFlg").is("0").and("tagBelong").is(belong);
        if (StringUtils.isNotBlank(keyword)) {
            criteria.and("tagName").regex("^.*" + keyword + ".*$", "i");
        }
        if (belong.equals("1")) {
            criteria.and("tagType").in(typeRange);
        }
        return mongoTemplate.find(Query.query(criteria).skip(0).limit(20), GoblinSelfTagVo.class, GoblinSelfTagVo.class.getSimpleName());
    }

    /**
     * 标签全量数据
     *
     * @param belong 标签所属[0-普通标签|1-专属标签]
     * @return List<GoblinSelfTagVo>
     */
    public List<GoblinSelfTagVo> getSelfTagVos(String belong) {
        return mongoTemplate.find(Query.query(Criteria.where("delFlg").is("0").and("tagBelong").is(belong)),
                GoblinSelfTagVo.class, GoblinSelfTagVo.class.getSimpleName());
    }

    public List<GoblinSelfTagVo> getMgtSelfTagVos(List<String> tagIds) {
        if (CollectionUtils.isEmpty(tagIds)) return ObjectUtil.getGoblinSelfTagVoArrayList();
        return mongoTemplate.find(Query.query(Criteria.where("delFlg").is("0")),
                GoblinSelfTagVo.class, GoblinSelfTagVo.class.getSimpleName());
    }

//    public List<GoblinGoodsTagVo> getGoodsTagVos(List<String> tagIds) {
//        if (CollectionUtils.isEmpty(tagIds)) return ObjectUtil.getGoblinGoodsTagVoArrayList();
//
//        return null;
//    }
//
//    public List<GoblinGoodsExtagVo> getGoodsExtagVos(List<String> tagIds) {
//        if (CollectionUtils.isEmpty(tagIds)) return ObjectUtil.getGoblinGoodsExtagVoArrayList();
//
//        return null;
//    }

    /* ---------------------------------------- 服务保障数据源 ---------------------------------------- */

    public List<GoblinServiceSupportVo> getServiceSupportVos(List<String> ssids) {
        if (CollectionUtils.isEmpty(ssids)) return ObjectUtil.getGoblinServiceSupportVoArrayList();
        return mongoTemplate.find(Query.query(Criteria.where("ssid").in(ssids)),
                GoblinServiceSupportVo.class, GoblinServiceSupportVo.class.getSimpleName());
    }

    public List<GoblinServiceSupportVo> getMgtServiceSupportVos() {
        return mongoTemplate.findAll(GoblinServiceSupportVo.class, GoblinServiceSupportVo.class.getSimpleName());
    }

    public List<GoblinServiceSupportVo> insertMgtServiceSupportVos(List<GoblinServiceSupportVo> vos) {
        return (List<GoblinServiceSupportVo>) mongoTemplate.insert(vos, GoblinServiceSupportVo.class.getSimpleName());
    }

    /* ---------------------------------------- 店铺公告数据源 ---------------------------------------- */

    public PagedResult<GoblinStoreNoticeVo> getStoreNoticeVos(GoblinStoreMgtNoticeFilterParam filterParam) {
        Criteria criteria = Criteria.where("storeId").is(filterParam.getStoreId()).and("delFlg").is("0");
        if (StringUtils.isNotBlank(filterParam.getKeyword())) {
            Pattern pattern = Pattern.compile("^.*" + filterParam.getKeyword() + ".*$", Pattern.CASE_INSENSITIVE);
            criteria.and("content").regex(pattern);
        }
        Query query = Query.query(criteria);

        long count = mongoTemplate.count(query, GoblinStoreNoticeVo.class.getSimpleName());

        PagedResult<GoblinStoreNoticeVo> pagedResult = ObjectUtil.getGoblinStoreNoticeVoPagedResult();
        if (count <= 0) return pagedResult;

        query.with(PageRequest.of(filterParam.getPageNum() - 1, filterParam.getPageSize()));
        query.with(Sort.by(Sort.Order.desc("createdAt")));

        List<GoblinStoreNoticeVo> storeNoticeVos = mongoTemplate.find(query, GoblinStoreNoticeVo.class, GoblinStoreNoticeVo.class.getSimpleName());
        return pagedResult.setList(storeNoticeVos).setTotal(count, filterParam.getPageSize());
    }

    /**
     * 查取指定店铺有效的公告通知
     *
     * @param storeId 店铺ID
     * @return List<GoblinStoreNoticeVo>
     */
    public List<GoblinStoreNoticeVo> getStoreNoticeVos(String storeId, LocalDateTime nowTime) {
        return mongoTemplate.find(Query.query(Criteria.where("storeId").is(storeId).and("delFlg").is("0")
                        .orOperator(
                                Criteria.where("releaseTime").gte(nowTime),
                                Criteria.where("longLasting").is("0").and("cancellTime").gte(nowTime),
                                Criteria.where("longLasting").is("1")
                        )
                ).with(Sort.by(Sort.Order.asc("releaseTime"), Sort.Order.asc("createdAt"))),
                GoblinStoreNoticeVo.class, GoblinStoreNoticeVo.class.getSimpleName());
    }

    public void setStoreNoticeVo(GoblinStoreNoticeVo vo) {
        mongoTemplate.insert(vo, GoblinStoreNoticeVo.class.getSimpleName());
    }

    public boolean updateStoreNoticeVo(GoblinStoreNoticeVo vo) {
        return mongoTemplate.getCollection(GoblinStoreNoticeVo.class.getSimpleName())
                .updateOne(
                        Query.query(Criteria.where("storeId").is(vo.getStoreId()).and("delFlg").is("0").and("noticeId").is(vo.getNoticeId())).getQueryObject(),
                        ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(vo))
                ).getModifiedCount() > 0;
    }

    public boolean updateStoreNoticeVoByBulk(List<GoblinStoreNoticeVo> vos) {
        List<WriteModel<Document>> list = ObjectUtil.getWriteModelDocumentArrayList();
        vos.forEach(r -> {
            if (StringUtils.isNotEmpty(r.getStoreId())) {
                HashMap<String, Object> updateMdbMap = CollectionUtil.mapStringObject();
                updateMdbMap.put("releaseTime", r.getReleaseTime());
                updateMdbMap.put("status", r.getStatus());
                updateMdbMap.put("updatedBy", r.getUpdatedBy());
                updateMdbMap.put("updatedAt", r.getUpdatedAt());
                list.add(new UpdateOneModel<>(
                        Query.query(Criteria.where("storeId").is(r.getStoreId()).and("noticeId").is(r.getNoticeId())).getQueryObject(),
                        ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(updateMdbMap))
                ));
            }
        });
        return mongoTemplate.getCollection(GoblinStoreNoticeVo.class.getSimpleName()).bulkWrite(list).getModifiedCount() > 0;
    }

    public boolean updateStoreNoticeVoByRelease(String uid, LocalDateTime nowTime, String storeId, List<String> noticeIdList) {
        Object nowTimeMdbObj = mongoConverter.convertToMongoType(nowTime);
        return mongoTemplate.getCollection(GoblinStoreNoticeVo.class.getSimpleName()).updateMany(
                Query.query(Criteria.where("storeId").is(storeId).and("delFlg").is("0").and("noticeId").in(noticeIdList.toArray()).and("status").is("0")).getQueryObject(),
                Update.update("status", "1").set("releaseTime", nowTimeMdbObj).set("updatedBy", uid).set("updatedAt", nowTimeMdbObj).getUpdateObject()
        ).getModifiedCount() > 0;
    }

    public boolean updateStoreNoticeVoByRemove(String uid, LocalDateTime nowTime, String storeId, List<String> noticeIdList) {
        HashMap<String, Object> updateMdbMap = CollectionUtil.mapStringObject();
        updateMdbMap.put("delFlg", "1");
        updateMdbMap.put("updatedBy", uid);
        updateMdbMap.put("updatedAt", nowTime);
        return mongoTemplate.getCollection(GoblinStoreNoticeVo.class.getSimpleName()).updateMany(
                Query.query(Criteria.where("storeId").is(storeId).and("delFlg").is("0").and("noticeId").in(noticeIdList.toArray())).getQueryObject(),
                ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(updateMdbMap))
        ).getModifiedCount() > 0;
    }

    /* ---------------------------------------- 店铺配置数据源 ---------------------------------------- */

    public List<GoblinStoreConfigVo> getStoreConfigVos(String storeId) {
        Query query = Query.query(Criteria.where("storeId").is(storeId));
        query.fields().include("storeId").include("configKey").include("configVal");
        return mongoTemplate.find(query,
                GoblinStoreConfigVo.class, GoblinStoreConfigVo.class.getSimpleName());
    }

    public boolean updateStoreConfigVos(List<GoblinStoreConfigVo> vos) {
        List<WriteModel<Document>> list = ObjectUtil.getWriteModelDocumentArrayList();
        vos.forEach(r -> {
            if (StringUtils.isNotEmpty(r.getStoreId())) {
                HashMap<String, Object> updateMdbMap = CollectionUtil.mapStringObject();
                updateMdbMap.put("configVal", r.getConfigVal());
                updateMdbMap.put("updatedBy", r.getUpdatedBy());
                updateMdbMap.put("updatedAt", r.getUpdatedAt());
                list.add(new UpdateOneModel<>(
                        Query.query(Criteria.where("storeId").is(r.getStoreId()).and("configKey").is(r.getConfigKey())).getQueryObject(),
                        ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(updateMdbMap))
                ));
            }
        });
        return mongoTemplate.getCollection(GoblinStoreConfigVo.class.getSimpleName()).bulkWrite(list).getModifiedCount() > 0;
    }

    public List<GoblinStoreConfigVo> delStoreConfigVo(String storeId) {
        Query query = Query.query(Criteria.where("storeId").is(storeId));
        query.fields().include("configKey").include("configVal");
        return mongoTemplate.find(query,
                GoblinStoreConfigVo.class, GoblinStoreConfigVo.class.getSimpleName());
    }

    /* ---------------------------------------- 店铺ERP配置数据源 ---------------------------------------- */

    public List<String> getStoreErpShopNoList() {
        Query query = Query.query(Criteria.where("shopNo").ne(""));
        query.fields().include("shopNo");
        List<GoblinStoreErpConfigVo> vos = mongoTemplate.find(query, GoblinStoreErpConfigVo.class, GoblinStoreErpConfigVo.class.getSimpleName());
        if (!CollectionUtils.isEmpty(vos)) {
            return vos.stream().map(GoblinStoreErpConfigVo::getShopNo).distinct().collect(Collectors.toList());
        }
        return null;
    }

    public GoblinStoreErpConfigVo getStoreErpConfigVo(String storeId) {
        Query query = Query.query(Criteria.where("storeId").is(storeId));
        return mongoTemplate.findOne(query, GoblinStoreErpConfigVo.class, GoblinStoreErpConfigVo.class.getSimpleName());
    }

    public boolean updateStoreErpConfigVo(GoblinStoreErpConfigVo vo) {
        GoblinStoreErpConfigVo storeErpConfigVo = this.getStoreErpConfigVo(vo.getStoreId());
        if (null == storeErpConfigVo) {
            mongoTemplate.insert(vo, GoblinStoreErpConfigVo.class.getSimpleName());
            return true;
        } else {
            return mongoTemplate.getCollection(GoblinStoreErpConfigVo.class.getSimpleName())
                    .updateOne(Query.query(Criteria.where("storeId").is(vo.getStoreId())).getQueryObject(),
                            ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(vo))
                    ).getModifiedCount() > 0;
        }
    }

    /* ---------------------------------------- 店铺数据源 ---------------------------------------- */

    public GoblinStoreInfoVo setStoreInfoVo(GoblinStoreInfoVo vo) {
        return mongoTemplate.insert(vo, GoblinStoreInfoVo.class.getSimpleName());
    }

    public boolean delStoreInfoVo(String storeId, String uid, LocalDateTime time) {
        return mongoTemplate.updateFirst(Query.query(Criteria.where("storeId").is(storeId)),
                Update.update("delFlg", "1").set("updatedBy", uid).set("updatedAt", time).set("deletedBy", uid).set("deletedAt", time),
                GoblinStoreInfoVo.class.getSimpleName()).getModifiedCount() > 0;
    }

    public boolean updateStoreInfoVo(GoblinStoreInfoVo vo) {
        return mongoTemplate.getCollection(GoblinStoreInfoVo.class.getSimpleName())
                .updateOne(Query.query(Criteria.where("storeId").is(vo.getStoreId())).getQueryObject(),
                        ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(vo))
                ).getModifiedCount() > 0;
    }

    public GoblinStoreInfoVo getStoreInfoVo(String storeId) {
        return mongoTemplate.findOne(Query.query(Criteria.where("storeId").is(storeId).and("delFlg").is("0")),
                GoblinStoreInfoVo.class, GoblinStoreInfoVo.class.getSimpleName());
    }

    public ArrayList<String> getStoreInfoVoRegexName(String storeName) {
        Query query = Query.query(Criteria.where("storeName").regex("^.*" + storeName + ".*$").and("delFlg").is("0").and("status").in("3", "5"));
        query.fields().include("storeId");
        List<GoblinStoreInfoVo> voList = mongoTemplate.find(query, GoblinStoreInfoVo.class, GoblinStoreInfoVo.class.getSimpleName());
        ArrayList<String> list = CollectionUtil.arrayListString();
        for (GoblinStoreInfoVo goblinStoreInfoVo : voList) {
            list.add(goblinStoreInfoVo.getStoreId());
        }
        return list;
    }

    public List<GoblinStoreInfoVo> getStoreInfoVoByUid(String uid) {
//        return mongoTemplate.findOne(Query.query(Criteria.where("uid").is(uid).and("delFlg").is("0")),
//                GoblinStoreInfoVo.class, GoblinStoreInfoVo.class.getSimpleName());
        return mongoTemplate.find(Query.query(Criteria.where("uid").is(uid).and("delFlg").is("0")),
                GoblinStoreInfoVo.class, GoblinStoreInfoVo.class.getSimpleName());
    }

    /* ---------------------------------------- 商品数据源 ---------------------------------------- */

    // SPU信息
    public GoblinGoodsInfoVo setGoodsInfoVo(GoblinGoodsInfoVo vo) {
        return mongoTemplate.insert(vo, GoblinGoodsInfoVo.class.getSimpleName());
    }

    public List<GoblinGoodsInfoVo> insertMgtGoodsInfoVos(List<GoblinGoodsInfoVo> vos) {
        return (List<GoblinGoodsInfoVo>) mongoTemplate.insert(vos, GoblinGoodsInfoVo.class.getSimpleName());
    }

    public void upsertGoodsInfoVo(GoblinGoodsInfoVo vo) {
        Document document = (Document) mongoConverter.convertToMongoType(vo);
        Update update = Update.fromDocument(document);
        mongoTemplate.upsert(Query.query(Criteria.where("storeId").is(vo.getStoreId()).and("spuId").is(vo.getSpuId())), update, GoblinGoodsInfoVo.class.getSimpleName());
    }

    public boolean delGoodsInfoVo(String spuId) {
        return mongoTemplate.getCollection(GoblinGoodsInfoVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("spuId").is(spuId).and("delFlg").is("0")).getQueryObject(),
                Update.update("delFlg", "1").getUpdateObject()
        ).getModifiedCount() > 0;
    }

    public boolean delGoodsSkuInfoVo(String skuId) {
        return mongoTemplate.getCollection(GoblinGoodsSkuInfoVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("skuId").is(skuId).and("delFlg").is("0")).getQueryObject(),
                Update.update("delFlg", "1").getUpdateObject()
        ).getModifiedCount() > 0;
    }

    public boolean delGoodsInfoVoBySpuIds(String storeId, List<String> spuIdList, String uid, LocalDateTime time) {
        return mongoTemplate.updateMulti(
                Query.query(Criteria.where("storeId").is(storeId).and("spuId").in(spuIdList).and("delFlg").is("0")),
                Update.update("delFlg", "1").set("updatedBy", uid).set("updatedAt", time).set("deletedBy", uid).set("deletedAt", time),
                GoblinGoodsInfoVo.class.getSimpleName()
        ).getModifiedCount() > 0;
    }

    public List<String> delGoodsInfoVoByStoreId(String storeId, String uid, LocalDateTime time) {
        Query query = Query.query(Criteria.where("storeId").is(storeId).and("delFlg").is("0").and("shelvesStatus").is("3"));
        query.fields().include("spuId");
        List<GoblinGoodsInfoVo> storeSpus = mongoTemplate.find(query, GoblinGoodsInfoVo.class, GoblinGoodsInfoVo.class.getSimpleName());

        List<String> storeSpuIdList = CollectionUtil.arrayListString();
        if (!CollectionUtils.isEmpty(storeSpus)) {
            storeSpuIdList = storeSpus.stream().map(GoblinGoodsInfoVo::getSpuId).collect(Collectors.toList());
            UpdateResult updateResult = mongoTemplate.updateMulti(Query.query(Criteria.where("spuId").in(storeSpuIdList)),
                    Update.update("delFlg", "1").set("updatedBy", uid).set("updatedAt", time).set("deletedBy", uid).set("deletedAt", time),
                    GoblinGoodsInfoVo.class.getSimpleName());
            if (updateResult.getModifiedCount() > 0) {
                return storeSpuIdList;
            }
        }
        return storeSpuIdList;
    }

    // SPU分页
    public PagedResult<GoblinStoreMgtGoodsListVo> getMgtGoodsInfoVos(GoblinStoreMgtGoodsFilterParam filterParam) {
        Criteria criteria = Criteria.where("delFlg").is("0").and("storeId").is(filterParam.getStoreId()).and("marketId").exists(false);
        if (null != filterParam.getSpuType()) {
            if (0 == filterParam.getSpuType()) {
                criteria.orOperator(Criteria.where("spuType").exists(false), (Criteria.where("spuType").is(0)));
            } else {
//                criteria.and("spuType").is(1);
                criteria.and("spuType").is(filterParam.getSpuType());
            }
        }
        if (StringUtils.isNotBlank(filterParam.getKeyword())) {
            Pattern pattern = Pattern.compile("^.*" + filterParam.getKeyword() + ".*$", Pattern.CASE_INSENSITIVE);
            criteria.and("name").regex(pattern);
        }
        if (StringUtils.isNotBlank(filterParam.getShelvesStatus())) {
            criteria.and("shelvesStatus").is(filterParam.getShelvesStatus());
        }
        if (StringUtils.isNotBlank(filterParam.getCateFid())) {
            criteria.and("cateFid").is(filterParam.getCateFid());
        }
        if (StringUtils.isNotBlank(filterParam.getCateSid())) {
            criteria.and("cateSid").is(filterParam.getCateSid());
        }
        if (StringUtils.isNotBlank(filterParam.getCateTid())) {
            criteria.and("cateTid").is(filterParam.getCateTid());
        }
        if (StringUtils.isNotBlank(filterParam.getCreatedDt())) {
            LocalDateTime createDt = DateUtil.Formatter.yyyy_MM_dd.parse(filterParam.getCreatedDt());
            LocalDateTime createdAtBegin = createDt.withHour(0).withMinute(0).withSecond(0).withNano(0);
            LocalDateTime createdAtEnd = createDt.withHour(23).withMinute(59).withSecond(59).withNano(999);

            criteria.and("createdAt").gte(createdAtBegin).lte(createdAtEnd);
        }
        if (null != filterParam.getPriceGe()) {
            criteria.and("priceGe").gte(filterParam.getPriceGe());
        }
        if (null != filterParam.getPriceLe()) {
            criteria.and("priceLe").lte(filterParam.getPriceLe());
        }
        Query query = Query.query(criteria);

        long count = mongoTemplate.count(query, GoblinGoodsInfoVo.class.getSimpleName());

        PagedResult<GoblinStoreMgtGoodsListVo> pagedResult = ObjectUtil.getGoblinStoreMgtGoodsVoPagedResult();
        if (count <= 0) return pagedResult;

        query.with(PageRequest.of(filterParam.getPageNum() - 1, filterParam.getPageSize()));
        query.with(Sort.by(Sort.Order.desc("createdAt"), Sort.Order.desc("spuId")));

        List<GoblinStoreMgtGoodsListVo> goodsListVos = mongoTemplate.find(query, GoblinStoreMgtGoodsListVo.class, GoblinGoodsInfoVo.class.getSimpleName());

        return pagedResult.setList(goodsListVos).setTotal(count, filterParam.getPageSize());
    }

    /**
     * 在指定SPU商品中模糊搜索，并返回符合条件的SPUID
     *
     * @param spuIdList SPUID列表
     * @param keyword   搜索内容
     * @return List<String>
     */
    public List<String> getSpuIdListBySpuIdListAndKeyword(List<String> spuIdList, String keyword) {
        Criteria criteria = Criteria.where("delFlg").is("0").and("spuId").in(spuIdList);
        if (StringUtils.isNotBlank(keyword)) {
            Pattern pattern = Pattern.compile("^.*" + keyword + ".*$", Pattern.CASE_INSENSITIVE);
            criteria.orOperator(
                    Criteria.where("name").regex(pattern)
            );
        }
        Query query = Query.query(criteria);
        query.fields().include("spuId");
        List<GoblinStoreMgtGoodsListVo> goodsListVos = mongoTemplate.find(query, GoblinStoreMgtGoodsListVo.class, GoblinGoodsInfoVo.class.getSimpleName());
        return CollectionUtils.isEmpty(goodsListVos) ? CollectionUtil.arrayListString() : goodsListVos.stream().map(GoblinStoreMgtGoodsListVo::getSpuId).distinct().collect(Collectors.toList());
    }

    /**
     * 在指定SPU商品中模糊搜索，并返回符合条件的SPUID
     *
     * @param marketId 活动id
     * @param keyword  搜索内容
     * @param page     页数
     * @return List<String>
     */
    public HashMap<String, Object> getMarketSpuData(String marketId, int page, String keyword, String storeId) {
        int pageSize = 16;
        HashMap map = CollectionUtil.mapStringObject();
        Criteria criteria = Criteria.where("delFlg").is("0")
                .and("storeId").is(storeId)
                .and("marketId").is(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue().concat(marketId));
        if (StringUtils.isNotBlank(keyword)) {
            Pattern pattern = Pattern.compile("^.*" + keyword + ".*$", Pattern.CASE_INSENSITIVE);
            criteria.orOperator(
                    Criteria.where("name").regex(pattern)
            );
        }
        Query query = Query.query(criteria);
        query.with(PageRequest.of(page - 1, pageSize));
        query.fields().include("spuId");
        query.with(Sort.by(Sort.Order.desc("shelvesAt")));
        long total = mongoTemplate.count(query, GoblinStoreMgtGoodsListVo.class, GoblinGoodsInfoVo.class.getSimpleName());
        List<GoblinStoreMgtGoodsListVo> goodsListVos = mongoTemplate.find(query, GoblinStoreMgtGoodsListVo.class, GoblinGoodsInfoVo.class.getSimpleName());
        map.put("total", total);
        map.put("data", CollectionUtils.isEmpty(goodsListVos) ? CollectionUtil.arrayListString() : goodsListVos.stream().map(GoblinStoreMgtGoodsListVo::getSpuId).distinct().collect(Collectors.toList()));
        return map;
    }

    public List<String> getMgtSpuNosForMarketBySpuNos(List<String> spuNos, Object... shelvesStatus) {
        Query query = Query.query(Criteria.where("spuNo").in(spuNos.toArray())
                .and("marketId").exists(true).and("delFlg").is("0").and("shelvesStatus").in(shelvesStatus));
        query.fields().include("spuNo");
        List<GoblinGoodsInfoVo> goblinGoodsInfoVos = mongoTemplate.find(query, GoblinGoodsInfoVo.class, GoblinGoodsInfoVo.class.getSimpleName());
        return CollectionUtils.isEmpty(goblinGoodsInfoVos) ? CollectionUtil.arrayListString() : goblinGoodsInfoVos.stream().map(GoblinGoodsInfoVo::getSpuNo).distinct().collect(Collectors.toList());
    }

    public List<String> getMgtSpuIdsForMarketBySpuNos(List<String> spuNos, Object... shelvesStatus) {
        Query query = Query.query(Criteria.where("spuNo").in(spuNos.toArray())
                .and("marketId").exists(true).and("delFlg").is("0").and("shelvesStatus").in(shelvesStatus));
        query.fields().include("spuId");
        List<GoblinGoodsInfoVo> goblinGoodsInfoVos = mongoTemplate.find(query, GoblinGoodsInfoVo.class, GoblinGoodsInfoVo.class.getSimpleName());
        return CollectionUtils.isEmpty(goblinGoodsInfoVos) ? CollectionUtil.arrayListString() : goblinGoodsInfoVos.stream().map(GoblinGoodsInfoVo::getSpuId).distinct().collect(Collectors.toList());
    }

    // SPU信息
    public List<String> getMgtGoodsSpuIds(String storeId) {
        Query query = Query.query(Criteria.where("storeId").is(storeId).and("delFlg").is("0"));
        query.fields().include("spuId");
        List<GoblinGoodsInfoVo> vos = mongoTemplate.find(query, GoblinGoodsInfoVo.class, GoblinGoodsInfoVo.class.getSimpleName());
        return CollectionUtils.isEmpty(vos) ? CollectionUtil.arrayListString()
                : vos.stream().map(GoblinGoodsInfoVo::getSpuId).collect(Collectors.toList());
    }

    // SPU信息
    public GoblinGoodsInfoVo getGoodsInfoVo(String spuId) {
//        return mongoTemplate.findOne(Query.query(Criteria.where("spuId").is(spuId).and("delFlg").is("0").and("shelvesStatus").is("3")),
//        return mongoTemplate.findOne(Query.query(Criteria.where("spuId").is(spuId).and("delFlg").is("0")),
        return mongoTemplate.findOne(Query.query(Criteria.where("spuId").is(spuId)),
                GoblinGoodsInfoVo.class, GoblinGoodsInfoVo.class.getSimpleName());
    }

    // SPU信息
//    public GoblinGoodsInfoVo getMgtGoodsInfoVo(String spuId) {
//        return mongoTemplate.findOne(Query.query(Criteria.where("spuId").is(spuId).and("delFlg").is("0")),
//                GoblinGoodsInfoVo.class, GoblinGoodsInfoVo.class.getSimpleName());
//    }

    // SPU信息
    public GoblinGoodsInfoVo getMgtGoodsInfoVo(String storeId, String name) {
        return mongoTemplate.findOne(Query.query(Criteria.where("storeId").is(storeId).and("name").is(name).and("delFlg").is("0")),
                GoblinGoodsInfoVo.class, GoblinGoodsInfoVo.class.getSimpleName());
    }

    public long countMgtGoodsInfoVo(String name) {
        return mongoTemplate.count(Query.query(Criteria.where("name").is(name).and("delFlg").is("0")),
                GoblinGoodsInfoVo.class.getSimpleName());
    }

    public long countMgtGoodsSkuInfoVo(String name, int skuType) {
        return mongoTemplate.count(Query.query(Criteria.where("name").is(name).and("delFlg").is("0").and("skuType").is(skuType)),
                GoblinGoodsSkuInfoVo.class.getSimpleName());
    }

    // SPU信息
    public boolean updateGoodsInfoVo(GoblinGoodsInfoVo vo) {
        return mongoTemplate.getCollection(GoblinGoodsInfoVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("spuId").is(vo.getSpuId()).and("delFlg").is("0")).getQueryObject(),
                ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(vo))
        ).getModifiedCount() > 0;
    }

    // SPU活动商品信息更新
    public List<String> updateGoodsInfoVoForMarket(String spuId, String spuNo, GoblinGoodsInfoVo vo) {
        Query query = Query.query(Criteria.where("spuNo").is(spuNo).and("delFlg").is("0").and("spuId").ne(spuId));
        query.fields().include("spuId");
        List<GoblinGoodsInfoVo> marketGoodsInfoVos = mongoTemplate.find(query, GoblinGoodsInfoVo.class, GoblinGoodsInfoVo.class.getSimpleName());
        if (!CollectionUtils.isEmpty(marketGoodsInfoVos)) {
            List<String> marketSpuIds = marketGoodsInfoVos.stream().map(GoblinGoodsInfoVo::getSpuId).collect(Collectors.toList());
            Update update = Update.update("spuNo", vo.getSpuNo())
                    .set("name", vo.getName())
                    .set("subtitle", vo.getSubtitle())
                    .set("sellPrice", vo.getSellPrice())
                    .set("intro", vo.getIntro())
                    .set("details", vo.getDetails())
                    .set("coverPic", vo.getCoverPic())
                    .set("video", vo.getVideo())
                    .set("specMode", "2")
                    .set("cateFid", vo.getCateFid())
                    .set("cateSid", vo.getCateSid())
                    .set("cateTid", vo.getCateTid())
                    .set("shelvesHandle", vo.getShelvesHandle())
                    .set("shelvesTime", vo.getShelvesTime())
                    .set("spuValidity", vo.getSpuValidity())
                    .set("virtualFlg", vo.getVirtualFlg())
                    .set("imageList", mongoConverter.convertToMongoType(vo.getImageList()))
                    .set("logisticsTemplate", vo.getLogisticsTemplate())
                    .set("serviceSupportVoList", mongoConverter.convertToMongoType(vo.getServiceSupportVoList()))
                    .set("updatedBy", vo.getUpdatedBy())
                    .set("updatedAt", mongoConverter.convertToMongoType(vo.getUpdatedAt()));
            if (vo.getTagVoList() != null) {
                update.set("tagVoList", mongoConverter.convertToMongoType(vo.getTagVoList()));
            }
            if (vo.getExtagVoList() != null) {
                update.set("extagVoList", mongoConverter.convertToMongoType(vo.getExtagVoList()));
            }
            if (vo.getArtagVoList() != null) {
                update.set("artagVoList", mongoConverter.convertToMongoType(vo.getArtagVoList()));
            }

            mongoTemplate.getCollection(GoblinGoodsInfoVo.class.getSimpleName()).updateMany(
                    Query.query(Criteria.where("spuId").in(marketSpuIds).and("delFlg").is("0")).getQueryObject(),
                    update.getUpdateObject()
            );
            return marketSpuIds;
        }
        return null;
    }

    // SPU信息
    public boolean updateGoodsInfoVoAppear(String storeId, String spuAppear, LocalDateTime time, String uid) {
        return mongoTemplate.getCollection(GoblinGoodsInfoVo.class.getSimpleName()).updateMany(
                Query.query(Criteria.where("storeId").is(storeId).and("delFlg").is("0")).getQueryObject(),
                Update.update("spuAppear", spuAppear).set("updatedBy", uid).set("updatedAt", mongoConverter.convertToMongoType(time)).getUpdateObject()
        ).getModifiedCount() > 0;
    }

    public boolean updateGoodsInfoVoByShelves(String storeId, List<String> spuIdList, boolean shelvesFlg, String uid, LocalDateTime time) {
        Update update = Update.update("shelvesStatus", shelvesFlg ? "3" : "1").set("shelvesAt", time).set("updatedBy", uid).set("updatedAt", time);
        if (!shelvesFlg) {
            update.set("shelvesHandle", "1");
        }
        return mongoTemplate.updateMulti(Query.query(Criteria.where("storeId").is(storeId).and("spuId").in(spuIdList.toArray())),
                update,
                GoblinGoodsInfoVo.class.getSimpleName()).getModifiedCount() > 0;
    }

    // SKU信息
    public GoblinGoodsSkuInfoVo setGoodsSkuInfoVo(GoblinGoodsSkuInfoVo vo) {
        return mongoTemplate.insert(vo, GoblinGoodsSkuInfoVo.class.getSimpleName());
    }

    public List<GoblinGoodsSkuInfoVo> insertMgtGoodsSkuInfoVos(List<GoblinGoodsSkuInfoVo> vos) {
        return (List<GoblinGoodsSkuInfoVo>) mongoTemplate.insert(vos, GoblinGoodsSkuInfoVo.class.getSimpleName());
    }

    public UpdateResult upsertGoodsSkuInfoVo(GoblinGoodsSkuInfoVo vo) {
        Document document = (Document) mongoConverter.convertToMongoType(vo);
        Update update = Update.fromDocument(document);
        Query query = Query.query(Criteria.where("storeId").is(vo.getStoreId()).and("skuId").is(vo.getSkuId()));
        UpdateResult result = mongoTemplate.upsert(query, update, GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
        return result;
    }

    // SKU信息
    public List<GoblinGoodsSkuInfoVo> setGoodsSkuInfoVos(List<GoblinGoodsSkuInfoVo> vos) {
        return (List<GoblinGoodsSkuInfoVo>) mongoTemplate.insert(vos, GoblinGoodsSkuInfoVo.class.getSimpleName());
    }

    public boolean delGoodsSkuInfoVo(List<String> skuIdList, String operator, LocalDateTime time) {
        Object timeMdbObj = mongoConverter.convertToMongoType(time);
        return mongoTemplate.getCollection(GoblinGoodsSkuInfoVo.class.getSimpleName()).updateMany(
                Query.query(Criteria.where("skuId").in(skuIdList).and("delFlg").is("0")).getQueryObject(),
                Update.update("delFlg", "1").set("updatedBy", operator).set("updatedAt", timeMdbObj)
                        .set("deletedBy", operator).set("deletedAt", timeMdbObj).getUpdateObject()
        ).getModifiedCount() > 0;
    }

    public List<String> delGoodsSkuInfoVoByStoreId(String storeId, String uid, LocalDateTime time) {
        Query query = Query.query(Criteria.where("storeId").is(storeId).and("delFlg").is("0").and("shelvesStatus").is("3"));
        query.fields().include("skuId");
        List<GoblinGoodsSkuInfoVo> storeSkus = mongoTemplate.find(query, GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());

        List<String> storeSkuIdList = CollectionUtil.arrayListString();
        if (!CollectionUtils.isEmpty(storeSkus)) {
            storeSkuIdList = storeSkus.stream().map(GoblinGoodsSkuInfoVo::getSkuId).collect(Collectors.toList());
            UpdateResult updateResult = mongoTemplate.updateMulti(Query.query(Criteria.where("skuId").in(storeSkuIdList)),
                    Update.update("delFlg", "1").set("updatedBy", uid).set("updatedAt", time).set("deletedBy", uid).set("deletedAt", time),
                    GoblinGoodsSkuInfoVo.class.getSimpleName());
            if (updateResult.getModifiedCount() > 0) {
                return storeSkuIdList;
            }
        }
        return storeSkuIdList;
    }

    // SKU搜索
    public PagedResult<GoblinStoreMgtGoodsSkuSimpleVo> getMgtGoodsSkuSimpleVos(GoblinStoreMgtGoodsSkuSimpleFilterParam filterParam) {
        Criteria criteria = Criteria.where("delFlg").is("0").and("storeId").is(filterParam.getStoreId());
//        if (null != filterParam.getSkuType()) {
//            if (0 == filterParam.getSkuType()) {
//                criteria.orOperator(Criteria.where("skuType").exists(false), (Criteria.where("skuType").is(0)));
//            } else {
//                criteria.and("skuType").is(1);
//            }
//        }
//        if (StringUtils.isNotBlank(filterParam.getKeyword())) {
//            Pattern pattern = Pattern.compile("^.*" + filterParam.getKeyword() + ".*$", Pattern.CASE_INSENSITIVE);
//            criteria.orOperator(Criteria.where("name").regex(pattern), Criteria.where("subtitle").regex(pattern));
//        }
        if (null != filterParam.getSkuType()) {
            if (0 == filterParam.getSkuType() && StringUtils.isNotBlank(filterParam.getKeyword())) {
                Pattern pattern = Pattern.compile("^.*" + filterParam.getKeyword() + ".*$", Pattern.CASE_INSENSITIVE);
                criteria.orOperator(
                        Criteria.where("skuType").exists(false).and("name").regex(pattern),
                        Criteria.where("skuType").exists(false).and("subtitle").regex(pattern),
                        Criteria.where("skuType").is(0).and("name").regex(pattern),
                        Criteria.where("skuType").is(0).and("subtitle").regex(pattern)
                );
                filterParam.setKeyword(null);
            } else if (0 == filterParam.getSkuType()) {
                criteria.orOperator(Criteria.where("skuType").exists(false), (Criteria.where("skuType").is(0)));
            }
//            else if (1 == filterParam.getSkuType()) {
//                criteria.and("skuType").is(1);
//            }
            else {
                criteria.and("skuType").is(filterParam.getSkuType());
            }
        }
        if (StringUtils.isNotBlank(filterParam.getKeyword())) {
            Pattern pattern = Pattern.compile("^.*" + filterParam.getKeyword() + ".*$", Pattern.CASE_INSENSITIVE);
            criteria.orOperator(Criteria.where("name").regex(pattern), Criteria.where("subtitle").regex(pattern));
        }
//        if (StringUtils.isNotBlank(filterParam.getShelvesStatus())) {
//            criteria.and("shelvesStatus").is(filterParam.getShelvesStatus());
//        }
        Query query = Query.query(criteria);

        long count = mongoTemplate.count(query, GoblinGoodsSkuInfoVo.class.getSimpleName());

        PagedResult<GoblinStoreMgtGoodsSkuSimpleVo> pagedResult = ObjectUtil.getGoblinStoreMgtGoodsSkuSimpleVoPagedResult();
        if (count <= 0) return pagedResult;

        int pageSize = 20;
        query.with(PageRequest.of(filterParam.getPageNum() - 1, pageSize));
        query.with(Sort.by(Sort.Order.desc("createdAt")));

        List<GoblinStoreMgtGoodsSkuSimpleVo> list = mongoTemplate.find(query, GoblinStoreMgtGoodsSkuSimpleVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());

        return pagedResult.setList(list).setTotal(count, pageSize);
    }

    // 根据sku条码获取skuNo
    public List<String> existGoodsSkuNoBySkuNoList(String storeId, List<String> skuNoList) {
        Query query = Query.query(Criteria.where("delFlg").is("0").and("storeId").is(storeId).and("skuNo").in(skuNoList));
        query.fields().include("skuNo");
        List<GoblinGoodsSkuInfoVo> vos = mongoTemplate.find(query, GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
        return CollectionUtils.isEmpty(vos) ? null : vos.stream().map(GoblinGoodsSkuInfoVo::getSkuNo).collect(Collectors.toList());
//        return mongoTemplate.count(query, GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
    }

    // SKU信息
    public GoblinGoodsSkuInfoVo getGoodsSkuInfoVo(String skuId) {
//        return mongoTemplate.findOne(Query.query(Criteria.where("skuId").is(skuId).and("delFlg").is("0").and("shelvesStatus").is("3")),
//        return mongoTemplate.findOne(Query.query(Criteria.where("skuId").is(skuId).and("delFlg").is("0")),
        return mongoTemplate.findOne(Query.query(Criteria.where("skuId").is(skuId)),
                GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
    }

    public List<GoblinGoodsSkuInfoVo> getGoodsSkuInfoVos(List<String> skuIds) {
        return mongoTemplate.find(Query.query(Criteria.where("skuId").in(skuIds)),
                GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
    }

    // SKU信息
    public List<String> getMgtGoodsSkuIds(String storeId, List<String> spuIdList) {
        Query query = Query.query(Criteria.where("storeId").is(storeId).and("delFlg").is("0").and("spuId").in(spuIdList.toArray()));
        query.fields().include("skuId");
        List<GoblinGoodsSkuInfoVo> vos = mongoTemplate.find(query, GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
        return CollectionUtils.isEmpty(vos) ? CollectionUtil.arrayListString()
                : vos.stream().map(GoblinGoodsSkuInfoVo::getSkuId).collect(Collectors.toList());
    }

    // SKU信息
//    public GoblinGoodsSkuInfoVo getMgtGoodsSkuInfoVo(String skuId) {
//        return mongoTemplate.findOne(Query.query(Criteria.where("skuId").is(skuId).and("delFlg").is("0")),
//                GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
//    }

    // SKU信息
    public boolean updateGoodsSkuInfoVo(GoblinGoodsSkuInfoVo vo) {
        return mongoTemplate.getCollection(GoblinGoodsSkuInfoVo.class.getSimpleName())
                .updateOne(
                        Query.query(Criteria.where("skuId").is(vo.getSkuId()).and("delFlg").is("0")).getQueryObject(),
                        ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(vo))
                ).getModifiedCount() > 0;
    }

    // SKU活动商品信息更新
    public boolean updateGoodsSkuInfoVoForMarket(List<String> skuIds, GoblinGoodsSkuInfoVo vo) {
        return mongoTemplate.getCollection(GoblinGoodsSkuInfoVo.class.getSimpleName()).updateMany(
                Query.query(Criteria.where("skuId").in(skuIds).and("delFlg").is("0")).getQueryObject(),
                Update.update("name", vo.getName())
                        .set("skuBarCode", vo.getSkuBarCode())
                        .set("skuPic", vo.getSkuPic())
                        .set("skuSpecList", mongoConverter.convertToMongoType(vo.getSkuSpecList()))
                        .set("sellPrice", vo.getSellPrice())
//                        .set("price", vo.getPrice())
//                        .set("priceMember", vo.getPriceMember())
                        .set("weight", vo.getWeight())
                        .set("stock", vo.getStock())
//                        .set("skuStock", vo.getSkuStock())
                        .set("warningStock", vo.getWarningStock())
                        .set("skuAppear", vo.getSkuAppear())
                        .set("skuIsbn", vo.getSkuIsbn())
//                        .set("buyFactor", vo.getBuyFactor())
//                        .set("buyRoster", vo.getBuyRoster())
//                        .set("buyLimit", vo.getBuyLimit())
                        .set("skuValidity", vo.getSkuValidity())
                        .set("updatedBy", vo.getUpdatedBy())
                        .set("updatedAt", mongoConverter.convertToMongoType(vo.getUpdatedAt()))
                        .getUpdateObject()
        ).getModifiedCount() > 0;
    }

    public boolean updateGoodsSkuInfoVoBySpuId(GoblinGoodsSkuInfoVo vo) {
        return mongoTemplate.getCollection(GoblinGoodsSkuInfoVo.class.getSimpleName()).updateMany(
                Query.query(Criteria.where("spuId").is(vo.getSpuId()).and("delFlg").is("0")).getQueryObject(),
                ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(vo))
        ).getModifiedCount() > 0;
    }

    public boolean updateGoodsSkuInfoVoPropBySpuId(GoblinGoodsSkuInfoVo vo) {
        return mongoTemplate.getCollection(GoblinGoodsSkuInfoVo.class.getSimpleName()).updateMany(
                Query.query(Criteria.where("spuId").is(vo.getSpuId()).and("delFlg").is("0")).getQueryObject(),
                Update.update("skuNo", vo.getSkuNo())
                        .set("virtualFlg", vo.getVirtualFlg())
                        .set("logisticsTemplate", vo.getLogisticsTemplate())
                        .set("updatedBy", vo.getUpdatedBy())
                        .set("updatedAt", mongoConverter.convertToMongoType(vo.getUpdatedAt())).getUpdateObject()
        ).getModifiedCount() > 0;
    }

    public boolean updateGoodsSkuInfoVoByShelves(String storeId, List<String> spuIdList, boolean shelvesFlg, String uid, LocalDateTime time) {
        return mongoTemplate.updateMulti(Query.query(Criteria.where("storeId").is(storeId).and("delFlg").is("0").and("spuId").in(spuIdList.toArray())),
                Update.update("shelvesStatus", shelvesFlg ? "3" : "1").set("shelvesAt", time).set("updatedBy", uid).set("updatedAt", time),
                GoblinGoodsSkuInfoVo.class.getSimpleName()).getModifiedCount() > 0;
    }

    public boolean updateGoodsSkuInfoVoByShelvesSku(String storeId, List<String> skuIdList, boolean shelvesFlg, String uid, LocalDateTime time) {
        return mongoTemplate.updateMulti(Query.query(Criteria.where("storeId").is(storeId).and("delFlg").is("0").and("skuId").in(skuIdList)),
                Update.update("shelvesStatus", shelvesFlg ? "3" : "1").set("shelvesAt", time).set("updatedBy", uid).set("updatedAt", time),
                GoblinGoodsSkuInfoVo.class.getSimpleName()).getModifiedCount() > 0;
    }

    public boolean updateGoodsSkuInfoVoBySoldoutSku(String storeId, List<String> skuIdList, String soldoutStatus, String uid, LocalDateTime time) {
        return mongoTemplate.updateMulti(Query.query(Criteria.where("storeId").is(storeId).and("delFlg").is("0").and("skuId").in(skuIdList)),
                Update.update("soldoutStatus", soldoutStatus).set("updatedBy", uid).set("updatedAt", time),
                GoblinGoodsSkuInfoVo.class.getSimpleName()).getModifiedCount() > 0;
    }

    public boolean updateGoodsSkuInfoVoForArUrl(String skuId, String uid, LocalDateTime now, String arUrlIos, String arUrlAndroid, boolean editFlg) {
        return mongoTemplate.updateMulti(Query.query(Criteria.where("skuId").is(skuId).and("delFlg").is("0").and("arUrlIos").exists(editFlg)),
                Update.update("updatedBy", uid).set("updatedAt", now).set("arUrlIos", arUrlIos).set("arUrlAndroid", arUrlAndroid),
                GoblinGoodsSkuInfoVo.class.getSimpleName()).getModifiedCount() > 0;
    }

    public boolean updateGoodsSkuInfoVoDelArUrl(String uid, LocalDateTime now, List<String> skuIds) {
        return mongoTemplate.updateMulti(Query.query(Criteria.where("skuId").in(skuIds).and("delFlg").is("0").and("arUrlIos").exists(true)),
                Update.update("updatedBy", uid).set("updatedAt", now).unset("arUrlIos").unset("arUrlAndroid"),
                GoblinGoodsSkuInfoVo.class.getSimpleName()).getModifiedCount() > 0;
    }

    /* ----------------------------------------  ---------------------------------------- */

    /**
     * 添加 商铺活动 mongo
     *
     * @param data
     * @return
     */
    public GoblinStoreMarketVo insertStoreMarket(GoblinStoreMarketVo data) {
        return mongoTemplate.insert(data, GoblinStoreMarketVo.class.getSimpleName());
    }

    /**
     * 修改 商铺活动 mongo
     *
     * @param marketId
     * @param data
     * @return
     */
    public UpdateResult updateStoreMarket(String marketId, String storeId, GoblinStoreMarketVo data) {
        BasicDBObject object = ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(data));
        return mongoTemplate.getCollection(GoblinStoreMarketVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("storeMarketId").is(marketId).and("storeId").is(storeId)).getQueryObject(),
                object);
    }

    /**
     * 获取 商铺活动 mongo
     *
     * @param marketId
     * @return
     */
    public GoblinStoreMarketVo getStoreMarket(String marketId) {
        return mongoTemplate.findOne(Query.query(Criteria.where("storeMarketId").is(marketId)), GoblinStoreMarketVo.class, GoblinStoreMarketVo.class.getSimpleName());
    }

    /**
     * 删除 商铺活动 mongo
     *
     * @param marketId
     * @param storeId
     * @return
     */
    public DeleteResult delStoreMarket(String marketId, String storeId) {
        return mongoTemplate.remove(Query.query(Criteria.where("storeMarketId").is(marketId).and("storeId").is(storeId)), GoblinStoreMarketVo.class.getSimpleName());
    }


    /**
     * 获取 商铺活动列表
     *
     * @param page
     * @param purchaseName
     * @param status
     * @param st
     * @param et
     * @param ct
     * @return
     */
    public HashMap<String, Object> getStoreMarketList(int page, String purchaseName, int status, String st, String et, String ct) {
        String nowStr = DateUtil.getNowTime();
        int size = 40;
        HashMap<String, Object> info = CollectionUtil.mapStringObject();
        // 排序 分页
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createdAt"));
        //条件
        Criteria criteria = new Criteria();
        if (purchaseName != null) {
            criteria = criteria.and("name").regex(".*?\\" + purchaseName);
        }
        if (st != null && et != null) {
            criteria = criteria.and("endTime").lte(et).and("startTime").gte(st);
        }
        if (ct != null) {
            criteria = criteria.and("createdAt").regex(".*?\\" + ct);
        }

        switch (status) {
            case 0:
                criteria = criteria.and("startTime").gte(nowStr);
                break;
            case 1:
                criteria = criteria.and("endTime").gte(nowStr).and("startTime").lte(nowStr);
                break;
            case 2:
                criteria = criteria.and("endTime").lte(nowStr);
                break;
            case 7:
                criteria = criteria.and("status").lte(7);
                break;
        }
        Query query = Query.query(criteria);
        // 查询总数
        long count = mongoTemplate.count(query, GoblinStoreMarketVo.class, GoblinStoreMarketVo.class.getSimpleName());
        query.with(pageable);
        List<GoblinStoreMarketVo> voList = mongoTemplate.find(query, GoblinStoreMarketVo.class, GoblinStoreMarketVo.class.getSimpleName());
        info.put("total", count);
        info.put("data", voList);
        return info;
    }

    //获取全部正在下单的活动
    /* ---------------------------------------- 官方营销数据源 ---------------------------------------- */

    public List<GoblinSelfMarketingVo> getSelfMarketingByPerformanceId(String performanceId) {
        Query query = Query.query(Criteria.where("performanceId").is(performanceId).and("status").ne(7));
        return mongoTemplate.find(query, GoblinSelfMarketingVo.class, GoblinSelfMarketingVo.class.getSimpleName());
    }

    public List<GoblinSelfMarketingVo> getGoblinSelfMarketingVoList() {
        String nowStr = DateUtil.getNowTime();
        List<GoblinSelfMarketingVo> voList = mongoTemplate.find(Query.query(Criteria.where("type").is(2).and("status").ne(7).and("endTime").gte(nowStr).and("startTime").lte(nowStr)), GoblinSelfMarketingVo.class, GoblinSelfMarketingVo.class.getSimpleName());
        return voList;
    }

    //添加 订单vo全量
    public GoblinStoreOrderVo insertGoblinStoreOrderVo(GoblinStoreOrderVo vo) {
        return mongoTemplate.insert(vo, GoblinStoreOrderVo.class.getSimpleName());
    }

    public GoblinStoreOrderVo getGoblinStoreOrderVoByCode(String orderCode) {
        return mongoTemplate.findOne(Query.query(Criteria.where("orderCode").is(orderCode)), GoblinStoreOrderVo.class, GoblinStoreOrderVo.class.getSimpleName());
    }

    public UpdateResult updateGoblinStoreOrderVo(String orderId, GoblinStoreOrderVo data) {
        BasicDBObject object = ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(data));
        return mongoTemplate.getCollection(GoblinStoreOrderVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("orderId").is(orderId)).getQueryObject(),
                object);
    }

    public GoblinStoreOrderVo getGoblinStoreOrderVoByOrderId(String orderId) {
        if (orderId == null || orderId.trim().isEmpty()) {
            return null;
        }
        return mongoTemplate.findOne(Query.query(Criteria.where("orderId").is(orderId)),
                GoblinStoreOrderVo.class, GoblinStoreOrderVo.class.getSimpleName());
    }

    public GoblinOrderSkuVo getGoblinOrderSkuVoByOrderSkuId(String orderSkuId) {
        if (orderSkuId == null || orderSkuId.trim().isEmpty()) {
            return null;
        }
        return mongoTemplate.findOne(Query.query(Criteria.where("orderSkuId").is(orderSkuId)),
                GoblinOrderSkuVo.class, GoblinOrderSkuVo.class.getSimpleName());
    }

    //添加 订单SkuVo全量
    public GoblinOrderSkuVo insertGoblinOrderSkuVo(GoblinOrderSkuVo vo) {
        return mongoTemplate.insert(vo, GoblinOrderSkuVo.class.getSimpleName());
    }

    public UpdateResult updateGoblinOrderSkuVo(String orderSkuId, GoblinOrderSkuVo data) {
        BasicDBObject object = ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(data));
        return mongoTemplate.getCollection(GoblinOrderSkuVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("orderSkuId").is(orderSkuId)).getQueryObject(),
                object);
    }

    //添加 订单SkuVo全量
    public GoblinMailVo insertGoblinMailVo(GoblinMailVo vo) {
        return mongoTemplate.insert(vo, GoblinMailVo.class.getSimpleName());
    }

    public UpdateResult updateGoblinMailVo(String mailId, GoblinMailVo data) {
        BasicDBObject object = ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(data));
        return mongoTemplate.getCollection(GoblinMailVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("mailId").is(mailId)).getQueryObject(),
                object);
    }

    //添加 操作日志
    public GoblinOrderLogVo insertGoblinOrderLogVo(GoblinOrderLogVo vo) {
        return mongoTemplate.insert(vo, GoblinOrderLogVo.class.getSimpleName());
    }

    //添加 订单退款数据
    public GoblinBackOrderVo insertGoblinBackOrderVo(GoblinBackOrderVo vo) {
        return mongoTemplate.insert(vo, GoblinBackOrderVo.class.getSimpleName());
    }

    //修改 订单退款数据
    public UpdateResult updateGoblinBackOrderVo(String backOrderId, GoblinBackOrderVo data) {
        BasicDBObject object = ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(data));
        return mongoTemplate.getCollection(GoblinBackOrderVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("backOrderId").is(backOrderId)).getQueryObject(),
                object);
    }

    //获取 订单退款数据根据orderCode
    public GoblinBackOrderVo getGoblinBackOrderVoByBackCode(String backCode) {
        return mongoTemplate.findOne(Query.query(Criteria.where("backCode").is(backCode)), GoblinBackOrderVo.class, GoblinBackOrderVo.class.getSimpleName());
    }

    //获取 正在下单活动内容列表
    public List<GoblinGoodsInfoVo> marketSpuList(String marketId, String storeId, int start, int skip) {
        List<GoblinGoodsInfoVo> list = mongoTemplate.find(Query.query(Criteria.where("storeId").is(storeId).and("marketId").is("ZZ" + marketId).and("delFlg").is("0").and("shelvesStatus").is("3")).with(Sort.by(Sort.Order.desc("createdAt"))).skip(start).limit(skip), GoblinGoodsInfoVo.class, GoblinGoodsInfoVo.class.getSimpleName());
        return list;
    }

    //店铺总收入
    public String storeMoney(String storeId, String spuId, String st, String et) {
        String spuName = "店铺总收入";
        Criteria criteria = Criteria.where("status").in(GoblinStatusConst.Status.ORDER_LOG_STATUS_11.getValue(), GoblinStatusConst.Status.ORDER_LOG_STATUS_22.getValue(), GoblinStatusConst.Status.ORDER_LOG_STATUS_28.getValue()).and("storeId").is(storeId);
        if (st != null && et != null) {
            LocalDateTime stDateTime = LocalDateTime.parse(st, DTF_YMD_HMS);
            LocalDateTime etDateTime = LocalDateTime.parse(et, DTF_YMD_HMS);
            criteria = criteria.and("createdAt").gte(stDateTime).lt(etDateTime);
        }
        Aggregation aggregation;
        if (spuId != null) {
            criteria = criteria.and("spuId").is(spuId);
            Query query = Query.query(Criteria.where("spuId").is(spuId));
            query.fields().include("name");
            GoblinGoodsInfoVo spuIdAndName = mongoTemplate.findOne(query, GoblinGoodsInfoVo.class, GoblinGoodsInfoVo.class.getSimpleName());
            if (spuIdAndName == null) {
                return "," + BigDecimal.ZERO;
            } else {
                spuName = spuIdAndName.getName();
            }
            aggregation = Aggregation.newAggregation(
                    Aggregation.match(criteria),
                    Aggregation.group("spuId")
                            .first("spuId").as("spuId")
                            .sum("skuPriceActual").as("skuPriceActual"));
//            aggregation = Aggregation.newAggregation(
//                    Aggregation.match(criteria),
//                    Aggregation.project("spuId", "skuPriceActual"),
//                    Aggregation.group("spuId")
//                            .first("spuId").as("spuId")
//                            .sum("skuPriceActual").as("skuPriceActual")
//            );
        } else {
            aggregation = Aggregation.newAggregation(
                    Aggregation.match(criteria),
                    Aggregation.group("storeId")
                            .first("storeId").as("storeId")
                            .sum("skuPriceActual").as("skuPriceActual"));
        }
        AggregationResults<GoblinOrderLogVo> outputType = mongoTemplate.aggregate(aggregation, GoblinOrderLogVo.class.getSimpleName(), GoblinOrderLogVo.class);
        List<GoblinOrderLogVo> dataList = new ArrayList(outputType.getMappedResults());
        if (dataList.size() > 0) {
            return spuName + "," + dataList.get(0).getSkuPriceActualBig();
        } else {
            return "," + BigDecimal.ZERO;
        }
    }


    //资金列表
    public HashMap<String, Object> moneyGetSpuList(String spuName, String st, String et, String storeId, int page) {
        //查询销量
        int size = 20;
        int skipCount = ((page - 1) * size);
        int finalCount = skipCount + size;
        List<GoblinGoodsInfoVo> spuIdAndName = null;
        Criteria criteria = Criteria.where("status").in(GoblinStatusConst.Status.ORDER_LOG_STATUS_11.getValue(), GoblinStatusConst.Status.ORDER_LOG_STATUS_22.getValue(), GoblinStatusConst.Status.ORDER_LOG_STATUS_28.getValue()).and("storeId").is(storeId);
        Criteria criteriaCount = Criteria.where("status").in(GoblinStatusConst.Status.ORDER_LOG_STATUS_11.getValue(), GoblinStatusConst.Status.ORDER_LOG_STATUS_22.getValue(), GoblinStatusConst.Status.ORDER_LOG_STATUS_28.getValue()).and("storeId").is(storeId);
        if (st != null && et != null) {
            LocalDateTime stDateTime = LocalDateTime.parse(st, DTF_YMD_HMS);
            LocalDateTime etDateTime = LocalDateTime.parse(et, DTF_YMD_HMS);
            criteria = criteria.and("createdAt").gte(stDateTime).lt(etDateTime);
            criteriaCount = criteriaCount.and("createdAt").gte(stDateTime).lt(etDateTime);
        }
        if (spuName != null) {
            Query q1 = Query.query(Criteria.where("name").regex(".*" + spuName + ".*"));
            q1.fields().include("spuId");
            List<String> spuIds = mongoTemplate.find(q1, GoblinGoodsInfoVo.class, GoblinGoodsInfoVo.class.getSimpleName()).stream().map(GoblinGoodsInfoVo::getSpuId).collect(Collectors.toList());
            criteriaCount = criteriaCount.and("spuId").in(spuIds);
        }
        //查询总数量

        Query countQuery = Query.query(criteriaCount).with(Sort.by(Sort.Order.desc("createdAt")));
        countQuery.fields().include("spuId").include("spuName");
        List<GoblinOrderLogVo> countList = mongoTemplate.find(countQuery, GoblinOrderLogVo.class, GoblinOrderLogVo.class.getSimpleName());
        List<String> spuIdList = countList.stream().map(GoblinOrderLogVo::getSpuId).distinct().collect(Collectors.toList());
        long total = spuIdList.size();
        if (finalCount > total) {
            finalCount = (int) total;
        }
        if (finalCount > 0) {
            spuIdList = spuIdList.subList(skipCount, finalCount);
        }
        criteria = criteria.and("spuId").in(spuIdList);

        //查询聚合数据
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.project("spuId", "skuPriceActual", "orderType", "spuName"),
                Aggregation.group("spuId")
                        .first("spuId").as("spuId")
//                        .first("spuName").as("spuName")
                        .first("orderType").as("orderType")
                        .sum("skuPriceActual").as("skuPriceActual"),
                Aggregation.sort(Sort.by(Sort.Order.desc("spuId")))
        );
        AggregationResults<GoblinOrderLogVo> outputType = mongoTemplate.aggregate(aggregation, GoblinOrderLogVo.class.getSimpleName(), GoblinOrderLogVo.class);
        List<GoblinOrderLogVo> dataList = new ArrayList(outputType.getMappedResults());
        if (spuIdAndName == null) {
            Query query = Query.query(Criteria.where("spuId").in(dataList.stream().map(GoblinOrderLogVo::getSpuId).collect(Collectors.toList())));
            query.fields().include("spuId").include("name");
            spuIdAndName = mongoTemplate.find(query, GoblinGoodsInfoVo.class, GoblinGoodsInfoVo.class.getSimpleName());
        }
        //处理数据
        for (GoblinOrderLogVo item : dataList) {
            for (GoblinGoodsInfoVo item2 : spuIdAndName) {
                if (item.getSpuId().equals(item2.getSpuId())) {
                    item.setSpuName(item2.getName());
                    break;
                }
            }
        }
        HashMap<String, Object> map = CollectionUtil.mapStringObject();
        map.put("data", dataList);
        map.put("total", total);
        return map;
    }

    //商品订单操作日志列表
    public HashMap<String, Object> moneyGetSpuDetails(String spuId, String orderCode, Integer type, String st, String et, int page) {
        //查询销量
        int size = 20;
        int skipCount = ((page - 1) * size);
        Criteria criteria = Criteria.where("spuId").is(spuId);
        if (st != null && et != null) {
            LocalDateTime stDateTime = LocalDateTime.parse(st, DTF_YMD_HMS);
            LocalDateTime etDateTime = LocalDateTime.parse(et, DTF_YMD_HMS);
            criteria = criteria.and("createdAt").gte(stDateTime).lt(etDateTime);
        }
        if (orderCode != null) {
            criteria = criteria.and("orderCode").is(orderCode);
        }
        if (type != null) {
            switch (type) {
                case 1:
                    criteria = criteria.and("orderType").is("order").and("status").is(11);
                    break;
                case 2:
                    criteria = criteria.and("orderType").is("order").and("status").in(22, 28);
                    break;
                case 3:
                    criteria = criteria.and("orderType").is("zhengzai").and("status").is(11);
                    break;
                case 4:
                    criteria = criteria.and("orderType").is("zhengzai").and("status").in(22, 28);
                    break;
            }
        } else {
            criteria = criteria.and("status").in(
                    GoblinStatusConst.Status.ORDER_LOG_STATUS_11.getValue(),
                    GoblinStatusConst.Status.ORDER_LOG_STATUS_22.getValue(),
                    GoblinStatusConst.Status.ORDER_LOG_STATUS_28.getValue()
            );
        }
        Query query = Query.query(criteria);
        query.skip(skipCount).limit(size).with(Sort.by(Sort.Order.desc("createdAt")));
        List<GoblinOrderLogVo> dataList = mongoTemplate.find(query, GoblinOrderLogVo.class, GoblinOrderLogVo.class.getSimpleName());
        //查询总数量
        Query countQuery = Query.query(criteria);
        countQuery.fields().include("spuId");
        List<GoblinOrderLogVo> countList = mongoTemplate.find(countQuery, GoblinOrderLogVo.class, GoblinOrderLogVo.class.getSimpleName());
        long total = countList.size();
        HashMap<String, Object> map = CollectionUtil.mapStringObject();
        map.put("data", dataList);
        map.put("total", total);
        return map;
    }

    //商品订单列表
    public HashMap<String, Object> storeOrderList(String storeId, Integer page, String orderCode, String cst, String cet, String expressContacts, String phone, Integer status) {
        //查询销量
        int size = 20;
        int skipCount = ((page - 1) * size);
        Criteria criteria = Criteria.where("storeId").is(storeId);
        if (cst != null && cet != null) {
            criteria = criteria.and("createdAt").gte(cst).lt(cet);
        }
        if (orderCode != null) {
            criteria = criteria.and("orderCode").is(orderCode);
        }
        if (phone != null) {
            criteria = criteria.and("userMobile").is(phone);
        }
        if (status != null) {
            criteria = criteria.and("status").is(status);
        }
        if (expressContacts != null) {
            criteria = criteria.and("orderAttrVo.expressContacts").is(expressContacts);
        }
        Query query = Query.query(criteria);
        query.with(Sort.by(Sort.Order.desc("createdAt")));
        query.skip(skipCount).limit(size);
        query.fields().include("orderCode").include("createdAt").include("payType").include("status").include("orderSkuVoIds").include("orderId").include("priceActual").include("priceExpress").include("marketId")
                .include("orderAttrVo.expressContacts").include("orderAttrVo.expressAddressDetail").include("orderAttrVo.expressAddress").include("orderAttrVo.expressPhone");
        List<GoblinStoreOrderVo> dataList = mongoTemplate.find(query, GoblinStoreOrderVo.class, GoblinStoreOrderVo.class.getSimpleName());
        //查询总数量
        Query countQuery = Query.query(criteria);
        countQuery.fields().include("orderCode");
        List<GoblinStoreOrderVo> countList = mongoTemplate.find(countQuery, GoblinStoreOrderVo.class, GoblinStoreOrderVo.class.getSimpleName());
        long total = countList.size();
        HashMap<String, Object> map = CollectionUtil.mapStringObject();
        map.put("data", dataList);
        map.put("total", total);
        return map;
    }

    //商品退款订单列表
    public HashMap<String, Object> storeBackOrderList(String storeId, Integer page, String orderBackCode, Integer type, String cst, String cet, String orderCode, String spuName, Integer status) {
        //查询销量
        int size = 20;
        int skipCount = ((page - 1) * size);
        Criteria criteria = Criteria.where("storeId").is(storeId);
        if (cst != null && cet != null) {
            criteria = criteria.and("createdAt").gte(cst).lt(cet);
        }
        if (orderCode != null) {
            criteria = criteria.and("orderCode").is(orderCode);
        }
        if (orderBackCode != null) {
            criteria = criteria.and("backCode").is(orderBackCode);
        }
        if (status != null) {
            criteria = criteria.and("status").is(status);
        }
        if (type != null) {
            criteria = criteria.and("type").is(type);
        }
        if (spuName != null) {
            criteria = criteria.and("backOrderSkuVos.spuName").regex(".*?\\" + spuName);
        }
        Query query = Query.query(criteria);
        query.skip(skipCount).limit(size).with(Sort.by(Sort.Order.desc("createdAt")));
        ;
        query.fields().include("backCode").include("orderCode").include("backOrderId").include("type").include("status").include("realBackPrice").include("createdAt")
                .include("backOrderSkuVos.spuName").include("backOrderSkuVos.skuName").include("backOrderSkuVos.spuPic").include("backOrderSkuVos.skuPic")
                .include("backOrderSkuVos.skuSpecs").include("backOrderSkuVos.skuId").include("backOrderSkuVos.spuId").include("backOrderSkuVos.orderSkuId")
                .include("backOrderSkuVos.refundPrice");
        List<GoblinBackOrderVo> dataList = mongoTemplate.find(query, GoblinBackOrderVo.class, GoblinBackOrderVo.class.getSimpleName());
        //查询总数量
        Query countQuery = Query.query(criteria);
        countQuery.fields().include("orderCode");
        List<GoblinBackOrderVo> countList = mongoTemplate.find(countQuery, GoblinBackOrderVo.class, GoblinBackOrderVo.class.getSimpleName());
        long total = countList.size();
        HashMap<String, Object> map = CollectionUtil.mapStringObject();
        map.put("data", dataList);
        map.put("total", total);
        return map;
    }

    //商户 正在下单列表
    public List<GoblinStoreOrderVo> storeZhengzaiOrderList(int page, String storeId) {
        //查询销量
        int size = 40;
        int skipCount = ((page - 1) * size);
        Criteria criteria = Criteria.where("storeId").is(storeId).and("marketType").is(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue());
        Query query = Query.query(criteria);
        query.skip(skipCount).limit(size).with(Sort.by(Sort.Order.desc("createdAt")));
        return mongoTemplate.find(query, GoblinStoreOrderVo.class, GoblinStoreOrderVo.class.getSimpleName());
    }

    public List<GoblinFrontBanner> getListBanner() {
        Query query = Query.query(Criteria.where("delTag").is(0).and("bannerType").is(1));
        return mongoTemplate.find(query,
                GoblinFrontBanner.class, GoblinFrontBanner.class.getSimpleName());
    }

    public List<GoblinFrontBanner> getMiddleBanner() {
        Query query = Query.query(Criteria.where("delTag").is(0).and("bannerType").is(2));
        return mongoTemplate.find(query,
                GoblinFrontBanner.class, GoblinFrontBanner.class.getSimpleName());
    }

    public List<GoblinFrontHotWord> getHotWord() {
        Query query = Query.query(Criteria.where("delTag").is(0));
        return mongoTemplate.find(query,
                GoblinFrontHotWord.class, GoblinFrontHotWord.class.getSimpleName());
    }

    public List<GoblinFrontNavigation> getNavigation() {
        Query query = Query.query(Criteria.where("delTag").is(0));
        query.with(Sort.by(Sort.Order.asc("indexs")));
        return mongoTemplate.find(query,
                GoblinFrontNavigation.class, GoblinFrontNavigation.class.getSimpleName());
    }

    /* ---------------------------------------- 商铺活动:优惠券 ---------------------------------------- */

    public GoblinStoreCouponBasicVo setMgtStoreCouponBasicVo(GoblinStoreCouponBasicVo vo) {
        return mongoTemplate.insert(vo, GoblinStoreCouponBasicVo.class.getSimpleName());
    }

    public boolean updateMgtStoreCouponBasicVo(GoblinStoreCouponBasicVo vo) {
        return mongoTemplate.getCollection(GoblinStoreCouponBasicVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("storeCouponId").is(vo.getStoreCouponId()).and("delFlg").is("0")).getQueryObject(),
                ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(vo))
        ).getModifiedCount() > 0;
    }

    public boolean activityMgtStoreCouponBasicVo(String uid, LocalDateTime time, String state, List<String> storeCouponIds) {
        return mongoTemplate.getCollection(GoblinStoreCouponBasicVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("storeCouponId").in(storeCouponIds).and("delFlg").is("0")).getQueryObject(),
                Update.update("state", state).set("updatedBy", uid).set("updatedAt", mongoConverter.convertToMongoType(time)).getUpdateObject()
        ).getModifiedCount() > 0;
    }

    public boolean updateMgtStoreCouponStock(String storeCouponId, int stock, String uid, LocalDateTime time) {
        return mongoTemplate.getCollection(GoblinStoreCouponBasicVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("storeCouponId").is(storeCouponId).and("delFlg").is("0")).getQueryObject(),
                Update.update("stock", stock).set("updatedBy", uid).set("updatedAt", mongoConverter.convertToMongoType(time)).getUpdateObject()
        ).getModifiedCount() > 0;
    }

    public boolean delMgtStoreCouponBasicVo(String storeCouponId, String uid, LocalDateTime time) {
        return mongoTemplate.updateFirst(
                Query.query(Criteria.where("storeCouponId").is(storeCouponId).and("delFlg").is("0")),
                Update.update("delFlg", "1").set("deletedBy", uid).set("deletedAt", time),
                GoblinStoreCouponBasicVo.class.getSimpleName()
        ).getModifiedCount() > 0;
    }

    public boolean delMgtStoreCouponBasicVos(List<String> storeCouponIds, String uid, LocalDateTime time) {
        return mongoTemplate.updateFirst(
                Query.query(Criteria.where("storeCouponId").in(storeCouponIds).and("delFlg").is("0")),
                Update.update("delFlg", "1").set("deletedBy", uid).set("deletedAt", time),
                GoblinStoreCouponBasicVo.class.getSimpleName()
        ).getModifiedCount() > 0;
    }

    public GoblinStoreCouponBasicVo getMgtStoreCouponBasicVo(String storeCouponId) {
        return mongoTemplate.findOne(
                Query.query(Criteria.where("storeCouponId").is(storeCouponId).and("delFlg").is("0")),
                GoblinStoreCouponBasicVo.class, GoblinStoreCouponBasicVo.class.getSimpleName()
        );
    }

    public GoblinStoreCouponVo getStoreCouponVo(String storeCouponId) {
        return mongoTemplate.findOne(
                Query.query(Criteria.where("storeCouponId").is(storeCouponId).and("delFlg").is("0")),
                GoblinStoreCouponVo.class, GoblinStoreCouponBasicVo.class.getSimpleName()
        );
    }

    public PagedResult<GoblinStoreMgtCouponListVo> getMgtStoreCouponListVos(GoblinStoreMgtCouponFilterParam filterParam) {
        Criteria criteria = Criteria.where("delFlg").is("0").and("storeId").is(filterParam.getStoreId());
        if (StringUtils.isNotBlank(filterParam.getKeyword())) {
            Pattern pattern = Pattern.compile("^.*" + filterParam.getKeyword() + ".*$", Pattern.CASE_INSENSITIVE);
            criteria.and("title").regex(pattern);
        }
        if (StringUtils.isNotBlank(filterParam.getStoreCouponNo())) {
            criteria.and("storeCouponNo").is(filterParam.getStoreCouponNo());
        }
        if (StringUtils.isNotBlank(filterParam.getState())) {
            criteria.and("state").is(filterParam.getState());
        }
        if (StringUtils.isNotBlank(filterParam.getStartTime())) {
            LocalDateTime startTime = DateUtil.Formatter.yyyyMMddHHmmss.parse(filterParam.getStartTime());
            LocalDateTime startTimeBegin = startTime.withHour(0).withMinute(0).withSecond(0).withNano(0);

            criteria.and("startTime").gte(startTimeBegin);
        }
        if (StringUtils.isNotBlank(filterParam.getEndTime())) {
            LocalDateTime endTime = DateUtil.Formatter.yyyyMMddHHmmss.parse(filterParam.getEndTime());
            LocalDateTime endTimeEnd = endTime.withHour(23).withMinute(59).withSecond(59).withNano(999);

            criteria.and("endTime").lte(endTimeEnd);
        }
        if (StringUtils.isNotBlank(filterParam.getCreatedDt())) {
            LocalDateTime createdAtBegin = DateUtil.Formatter.yyyyMMddHHmmss.parse(filterParam.getCreatedDt() + " 00:00:00");
            LocalDateTime createdAtEnd = createdAtBegin.withHour(23).withMinute(59).withSecond(59).withNano(999);

            criteria.and("createdAt").gte(createdAtBegin).lte(createdAtEnd);
        }
        Query query = Query.query(criteria);

        long count = mongoTemplate.count(query, GoblinStoreCouponBasicVo.class.getSimpleName());

        PagedResult<GoblinStoreMgtCouponListVo> pagedResult = ObjectUtil.getGoblinStoreMgtCouponListVoPagedResult();
        if (count <= 0) return pagedResult;

        query.with(PageRequest.of(filterParam.getPageNum() - 1, filterParam.getPageSize()));
        query.with(Sort.by(Sort.Order.desc("createdAt")));

        List<GoblinStoreMgtCouponListVo> mgtCouponListVos = mongoTemplate.find(query, GoblinStoreMgtCouponListVo.class, GoblinStoreCouponBasicVo.class.getSimpleName());

        return pagedResult.setList(mgtCouponListVos).setTotal(count, filterParam.getPageSize());
    }

    public List<Document> aggregateMgtUserCoupon(List<String> storeCouponIds) {
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.project("storeCouponId", "state", "receiveStock"),
                Aggregation.match(Criteria.where("storeCouponId").in(storeCouponIds).and("state").ne(2)),
                Aggregation.group("storeCouponId", "state").count().as("totalCount")
        );
        AggregationResults<Document> aggregationResults = mongoTemplate.aggregate(aggregation, GoblinUserCouponBasicVo.class.getSimpleName(), Document.class);
        return aggregationResults.getMappedResults();
    }

    //根据艺人标签和演出查询商品
    public List<GoblinGoodsInfoVo> getMusicTagPGoods(String musicTag, String performanceId) {
        List<GoblinGoodsInfoVo> returnData = ObjectUtil.getGoblinGoodsInfoVos();

        Query query = Query.query(Criteria.where("artagVoList.tagName").is(musicTag)
                .and("delFlg").is("0").and("shelvesStatus").is("3"));

        List<GoblinGoodsInfoVo> baseData = mongoTemplate.find(query,
                GoblinGoodsInfoVo.class,
                GoblinGoodsInfoVo.class.getSimpleName()
        );

        //查询活动id
        Query queryShow = Query.query(Criteria.where("performanceId").is(performanceId).and("status").ne(7));
        List<GoblinSelfMarketingVo> showVoList = mongoTemplate.find(queryShow,
                GoblinSelfMarketingVo.class,
                GoblinSelfMarketingVo.class.getSimpleName()
        );
        if (showVoList.size() == 0) {
            return baseData;
        } else {
            GoblinSelfMarketingVo showVo = showVoList.get(0);

            //只保留 参加该活动或者没参加活动的数据
            for (GoblinGoodsInfoVo vo : baseData) {
                if (vo.getMarketId() == null || vo.getMarketId().equals(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue().concat(showVo.getSelfMarketId())) || vo.getMarketId().equals("")) {
                    returnData.add(vo);
                }
            }
            return returnData;
        }
    }

    //获取退款sku订单价格
    public BigDecimal getRefundOrderSkuVoPrice(String orderSkuId) {
        BigDecimal refundPrice = BigDecimal.ZERO;
        List<GoblinBackOrderVo> backOrderVos = mongoTemplate.find(Query.query(Criteria.where("backOrderSkuVos.orderSkuId").is(orderSkuId).and("status").nin(3, 5, 9)),
                GoblinBackOrderVo.class, GoblinBackOrderVo.class.getSimpleName());
        for (GoblinBackOrderVo vo : backOrderVos) {
            for (GoblinBackOrderSkuVo orderSkuVo : vo.getBackOrderSkuVos()) {
                refundPrice = refundPrice.add(orderSkuVo.getRefundPrice());
            }
        }
        return refundPrice;
    }

    //根据spuId查询活动id
    public List<String> getMarketIdListBySpuId(String spuId) {
        Query query = Query.query(Criteria.where("marketId").ne(null).and("spuId").regex(spuId.concat(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue()).concat(".*")));
        query.fields().include("marketId");
        return mongoTemplate.find(query, GoblinGoodsInfoVo.class, GoblinGoodsInfoVo.class.getSimpleName()).stream().map(GoblinGoodsInfoVo::getMarketId).collect(Collectors.toList());
    }

    ;
    /* ---------------------------------------- 商城:用户优惠券 ---------------------------------------- */

    public List<GoblinUserCouponVo> getUserCouponVos(String uid) {
        return mongoTemplate.find(Query.query(Criteria.where("uid").is(uid)),
                GoblinUserCouponVo.class, GoblinUserCouponBasicVo.class.getSimpleName());
    }

    public GoblinUserCouponBasicVo insertUserCouponVo(GoblinUserCouponBasicVo vo) {
        return mongoTemplate.insert(vo, GoblinUserCouponBasicVo.class.getSimpleName());
    }

    public Boolean changeCouponVos(String ucouponId, GoblinUserCouponBasicVo vo) {
        return mongoTemplate.getCollection(GoblinUserCouponBasicVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("ucouponId").is(ucouponId)).getQueryObject(),
                Update.update("state", vo.getState())
                        .set("usedFor", vo.getUsedFor())
                        .getUpdateObject()
        ).getModifiedCount() > 0;
    }

    /* ---------------------------------------- 我的藏品 ---------------------------------------- */

    /**
     * 盲盒开启后，直接从`我的藏品列表`中移除
     */
    public boolean updateUserDigitalArtworkVoByUnboxing(GoblinUserDigitalArtworkVo vo) {
        UpdateResult updateResult = mongoTemplate.getCollection(GoblinUserDigitalArtworkVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("artworkId").is(vo.getArtworkId()).and("state").ne(1)).getQueryObject(),
                Update.update("state", vo.getState())
                        .set("delFlg", vo.getDelFlg())
                        .set("openingAt", mongoConverter.convertToMongoType(vo.getOpeningAt()))
                        .set("updatedAt", mongoConverter.convertToMongoType(vo.getUpdatedAt()))
                        .set("deletedAt", mongoConverter.convertToMongoType(vo.getDeletedAt()))
                        .getUpdateObject()
        );
        return updateResult.getModifiedCount() > 0;
    }

    /**
     * 藏品收取后，更改藏品状态信息
     */
    public boolean updateUserDigitalArtworkVoByAccept(GoblinUserDigitalArtworkVo vo) {
        UpdateResult updateResult = mongoTemplate.getCollection(GoblinUserDigitalArtworkVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("artworkId").is(vo.getArtworkId())
                        .and("delFlg").is("0").and("source").is(31).and("state").is(5)).getQueryObject(),
                Update.update("state", vo.getState())
                        .set("openingAt", mongoConverter.convertToMongoType(vo.getOpeningAt()))
                        .set("updatedAt", mongoConverter.convertToMongoType(vo.getUpdatedAt()))
                        .getUpdateObject()
        );
        return updateResult.getModifiedCount() > 0;
    }

    public boolean updateUserDigitalArtworkVoByChainTrade(GoblinUserDigitalArtworkVo vo) {
        UpdateResult updateResult = mongoTemplate.getCollection(GoblinUserDigitalArtworkVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("artworkId").is(vo.getArtworkId())).getQueryObject(),
                Update.update("editionSn", vo.getEditionSn())
                        .set("nftId", vo.getNftId())
                        .set("releaseTxhash", vo.getReleaseTxhash())
                        .set("releaseAt", vo.getReleaseAt())
                        .set("tradingTxhash", vo.getTradingTxhash())
                        .set("tradingAt", vo.getTradingAt())
                        .set("state", vo.getState())
                        .set("updatedAt", mongoConverter.convertToMongoType(vo.getUpdatedAt()))
                        .getUpdateObject()
        );
        return updateResult.getModifiedCount() > 0;
    }

    /**
     * 转赠成功后，更新藏品信息
     */
    public boolean updateUserDigitalArtworkVoByTransQuery(GoblinUserDigitalArtworkVo vo) {
        UpdateResult updateResult = mongoTemplate.getCollection(GoblinUserDigitalArtworkVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("artworkId").is(vo.getArtworkId())).getQueryObject(),
                Update.update("transferState", vo.getTransferState())
                        .set("delFlg", vo.getDelFlg())
                        .set("deletedAt", mongoConverter.convertToMongoType(vo.getDeletedAt()))
                        .getUpdateObject()
        );
        return updateResult.getModifiedCount() > 0;
    }

    /**
     * 转赠退还后，恢复藏品信息
     */
    public boolean updateUserDigitalArtworkVoByTransReturn(String artworkId, LocalDateTime currentDateTime) {
        Query queryMongo = Query.query(
                Criteria.where("artworkId").is(artworkId).and("transferState").is(GoblinStatusConst.TransferState.WAITING.name())
        );
        Update updateMongo = Update.update("updatedAt", currentDateTime).unset("transferOrderId").unset("transferState")
                .unset("receiverUid").unset("receiverUser").unset("transferAt");
        UpdateResult updateResult = mongoTemplate.updateMulti(queryMongo, updateMongo, GoblinUserDigitalArtworkVo.class.getSimpleName());
        return updateResult.getModifiedCount() > 0;
    }

    public List<String> getPageUserDigitalArtworkIds(String uid, Integer pageNum, Integer pageSize) {
        Criteria criteria = Criteria.where("uid").is(uid).and("delFlg").is("0");
        Query query = Query.query(criteria);

        query.with(PageRequest.of(pageNum - 1, pageSize)).with(Sort.by(Sort.Order.desc("createdAt")));

        query.fields().include("artworkId");
        List<GoblinUserDigitalArtworkVo> list = mongoTemplate.find(query, GoblinUserDigitalArtworkVo.class, GoblinUserDigitalArtworkVo.class.getSimpleName());
        return CollectionUtils.isEmpty(list) ? null : list.stream().map(GoblinUserDigitalArtworkVo::getArtworkId).collect(Collectors.toList());
    }

    public PagedResult<GoblinStoreMgtGoodsSkuListVo> getSkuSearch(GoblinStoreMgtGoodsSkuFilterParam filterParam) {
        String sysTime = DateUtil.getNowTime();
        Criteria criteria = Criteria.where("storeId").is(filterParam.getStoreId()).and("spuId").is(filterParam.getSpuId()).and("delFlg").is("0");
        if (StringUtils.isNotBlank(filterParam.getKeyword())) {
            Pattern pattern = Pattern.compile("^.*" + filterParam.getKeyword() + ".*$", Pattern.CASE_INSENSITIVE);
            criteria.and("name").regex(pattern);
        }
        if (StringUtils.isNotBlank(filterParam.getShelvesStatus())) {
            if ("4".equals(filterParam.getShelvesStatus())) {
                criteria.and("shelvesStatus").is("3").and("saleStartTime").gte(now());
            } else {
                criteria.and("shelvesStatus").is(filterParam.getShelvesStatus());
            }
        }
        Query query = Query.query(criteria);

        long count = mongoTemplate.count(query, GoblinGoodsSkuInfoVo.class.getSimpleName());

        PagedResult<GoblinStoreMgtGoodsSkuListVo> pagedResult = ObjectUtil.goblinStoreMgtGoodsSkuListVo();
        if (count <= 0) return pagedResult;

        query.with(PageRequest.of(filterParam.getPageNum() - 1, 20));
        query.with(Sort.by(Sort.Order.desc("createdAt")));

        List<GoblinGoodsSkuInfoVo> skuList = mongoTemplate.find(query, GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
        List<GoblinStoreMgtGoodsSkuListVo> voList = ObjectUtil.getGoblinStoreMgtGoodsSkuListVoArrayList();
        for (GoblinGoodsSkuInfoVo vo : skuList) {
            GoblinStoreMgtGoodsSkuListVo mgtGoodsSkuListVo = GoblinStoreMgtGoodsSkuListVo.getNew().copy(vo);
            if (vo.getUnbox().equals("0")) {
                mgtGoodsSkuListVo.setSurplusStock(redisUtils.getSkuStock(null, vo.getSkuId()));
            } else {
                List<String> skuIdList = redisUtils.getGoodsInfoVo(vo.getSpuId()).getSkuIdList();
                int restStock = 0;
                int stock = 0;
                for (String skuIdItem : skuIdList) {// 盲盒计算所有sku库存总数
                    if (skuIdItem.equals(vo.getSkuId())) {// 过滤自己
                        continue;
                    }
                    GoblinGoodsSkuInfoVo itemVo = redisUtils.getGoodsSkuInfoVo(skuIdItem);
                    if (filterParam.getType().equals(0)) {
                        if ("4".equals(filterParam.getShelvesStatus())) {
                            restStock += redisUtils.getSkuAllStatusStockStatus4(itemVo);
                        } else {
                            restStock += redisUtils.getSkuAllStatusStock(itemVo, null);
                        }
                    } else if (filterParam.getType().equals(1)) {
                        restStock += redisUtils.getSkuAllStatusStockType1(itemVo);
                    }
                    stock += redisUtils.getSkuTotalStockShelvesStatus3(itemVo);
                }
                mgtGoodsSkuListVo.setSurplusStock(restStock);
                mgtGoodsSkuListVo.setSkuStock(stock);

            }
            mgtGoodsSkuListVo.setSysTime(sysTime);
            voList.add(mgtGoodsSkuListVo);
        }
        return pagedResult.setList(voList).setTotal(count, 20);
    }

    public PagedResult<GoblinStoreMgtGoodsSkuArListVo> getSkuArList(GoblinStoreMgtGoodsSkuArFilterParam filterParam) {
        Criteria criteria = Criteria.where("storeId").is(filterParam.getStoreId()).and("delFlg").is("0").and("arUrlIos").exists(true);
        if (StringUtils.isNotBlank(filterParam.getKeyword())) {
            Pattern pattern = Pattern.compile("^.*" + filterParam.getKeyword() + ".*$", Pattern.CASE_INSENSITIVE);
            criteria.orOperator(Criteria.where("name").regex(pattern), Criteria.where("subtitle").regex(pattern));
        }
        Query query = Query.query(criteria);
        long count = mongoTemplate.count(query, GoblinGoodsSkuInfoVo.class.getSimpleName());

        PagedResult<GoblinStoreMgtGoodsSkuArListVo> pagedResult = ObjectUtil.getGoblinStoreMgtGoodsSkuArListVoPagedResult();
        if (count <= 0) return pagedResult;

        query.with(PageRequest.of(filterParam.getPageNum() - 1, filterParam.getPageSize()));
        query.with(Sort.by(Sort.Order.desc("createdAt")));

        List<GoblinStoreMgtGoodsSkuArListVo> list = mongoTemplate.find(query, GoblinStoreMgtGoodsSkuArListVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
        return pagedResult.setList(list).setTotal(count, filterParam.getPageSize());
    }

    /**
     * 记录用户藏品数据
     */
    public void insertUserDigitalArtworkVo(GoblinUserDigitalArtworkVo vo) {
        mongoTemplate.insert(vo, GoblinUserDigitalArtworkVo.class.getSimpleName());
    }

    /**
     * 新增名单数据
     */
    public void insertGoblinListDetailsVo(GoblinListDetailsVo vo) {
        mongoTemplate.insert(vo, GoblinListDetailsVo.class.getSimpleName());
    }

    public Boolean hasGoblinListDetailsVoByName(String name) {
        Criteria criteria = Criteria.where("name").is(name);
        Query query = Query.query(criteria);
        return mongoTemplate.exists(query, GoblinListDetailsVo.class, GoblinListDetailsVo.class.getSimpleName());
    }

    public void removeGoblinListDetailsVo(String listId) {
        mongoTemplate.remove(Query.query(Criteria.where("listId").is(listId)), GoblinListDetailsVo.class.getSimpleName());
    }

    public Boolean changeGoblinListDetailsVo(GoblinListDetailsVo vo) {
        return mongoTemplate.getCollection(GoblinListDetailsVo.class.getSimpleName())
                .updateOne(Query.query(Criteria.where("listId").is(vo.getListId())).getQueryObject(),
                        ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(vo))
                ).getModifiedCount() > 0;
    }

    public HashMap<String, Object> getGoblinListVo(String name, String uid, Integer pageNum) {
        int pageSize = 20;
        Criteria criteria = Criteria.where("uid").is(uid);
        if (name != null && !name.equals("")) {
            criteria = criteria.and("name").regex("^.*" + name + ".*$");
        }
        Query query = Query.query(criteria);

        long total = mongoTemplate.count(query, GoblinListDetailsVo.class, GoblinListDetailsVo.class.getSimpleName());
        query.with(PageRequest.of(pageNum - 1, pageSize)).with(Sort.by(Sort.Order.desc("createdAt")));
        List<GoblinListDetailsVo> list = mongoTemplate.find(query, GoblinListDetailsVo.class, GoblinListDetailsVo.class.getSimpleName());

        HashMap<String, Object> map = CollectionUtil.mapStringObject();
        map.put("data", list);
        map.put("total", total);
        return map;
    }

    // 添加 混合售 数据
    public GoblinMixDetailsVo setGoblinMixDetailsVo(GoblinMixDetailsVo vo) {
        return mongoTemplate.insert(vo, GoblinMixDetailsVo.class.getSimpleName());
    }

    // 添加 混合售 数据
    public long getMixNameCount(String name) {
        return mongoTemplate.count(Query.query(Criteria.where("name").is(name)), GoblinMixDetailsVo.class, GoblinMixDetailsVo.class.getSimpleName());
    }

    //修改 混合售 数据
    public Boolean changeGoblinMixDetailsVo(GoblinMixDetailsVo vo) {
        return mongoTemplate.getCollection(GoblinMixDetailsVo.class.getSimpleName())
                .updateOne(Query.query(Criteria.where("mixId").is(vo.getMixId())).getQueryObject(),
                        ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(vo))
                ).getModifiedCount() > 0;
    }

    public HashMap<String, Object> getGoblinMixListVo(String name, String uid, Integer pageNum) {
        int pageSize = 20;
        Criteria criteria = Criteria.where("userId").is(uid);
        if (name != null && !name.equals("")) {
            criteria = criteria.and("name").regex("^.*" + name + ".*$");
        }
        Query query = Query.query(criteria);

        long total = mongoTemplate.count(query, GoblinMixDetailsVo.class, GoblinMixDetailsVo.class.getSimpleName());
        query.with(PageRequest.of(pageNum - 1, pageSize)).with(Sort.by(Sort.Order.desc("createdAt")));
        List<GoblinMixDetailsVo> list = mongoTemplate.find(query, GoblinMixDetailsVo.class, GoblinMixDetailsVo.class.getSimpleName());

        HashMap<String, Object> map = CollectionUtil.mapStringObject();
        map.put("data", list);
        map.put("total", total);
        return map;
    }


    public List<GoblinNowOrderListVo> getGoblinNowOrderListVo(String orderCode, String storeId, String marketId, Integer pageNum) {
        int pageSize = 20;
        Criteria criteria = Criteria.where("storeId").is(storeId).and("marketId").is("ZZ".concat(marketId))
                .orOperator(Criteria.where("paymentId").regex("^.*" + orderCode + "$"), Criteria.where("orderCode").regex("^.*" + orderCode + "$"));
        Query query = Query.query(criteria);
        query.with(PageRequest.of(pageNum - 1, pageSize)).with(Sort.by(Sort.Order.desc("createdAt")));
        List<GoblinNowOrderListVo> list = mongoTemplate.find(query, GoblinNowOrderListVo.class, GoblinStoreOrderVo.class.getSimpleName());
        return list;
    }

    public GoblinNowOrderListVo getGoblinNowOrderDetailsVo(String orderCode, String storeId, String marketId) {
        Criteria criteria = Criteria.where("storeId").is(storeId).and("marketId").is("ZZ".concat(marketId))
                .orOperator(Criteria.where("payCode").is(orderCode), Criteria.where("orderCode").is(orderCode));
        Query query = Query.query(criteria);
        GoblinNowOrderListVo data = mongoTemplate.findOne(query, GoblinNowOrderListVo.class, GoblinStoreOrderVo.class.getSimpleName());
        return data;
    }
    /* ----------------------------------------  ---------------------------------------- */
    /* ----------------------------------------  ---------------------------------------- */

    public KylinPerformanceVo getKylinPerformanceVo(String performanceId) {
        Object obj = redisUtils.get(KylinRedisConst.PERFORMANCES + performanceId);
        if (obj != null) {
            return (KylinPerformanceVo) obj;
        } else {
            return mongoTemplate.findOne(Query
                            .query(Criteria.where("performancesId")
                                    .is(performanceId)),
                    KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());
        }

    }
}
