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.dto.manage.GoblinStoreMgtGoodsFilterParam;
import com.liquidnet.service.goblin.dto.manage.vo.GoblinStoreMgtGoodsListVo;
import com.liquidnet.service.goblin.dto.vo.*;
import com.mongodb.BasicDBObject;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.apache.commons.lang3.StringUtils;
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.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;

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

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

    public List<GoblinSelfTagVo> getSelfTagVos(List<String> tagIds) {
        if (CollectionUtils.isEmpty(tagIds)) return ObjectUtil.getGoblinSelfTagVoArrayList();

        return null;
    }

    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 GoblinStoreInfoVo setStoreInfoVo(GoblinStoreInfoVo vo) {
        return mongoTemplate.insert(vo, GoblinStoreInfoVo.class.getSimpleName());
    }

    public boolean delStoreInfoVo(String storeId) {
        return mongoTemplate.remove(Query.query(Criteria.where("storeId").is(storeId)),
                GoblinStoreInfoVo.class, GoblinStoreInfoVo.class.getSimpleName()).getDeletedCount() > 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)),
                GoblinStoreInfoVo.class, GoblinStoreInfoVo.class.getSimpleName());
    }

    public GoblinStoreInfoVo getStoreInfoVoByUid(String uid) {
        return mongoTemplate.findOne(Query.query(Criteria.where("uid").is(uid)),
                GoblinStoreInfoVo.class, GoblinStoreInfoVo.class.getSimpleName());
    }

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

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

    public boolean delGoodsInfoVo(String spuId) {
        return mongoTemplate.remove(Query.query(Criteria.where("spuId").is(spuId)),
                GoblinGoodsInfoVo.class, GoblinGoodsInfoVo.class.getSimpleName()).getDeletedCount() > 0;
    }

    // SPU分页
    public PagedResult<GoblinStoreMgtGoodsListVo> getGoodsInfoVo(GoblinStoreMgtGoodsFilterParam filterParam) {
        Criteria criteria = new Criteria();
        if (StringUtils.isNotBlank(filterParam.getKeyword())) {
            Pattern pattern = Pattern.compile("^.*" + filterParam.getKeyword() + ".*$", Pattern.CASE_INSENSITIVE);
            criteria.orOperator(
                    Criteria.where("name").regex(pattern)
            );
        }
        if (StringUtils.isNotBlank(filterParam.getShelvesStatus())) {
            criteria.andOperator(Criteria.where("shelvesStatus").is(filterParam.getShelvesStatus()));
        }
        if (StringUtils.isNotBlank(filterParam.getCateFid())) {
            criteria.andOperator(Criteria.where("cateFid").is(filterParam.getCateFid()));
        }
        if (StringUtils.isNotBlank(filterParam.getCateSid())) {
            criteria.andOperator(Criteria.where("cateSid").is(filterParam.getCateSid()));
        }
        if (StringUtils.isNotBlank(filterParam.getCateTid())) {
            criteria.andOperator(Criteria.where("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.andOperator(Criteria.where("createdAt").gte(createdAtBegin).lte(createdAtEnd));
        }
        if (null != filterParam.getPriceGe()) {
            criteria.andOperator(Criteria.where("priceGe").gte(filterParam.getPriceGe()));
        }
        if (null != filterParam.getPriceLe()) {
            criteria.andOperator(Criteria.where("priceGe").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")));

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

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

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

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

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

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

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

    public boolean delGoodsSkuInfoVo(String skuId) {
        return mongoTemplate.remove(Query.query(Criteria.where("skuId").is(skuId)),
                GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName()).getDeletedCount() > 0;
    }

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

    // SKU信息
    public GoblinGoodsSkuInfoVo getMgtGoodsSkuInfoVo(String skuId) {
        return mongoTemplate.findOne(Query.query(Criteria.where("skuId").is(skuId)),
                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())).getQueryObject(),
                        ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(vo))
                ).getModifiedCount() > 0;
    }

    public boolean updateGoodsSkuInfoVoBySpuId(GoblinGoodsSkuInfoVo vo) {
        return mongoTemplate.getCollection(GoblinGoodsSkuInfoVo.class.getSimpleName())
                .updateOne(
                        Query.query(Criteria.where("spuId").is(vo.getSpuId())).getQueryObject(),
                        ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(vo))
                ).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> 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;
    }
}
