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

import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.service.base.PagedResult;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.dto.GoblinGoodsSpecDto;
import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtGoodsActionParam;
import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtGoodsAddParam;
import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtGoodsEditSkuParam;
import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtGoodsFilterParam;
import com.liquidnet.service.goblin.dto.manage.vo.GoblinMgtCategorySpecVo;
import com.liquidnet.service.goblin.dto.manage.vo.GoblinStoreMgtGoodsInfoVo;
import com.liquidnet.service.goblin.dto.manage.vo.GoblinStoreMgtGoodsListVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSkuInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSpecValueVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSpecVo;
import com.liquidnet.service.goblin.service.manage.IGoblinstoreMgtGoodsService;
import com.liquidnet.service.goblin.util.GoblinMongoUtils;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.ObjectUtil;
import com.liquidnet.service.goblin.util.QueueUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

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

@Service
public class GoblinStoreMgtGoodsServiceImpl implements IGoblinstoreMgtGoodsService {
    @Autowired
    QueueUtils queueUtils;
    @Autowired
    GoblinRedisUtils goblinRedisUtils;
    @Autowired
    GoblinMongoUtils goblinMongoUtils;

    @Override
    public PagedResult<GoblinStoreMgtGoodsListVo> goodsList(GoblinStoreMgtGoodsFilterParam filterParam) {
        return goblinMongoUtils.getGoodsInfoVo(filterParam);
    }

    @Override
    public void goodsAdd(GoblinGoodsInfoVo goodsInfoVo, List<GoblinGoodsSkuInfoVo> goodsSkuInfoVoList) {
//        String uid = CurrentUtil.getCurrentUid();
//        LocalDateTime now = LocalDateTime.now();

//        GoblinGoodsInfoVo goodsInfoVo = storeMgtGoodsAddParam.initGoodsInfoVo();
//        goodsInfoVo.setCreatedBy(uid);
//        goodsInfoVo.setCreatedAt(now);
//
//        ArrayList<GoblinGoodsSpecVo> goodsSpecVoList = ObjectUtil.getGoblinGoodsSpecVoArrayList();
//        List<GoblinGoodsSkuInfoVo> goodsSkuInfoVoList = ObjectUtil.getGoblinGoodsSkuInfoVoArrayList();
//
//        storeMgtGoodsAddParam.initGoodsSkuInfoVo(goodsInfoVo, goodsSkuInfoVoList, goodsSpecVoList);

//        {// 标签处理
//            List<String> goodsTagIdList = storeMgtGoodsAddParam.getTagList();
//            List<String> goodsExtagIdList = storeMgtGoodsAddParam.getExtagList();
//            boolean goodsTagIsEmpty = CollectionUtils.isEmpty(goodsTagIdList);
//            boolean goodsExtagIsEmpty = CollectionUtils.isEmpty(goodsExtagIdList);
//
//            ArrayList<String> tagIdList = CollectionUtil.arrayListString();
//            tagIdList.addAll(goodsTagIdList);
//            tagIdList.addAll(goodsExtagIdList);
//            if (!CollectionUtils.isEmpty(tagIdList)) {
//                List<GoblinSelfTagVo> selfTagVoList = goblinMongoUtils.getSelfTagVos(tagIdList);
//                if (!goodsTagIsEmpty) {
//                    List<GoblinGoodsTagVo> goodsTagVoList = ObjectUtil.getGoblinGoodsTagVoArrayList();
//                    for (int i = 0; i < tagIdList.size(); i++) {
//                        String tagId = tagIdList.get(i);
//                        for (GoblinSelfTagVo r : selfTagVoList) {
//                            if (r.getTagId().equals(tagId)) {
//                                goodsTagVoList.add(GoblinGoodsTagVo.getNew().copy(r).setSort(i));
//                            }
//                        }
//                    }
//                    goodsInfoVo.setTagVoList(goodsTagVoList);
//                }
//                if (!goodsExtagIsEmpty) {
//                    List<GoblinGoodsExtagVo> goodsExtagVoList = ObjectUtil.getGoblinGoodsExtagVoArrayList();
//                    for (int i = 0; i < tagIdList.size(); i++) {
//                        String tagId = tagIdList.get(i);
//                        for (GoblinSelfTagVo r : selfTagVoList) {
//                            if (r.getTagId().equals(tagId)) {
//                                goodsExtagVoList.add(GoblinGoodsExtagVo.getNew().copy(r).setSort(i));
//                            }
//                        }
//                    }
//                    goodsInfoVo.setExtagVoList(goodsExtagVoList);
//                }
//            }
//        }
//
//        // 服务保障处理
//        goodsInfoVo.setServiceSupportVoList(goblinMongoUtils.getServiceSupportVos(storeMgtGoodsAddParam.getSsidList()));

        goblinMongoUtils.setGoodsInfoVo(goodsInfoVo);
        goblinMongoUtils.setGoodsSkuInfoVos(goodsSkuInfoVoList);

        String spuId = goodsInfoVo.getSpuId();

        LinkedList<String> toMqSqls = CollectionUtil.linkedListString();
        toMqSqls.add(SqlMapping.get("goblin_goods.insert"));
        LinkedList<Object[]> initGoodsObjs = CollectionUtil.linkedListObjectArr();
        initGoodsObjs.add(new Object[]{
                spuId, goodsInfoVo.getSpuNo(), goodsInfoVo.getName(), goodsInfoVo.getSubtitle(), goodsInfoVo.getSellPrice(),
                goodsInfoVo.getPriceGe(), goodsInfoVo.getPriceLe(), goodsInfoVo.getIntro(), goodsInfoVo.getDetails(), goodsInfoVo.getCoverPic(),
                goodsInfoVo.getVideo(), goodsInfoVo.getSpecMode(), goodsInfoVo.getStoreId(), goodsInfoVo.getCateFid(), goodsInfoVo.getCateSid(),
                goodsInfoVo.getCateTid(), goodsInfoVo.getStoreCateFid(), goodsInfoVo.getStoreCateSid(), goodsInfoVo.getStoreCateTid(), goodsInfoVo.getBrandId(),
                goodsInfoVo.getShelvesHandle(), goodsInfoVo.getShelvesTime(), goodsInfoVo.getSpuValidity(), goodsInfoVo.getVirtualFlg(), goodsInfoVo.getStatus(),
                goodsInfoVo.getShelvesStatus(), goodsInfoVo.getSpuAppear(), goodsInfoVo.getShelvesAt(), goodsInfoVo.getCreatedBy(), goodsInfoVo.getCreatedAt(),
                goodsInfoVo.getLogisticsTemplate()
        });
        toMqSqls.add(SqlMapping.get("goblin_goods_sku.insert"));
        LinkedList<Object[]> initGoodsSkuObjs = CollectionUtil.linkedListObjectArr();
        goodsSkuInfoVoList.forEach(skuInfoVo -> initGoodsSkuObjs.add(new Object[]{
                skuInfoVo.getSkuId(), skuInfoVo.getSpuId(), skuInfoVo.getSkuNo(), skuInfoVo.getName(), skuInfoVo.getSubtitle(),
                skuInfoVo.getSellPrice(), skuInfoVo.getSkuPic(), skuInfoVo.getSkuIsbn(), skuInfoVo.getStock(), skuInfoVo.getSkuStock(),
                skuInfoVo.getWarningStock(), skuInfoVo.getPrice(), skuInfoVo.getPriceMember(), skuInfoVo.getWeight(), skuInfoVo.getBuyFactor(),
                skuInfoVo.getBuyRoster(), skuInfoVo.getBuyLimit(), skuInfoVo.getStoreId(), skuInfoVo.getSkuValidity(), skuInfoVo.getVirtualFlg(),
                skuInfoVo.getStatus(), skuInfoVo.getShelvesStatus(), skuInfoVo.getSkuAppear(), skuInfoVo.getShelvesAt(), skuInfoVo.getCreatedBy(),
                skuInfoVo.getCreatedAt(), skuInfoVo.getLogisticsTemplate()
        }));
        toMqSqls.add(SqlMapping.get("goblin_goods_image.insert"));
        LinkedList<Object[]> initGoodsImageObjs = CollectionUtil.linkedListObjectArr();
        if (CollectionUtils.isEmpty(goodsInfoVo.getImageList())) {
            goodsInfoVo.getImageList().forEach(imageUrl -> initGoodsImageObjs.add(new Object[]{spuId, imageUrl}));
        }
        toMqSqls.add(SqlMapping.get("goblin_goods_tag.insert"));
        LinkedList<Object[]> initGoodsTagObjs = CollectionUtil.linkedListObjectArr();
        if (!CollectionUtils.isEmpty(goodsInfoVo.getTagVoList())) {
            goodsInfoVo.getTagVoList().forEach(tagVo -> initGoodsTagObjs.add(new Object[]{spuId, tagVo.getTagId(), tagVo.getSort(), "0"}));
        }
        if (!CollectionUtils.isEmpty(goodsInfoVo.getExtagVoList())) {
            goodsInfoVo.getExtagVoList().forEach(exTagVo -> initGoodsTagObjs.add(new Object[]{spuId, exTagVo.getTagId(), exTagVo.getSort(), "1"}));
        }
        toMqSqls.add(SqlMapping.get("goblin_goods_service_support.insert"));
        LinkedList<Object[]> initGoodsServiceSupportObjs = CollectionUtil.linkedListObjectArr();
        if (!CollectionUtils.isEmpty(goodsInfoVo.getServiceSupportVoList())) {
            goodsInfoVo.getServiceSupportVoList().forEach(ssvo -> initGoodsServiceSupportObjs.add(new Object[]{spuId, ssvo.getSsid()}));
        }
        {// 规格记录
            List<GoblinGoodsSpecVo> specVoList = goodsInfoVo.getSpecVoList();
            String cateFid = goodsInfoVo.getCateFid();
            String cateSid = goodsInfoVo.getCateSid();
            String cateTid = goodsInfoVo.getCateTid();
            String filterCateId = StringUtils.isBlank(cateTid) ? (StringUtils.isBlank(cateSid) ? cateFid : cateSid) : cateTid;
            List<GoblinMgtCategorySpecVo> categorySpecVoList = goblinMongoUtils.getCategorySpecVos(filterCateId);
            if (CollectionUtils.isEmpty(categorySpecVoList)) {// 根据分类ID未查取到规格信息，则新增

            } else {// 根据分类ID查取到规格信息，则进一步比对判断是否新增

            }
        }

        queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_GOODS.getKey(),
                SqlMapping.gets(toMqSqls, initGoodsObjs, initGoodsSkuObjs, initGoodsImageObjs, initGoodsTagObjs, initGoodsServiceSupportObjs));
    }

    @Override
    public GoblinStoreMgtGoodsInfoVo goodsInfo(String storeId, String spuId) {
        GoblinStoreMgtGoodsInfoVo vo = GoblinStoreMgtGoodsInfoVo.getNew();
        GoblinGoodsInfoVo goodsInfoVo = goblinRedisUtils.getMgtGoodsInfoVo(spuId);
        if (null != goodsInfoVo) {
            vo.setGoodsInfoVo(goodsInfoVo);
            List<String> skuIdList = goodsInfoVo.getSkuIdList();
            if (!CollectionUtils.isEmpty(skuIdList)) {
                List<GoblinGoodsSkuInfoVo> goodsSkuInfoVoList = ObjectUtil.getGoblinGoodsSkuInfoVoArrayList();
                skuIdList.forEach(skuId -> goodsSkuInfoVoList.add(goblinRedisUtils.getMgtGoodsSkuInfoVo(skuId)));
                vo.setGoodsSkuInfoVoList(goodsSkuInfoVoList);
            }
        }
        return vo;
    }

    @Override
    public boolean goodsEditSpu(GoblinStoreMgtGoodsAddParam storeMgtGoodsAddParam) {
        GoblinGoodsInfoVo editGoodsSkuInfoVo = storeMgtGoodsAddParam.initEditGoodsInfoVo();
        if (goblinMongoUtils.updateGoodsInfoVo(editGoodsSkuInfoVo)) {
            GoblinGoodsSkuInfoVo updateSkuInfoVo = GoblinGoodsSkuInfoVo.getNew();
            updateSkuInfoVo.setSpuId(editGoodsSkuInfoVo.getSpuId());
            updateSkuInfoVo.setSkuNo(editGoodsSkuInfoVo.getSpuNo());
            updateSkuInfoVo.setName(editGoodsSkuInfoVo.getName());
            updateSkuInfoVo.setSubtitle(editGoodsSkuInfoVo.getSubtitle());
            updateSkuInfoVo.setVirtualFlg(editGoodsSkuInfoVo.getVirtualFlg());
            updateSkuInfoVo.setLogisticsTemplate(editGoodsSkuInfoVo.getLogisticsTemplate());

            goblinMongoUtils.updateGoodsSkuInfoVoBySpuId(updateSkuInfoVo);
            // TODO: 2022/1/5 zhanggb redis+sql

            return true;
        }
        return false;
    }

    @Override
    public boolean goodsEditSku(GoblinStoreMgtGoodsEditSkuParam storeMgtGoodsEditSkuParam, GoblinGoodsInfoVo goodsInfoVo) {
        GoblinGoodsSkuInfoVo editGoodsSkuInfoVo = storeMgtGoodsEditSkuParam.initEditGoodsSkuInfoVo();
        if (goblinMongoUtils.updateGoodsSkuInfoVo(editGoodsSkuInfoVo)) {
            if (!CollectionUtils.isEmpty(storeMgtGoodsEditSkuParam.getSkuSpecList())) {// 更改了规格，需要同步SPU里的规格信息
                goblinMongoUtils.updateGoodsInfoVo(goodsInfoVo);
            }
            // TODO: 2022/1/5 zhanggb redis+sql

            return true;
        }
        return false;
    }

    @Override
    public void goodsEditSkuAdd(GoblinStoreMgtGoodsEditSkuParam storeMgtGoodsEditSkuParam, GoblinGoodsInfoVo goodsInfoVo) {
        String spuId = storeMgtGoodsEditSkuParam.getSpuId();
        String uid = CurrentUtil.getCurrentUid();
        LocalDateTime now = LocalDateTime.now();

        GoblinGoodsSkuInfoVo addGoodsSkuInfoVo = storeMgtGoodsEditSkuParam.initEditAddGoodsSkuInfoVo();
        addGoodsSkuInfoVo.setSkuId(spuId.concat(StringUtils.right(String.valueOf(System.nanoTime()), 5)));
        addGoodsSkuInfoVo.setSpuId(spuId);
        addGoodsSkuInfoVo.setSkuNo(goodsInfoVo.getSpuNo());
        addGoodsSkuInfoVo.setName(goodsInfoVo.getName());
        addGoodsSkuInfoVo.setSubtitle(goodsInfoVo.getSubtitle());
        addGoodsSkuInfoVo.setVirtualFlg(goodsInfoVo.getVirtualFlg());
        addGoodsSkuInfoVo.setStatus("3");
        addGoodsSkuInfoVo.setShelvesStatus(goodsInfoVo.getShelvesStatus());
        addGoodsSkuInfoVo.setDelFlg("0");
        addGoodsSkuInfoVo.setCreatedAt(now);
        addGoodsSkuInfoVo.setCreatedBy(uid);
        addGoodsSkuInfoVo.setLogisticsTemplate(goodsInfoVo.getLogisticsTemplate());

        goblinMongoUtils.setGoodsSkuInfoVo(addGoodsSkuInfoVo);

        List<String> skuIdList = goodsInfoVo.getSkuIdList();
        skuIdList.add(addGoodsSkuInfoVo.getSkuId());
        goodsInfoVo.setSkuIdList(skuIdList);

        goblinMongoUtils.updateGoodsInfoVo(goodsInfoVo);

        // TODO: 2022/1/5 zhanggb redis+sql
    }

    @Override
    public boolean goodsEditSkuDel(GoblinGoodsSkuInfoVo goodsSkuInfoVo) {
        String skuId = goodsSkuInfoVo.getSkuId();

        GoblinGoodsInfoVo mgtGoodsInfoVo = goblinRedisUtils.getMgtGoodsInfoVo(goodsSkuInfoVo.getSpuId());
        List<String> skuIdList = mgtGoodsInfoVo.getSkuIdList();
        skuIdList.removeIf(r -> r.equals(skuId));
        mgtGoodsInfoVo.setSkuIdList(skuIdList);

        List<GoblinGoodsSpecVo> specVoList = mgtGoodsInfoVo.getSpecVoList();
        Map<String, String> delGoodsSkuSpecMap = goodsSkuInfoVo.getSkuSpecList().stream()
                .collect(Collectors.toMap(GoblinGoodsSpecDto::getSpecName, GoblinGoodsSpecDto::getSpecVname, (k1, k2) -> k2));
        for (int i = 0; i < specVoList.size(); i++) {// 处理商品规格信息
            GoblinGoodsSpecVo specVo = specVoList.get(i);
            List<GoblinGoodsSpecValueVo> modifySpecValues = ObjectUtil.getGoblinGoodsSpecValueVoArrayList();

            String delSpecVname = delGoodsSkuSpecMap.get(specVo.getSpecName());
            List<GoblinGoodsSpecValueVo> specValues = specVo.getSpecValues();
            Integer rmIdx = null;
            for (GoblinGoodsSpecValueVo specValue : specValues) {
                if (specValue.getSpecVname().equals(delSpecVname)) {
                    modifySpecValues.remove(specValue);
                    rmIdx = specValue.getSpecVsort();
                } else {
                    modifySpecValues.add(specValue);
                }
                if (null != rmIdx && specValue.getSpecVsort() > rmIdx) {
                    specValue.setSpecVsort(specValue.getSpecVsort() - 1);
                }
            }
            if (modifySpecValues.size() == 0) {// 规格下规格值为0的时候，移除规格
                specVoList.remove(specVo);
            } else {
                specVo.setSpecValues(modifySpecValues);
            }
        }

        goblinMongoUtils.delGoodsSkuInfoVo(skuId);
        goblinRedisUtils.delGoodsSkuInfoVo(skuId);

        // TODO: 2022/1/5 zhanggb redis+sql

        return goblinMongoUtils.updateGoodsInfoVo(mgtGoodsInfoVo);
    }

    @Override
    public boolean goodsEditSkuBat(String spuId, String batField, String batFieldVal) {
        // TODO: 2022/1/5 zhanggb
        return false;
    }

    @Override
    public void goodsShelvesProcessing(GoblinStoreMgtGoodsActionParam storeMgtGoodsActionParam, String uid, boolean shelvesFlg) {
        LocalDateTime now = LocalDateTime.now();
        String storeId = storeMgtGoodsActionParam.getStoreId();
        List<String> spuIdList = storeMgtGoodsActionParam.getSpuIdList();

        if (goblinMongoUtils.updateGoodsInfoVoByShelves(storeId, spuIdList, shelvesFlg, uid, now)) {
            if (goblinMongoUtils.updateGoodsSkuInfoVoByShelves(storeId, spuIdList, shelvesFlg, uid, now)) {
                // TODO: 2022/1/7 zhanggb redis

                LinkedList<String> toMqSqls = CollectionUtil.linkedListString();
                toMqSqls.add(SqlMapping.get("goblin_goods.update_by_shelves"));
                LinkedList<Object[]> updateGoodsObjs = CollectionUtil.linkedListObjectArr();
                String shelvesStatus = shelvesFlg ? "3" : "1";
                spuIdList.forEach(spuId -> updateGoodsObjs.add(new Object[]{shelvesStatus, now, uid, now, spuId, storeId}));
                toMqSqls.add(SqlMapping.get("goblin_goods_sku.update_by_shelves"));
                LinkedList<Object[]> updateGoodsSkuObjs = CollectionUtil.linkedListObjectArr();
                spuIdList.forEach(spuId -> updateGoodsSkuObjs.add(new Object[]{shelvesStatus, now, uid, now, spuId, storeId}));

                queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_GOODS.getKey(),
                        SqlMapping.gets(toMqSqls, updateGoodsObjs, updateGoodsSkuObjs));
            } else {
                goblinMongoUtils.updateGoodsInfoVoByShelves(storeId, spuIdList, !shelvesFlg, uid, now);
            }
        }
    }

    @Override
    public void goodsRemove(GoblinStoreMgtGoodsActionParam storeMgtGoodsActionParam, String uid) {
        LocalDateTime now = LocalDateTime.now();
        String storeId = storeMgtGoodsActionParam.getStoreId();
        List<String> spuIdList = storeMgtGoodsActionParam.getSpuIdList();

        if (goblinMongoUtils.delGoodsInfoVoBySpuIds(storeId, spuIdList, uid, now)) {
            // TODO: 2022/1/7 zhanggb redis

            LinkedList<String> toMqSqls = CollectionUtil.linkedListString();
            toMqSqls.add(SqlMapping.get("goblin_goods.update_by_del"));
            LinkedList<Object[]> updateGoodsObjs = CollectionUtil.linkedListObjectArr();
            spuIdList.forEach(spuId -> updateGoodsObjs.add(new Object[]{uid, now, uid, now, spuId, storeId}));
            toMqSqls.add(SqlMapping.get("goblin_goods_sku.update_by_del"));
            LinkedList<Object[]> updateGoodsSkuObjs = CollectionUtil.linkedListObjectArr();
            spuIdList.forEach(spuId -> updateGoodsSkuObjs.add(new Object[]{uid, now, uid, now, spuId, storeId}));

            queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_GOODS.getKey(),
                    SqlMapping.gets(toMqSqls, updateGoodsObjs, updateGoodsSkuObjs));
        }
    }
}
