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

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.liquidnet.common.exception.constant.ErrorCode;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.PagedResult;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.GoblinGoodsSpecDto;
import com.liquidnet.service.goblin.dto.GoblinStoreMgtGoodsListVoExcel;
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.GoblinStoreMgtGoodsInfoVo;
import com.liquidnet.service.goblin.dto.manage.vo.GoblinStoreMgtGoodsListVo;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.service.manage.IGoblinStoreMgtExtraService;
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 io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@ApiSupport(order = 149004)
@Api(tags = "商品管理")
@Slf4j
@Validated
@RestController
@RequestMapping("store/mgt/goods")
public class GoblinStoreMgtGoodsController {
    @Autowired
    IGoblinstoreMgtGoodsService goblinstoreMgtGoodsService;
    @Autowired
    IGoblinStoreMgtExtraService goblinStoreMgtExtraService;
    @Autowired
    GoblinRedisUtils goblinRedisUtils;
    @Autowired
    GoblinMongoUtils goblinMongoUtils;

    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "SPU列表")
    @PostMapping("list")
    public ResponseDto<PagedResult<GoblinStoreMgtGoodsListVo>> list(@Valid @RequestBody GoblinStoreMgtGoodsFilterParam storeMgtGoodsFilterParam) {
        String currentUid = CurrentUtil.getCurrentUid();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeMgtGoodsFilterParam.getStoreId())) {
            return ResponseDto.success();
        }
        if (log.isDebugEnabled()) {
            log.debug("商品管理:SPU列表:[GoblinStoreMgtGoodsFilterParam={}]", JsonUtils.toJson(storeMgtGoodsFilterParam));
        }
        return ResponseDto.success(goblinstoreMgtGoodsService.goodsList(storeMgtGoodsFilterParam));
    }

    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "SPU导出")
    @PostMapping("export")
    public void export(@Valid @RequestBody GoblinStoreMgtGoodsFilterParam storeMgtGoodsFilterParam, HttpServletResponse response) {
        String currentUid = CurrentUtil.getCurrentUid();
        ServletOutputStream servletOutputStream = null;
        try {
            if (!goblinRedisUtils.hasStoreId(currentUid, storeMgtGoodsFilterParam.getStoreId())) {
                log.warn("商品管理:SPU导出:无权操作该店铺，请核实[UID={},GoblinStoreMgtGoodsFilterParam={}]", currentUid, JsonUtils.toJson(storeMgtGoodsFilterParam));
                return;
            }
            if (log.isDebugEnabled()) {
                log.debug("商品管理:SPU导出:[UID={},GoblinStoreMgtGoodsFilterParam={}]", currentUid, JsonUtils.toJson(storeMgtGoodsFilterParam));
            }
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=".concat(DateUtil.Formatter.ddHHmmssTrim.format(LocalDateTime.now()))
                    .concat(new String(("商品数据").getBytes("gb2312"), StandardCharsets.ISO_8859_1)).concat(ExcelTypeEnum.XLSX.getValue()));
            response.setContentType(MediaType.MULTIPART_FORM_DATA_VALUE);
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            servletOutputStream = response.getOutputStream();

            storeMgtGoodsFilterParam.setPageNum(1);
            storeMgtGoodsFilterParam.setPageSize(5000);
            PagedResult<GoblinStoreMgtGoodsListVo> pagedResult = goblinstoreMgtGoodsService.goodsList(storeMgtGoodsFilterParam);
            List<GoblinStoreMgtGoodsListVo> rows = pagedResult.getList();
            List<GoblinStoreMgtGoodsListVoExcel> rowsToExcels = ObjectUtil.getGoblinStoreMgtGoodsListVoExcelArrayList();
            rows.forEach(row -> rowsToExcels.add(GoblinStoreMgtGoodsListVoExcel.getNew().copy(row)));

            EasyExcel.write(servletOutputStream, GoblinStoreMgtGoodsListVoExcel.class).sheet("商品数据").doWrite(rowsToExcels);
        } catch (IOException e) {
            log.error("商品管理:SPU导出:异常[UID={},ex.msg={}]", currentUid, e.getLocalizedMessage());
        } finally {
            if (null != servletOutputStream) {
                try {
                    servletOutputStream.close();
                } catch (Exception e) {
                }
            }
        }
    }

    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "SPU管理")
    @PostMapping("operate")
    public ResponseDto<Object> action(@Valid @RequestBody GoblinStoreMgtGoodsActionParam mgtGoodsActionParam) {
        String currentUid = CurrentUtil.getCurrentUid(), storeId = mgtGoodsActionParam.getStoreId();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) {
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        List<String> spuIdList = mgtGoodsActionParam.getSpuIdList();
        if (CollectionUtils.isEmpty(spuIdList)) {
            return ResponseDto.failure(ErrorMapping.get("149009"));
        }
        if (log.isDebugEnabled()) {
            log.debug("商品管理:SPU管理:[UID={},GoblinStoreMgtGoodsActionParam={}]", currentUid, JsonUtils.toJson(mgtGoodsActionParam));
        }
        List<String> spuNoList = CollectionUtil.arrayListString();
        switch (mgtGoodsActionParam.getAction()) {
            case "ONSHELVES":
                for (String spuId : spuIdList) {
                    GoblinGoodsInfoVo goodsInfoVo = goblinRedisUtils.getGoodsInfoVo(spuId);
                    if (null == goodsInfoVo || !goodsInfoVo.getDelFlg().equals("0")) {
                        log.warn("商品管理:SPU管理:上架警告:商品不存在或已删除[UID={},spuId={}]", currentUid, spuId);
                        return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品不存在或已删除");
                    }
                    if (!goodsInfoVo.getStoreId().equals(storeId)) {
                        log.warn("商品管理:SPU管理:上架警告:非本店铺商品，无权操作[UID={},spuId={}]", currentUid, spuId);
                        return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "非本店铺商品，无权操作");
                    }
                    if (goodsInfoVo.getShelvesStatus().equals("3")) {
                        log.warn("商品管理:SPU管理:上架警告:请先将商品下架后操作[UID={},spuId={}]", currentUid, spuId);
                        return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "无效操作，商品已上架");
                    }
                    spuNoList.add(goodsInfoVo.getSpuNo());
                }
                goblinstoreMgtGoodsService.goodsShelvesProcessing(mgtGoodsActionParam, currentUid, true, spuNoList);
                break;
            case "UNSHELVE":
                for (String spuId : spuIdList) {
                    GoblinGoodsInfoVo goodsInfoVo = goblinRedisUtils.getGoodsInfoVo(spuId);
                    if (null == goodsInfoVo || !goodsInfoVo.getDelFlg().equals("0")) {
                        log.warn("商品管理:SPU管理:下架警告:商品不存在或已删除[UID={},spuId={}]", currentUid, spuId);
                        return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品不存在或已删除");
                    }
                    if (!goodsInfoVo.getStoreId().equals(storeId)) {
                        log.warn("商品管理:SPU管理:下架警告:非本店铺商品，无权操作[UID={},spuId={}]", currentUid, spuId);
                        return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "非本店铺商品，无权操作");
                    }
                    if (!goodsInfoVo.getShelvesStatus().equals("3")) {// 非上架中不允许下架
                        log.warn("商品管理:SPU管理:下架警告:非上架中商品不允许此操作[UID={},spuId={}]", currentUid, spuId);
                        return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "非上架中商品不允许此操作");
                    }
                    spuNoList.add(goodsInfoVo.getSpuNo());
                }
                goblinstoreMgtGoodsService.goodsShelvesProcessing(mgtGoodsActionParam, currentUid, false, spuNoList);
                break;
            case "REMOVE":
                for (String spuId : spuIdList) {
                    GoblinGoodsInfoVo goodsInfoVo = goblinRedisUtils.getGoodsInfoVo(spuId);
                    if (null == goodsInfoVo || !goodsInfoVo.getDelFlg().equals("0")) {
                        log.warn("商品管理:SPU管理:删除警告:商品不存在或已删除[UID={},spuId={}]", currentUid, spuId);
                        return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品不存在或已删除");
                    }
                    if (!goodsInfoVo.getStoreId().equals(storeId)) {
                        log.warn("商品管理:SPU管理:删除警告:非本店铺商品，无权操作[UID={},spuId={}]", currentUid, spuId);
                        return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "非本店铺商品，无权操作");
                    }
                    if (goodsInfoVo.getShelvesStatus().equals("3")) {// 上架中不允许删除
                        log.warn("商品管理:SPU管理:删除警告:请先将商品下架后操作[UID={},spuId={}]", currentUid, spuId);
                        return ResponseDto.failure(ErrorMapping.get("149016"));
                    }
                    spuNoList.add(goodsInfoVo.getSpuNo());
                }
                goblinstoreMgtGoodsService.goodsRemove(mgtGoodsActionParam, currentUid, spuNoList);
                break;
            default:
                log.warn("商品管理:SPU管理:Invalid operation[UID={},mgtGoodsActionParam={}]", currentUid, JsonUtils.toJson(mgtGoodsActionParam));
                return ResponseDto.failure(ErrorMapping.get("149001"));
        }
        return ResponseDto.success();
    }

    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "SPU添加")
    @PutMapping("add")
    public ResponseDto<Object> add(@Valid @RequestBody GoblinStoreMgtGoodsAddParam storeMgtGoodsAddParam) {
        String currentUid = CurrentUtil.getCurrentUid();
        String storeId = storeMgtGoodsAddParam.getStoreId();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) {
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        if (log.isDebugEnabled()) {
            log.debug("商品管理:SPU添加:[GoblinStoreMgtGoodsAddParam={}]", JsonUtils.toJson(storeMgtGoodsAddParam));
        }
        if (CollectionUtils.isEmpty(storeMgtGoodsAddParam.getSkuParamList())) {
            return ResponseDto.failure(ErrorMapping.get("149006"));
        }
        if (CollectionUtils.isEmpty(storeMgtGoodsAddParam.getImageList())) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品图片不能为空");
        }
        String cateSid = storeMgtGoodsAddParam.getCateSid(), cateTid = storeMgtGoodsAddParam.getCateTid();
        List<GoblinSelfGoodsCategoryVo> selfGoodsCategoryVos = goblinStoreMgtExtraService.listCategoryVo();
        if (selfGoodsCategoryVos.stream().noneMatch(r -> r.getCateId().equals(storeMgtGoodsAddParam.getCateFid()) && r.getGrade().equals("1"))) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品分类1无效");
        }
        if (StringUtils.isNotBlank(cateSid) && selfGoodsCategoryVos.stream().noneMatch(r -> r.getCateId().equals(cateSid) && r.getGrade().equals("2"))) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品分类2无效");
        }
        if (StringUtils.isNotBlank(cateTid) && selfGoodsCategoryVos.stream().noneMatch(r -> r.getCateId().equals(cateTid) && r.getGrade().equals("3"))) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品分类3无效");
        }
        GoblinGoodsInfoVo mgtGoodsInfoVo = goblinMongoUtils.getMgtGoodsInfoVo(storeId, storeMgtGoodsAddParam.getName());
        if (null != mgtGoodsInfoVo) {
            return ResponseDto.failure(ErrorMapping.get("149007"));
        }
        if (storeMgtGoodsAddParam.getShelvesHandle().equals("3") && null == storeMgtGoodsAddParam.getShelvesTime()) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "预约上架时间未指定");
        }

        LocalDateTime now = LocalDateTime.now();
        GoblinGoodsInfoVo goodsInfoVo = storeMgtGoodsAddParam.initGoodsInfoVo();
        goodsInfoVo.setCreatedBy(currentUid);
        goodsInfoVo.setCreatedAt(now);

        ArrayList<GoblinGoodsSpecVo> goodsSpecVoList = ObjectUtil.getGoblinGoodsSpecVoArrayList();
        List<GoblinGoodsSkuInfoVo> goodsSkuInfoVoList = ObjectUtil.getGoblinGoodsSkuInfoVoArrayList();

        storeMgtGoodsAddParam.initGoodsSkuInfoVo(goodsInfoVo, goodsSkuInfoVoList, goodsSpecVoList);

        {// 标签处理
            List<String> goodsTagIdList = storeMgtGoodsAddParam.getTagList(),
                    goodsExtagIdList = storeMgtGoodsAddParam.getExtagList(),
                    goodsArtagIdList = storeMgtGoodsAddParam.getExtagList();
            if (!CollectionUtils.isEmpty(goodsTagIdList)) {
                List<GoblinSelfTagVo> selfGoodsTagVos = goblinRedisUtils.getSelfTagVos();
                List<GoblinGoodsTagVo> goodsTagVoList = ObjectUtil.getGoblinGoodsTagVoArrayList();
                for (int i = 0; i < goodsTagIdList.size(); i++)
                    for (GoblinSelfTagVo r : selfGoodsTagVos)
                        if (r.getTagId().equals(goodsTagIdList.get(i)) && r.getTagBelong().equals("0")) {
                            goodsTagVoList.add(GoblinGoodsTagVo.getNew().copy(r).setSort(i));
                            break;
                        }
                goodsInfoVo.setTagVoList(goodsTagVoList);
            }
            if (!CollectionUtils.isEmpty(goodsExtagIdList)) {
                List<GoblinSelfTagVo> selfExtagVos = goblinRedisUtils.getSelfExtagVos();
                List<GoblinGoodsExtagVo> goodsExtagVoList = ObjectUtil.getGoblinGoodsExtagVoArrayList();
                for (int i = 0; i < goodsExtagIdList.size(); i++)
                    for (GoblinSelfTagVo r : selfExtagVos)
                        if (r.getTagId().equals(goodsExtagIdList.get(i)) && r.getTagBelong().equals("1") && !r.getTagType().equals("5")) {
                            goodsExtagVoList.add(GoblinGoodsExtagVo.getNew().copy(r).setSort(i));
                            break;
                        }
                goodsInfoVo.setExtagVoList(goodsExtagVoList);
            }
            if (!CollectionUtils.isEmpty(goodsArtagIdList)) {
                List<GoblinSelfTagVo> selfExtagVos = goblinRedisUtils.getSelfExtagVos();
                List<GoblinGoodsExtagVo> goodsArtagVoList = ObjectUtil.getGoblinGoodsExtagVoArrayList();
                for (int i = 0; i < goodsArtagIdList.size(); i++)
                    for (GoblinSelfTagVo r : selfExtagVos)
                        if (r.getTagId().equals(goodsArtagIdList.get(i)) && r.getTagBelong().equals("1")) {
                            goodsArtagVoList.add(GoblinGoodsExtagVo.getNew().copy(r).setSort(i));
                            break;
                        }
                goodsInfoVo.setArtagVoList(goodsArtagVoList);
            }
        }

        // 服务保障处理
        List<String> ssidList = storeMgtGoodsAddParam.getSsidList();
        if (!CollectionUtils.isEmpty(ssidList)) {
            goodsInfoVo.setServiceSupportVoList(goblinMongoUtils.getServiceSupportVos(ssidList));
        }

        goblinstoreMgtGoodsService.goodsAdd(goodsInfoVo, goodsSkuInfoVoList);

        return ResponseDto.success(goodsInfoVo.getSpuId());
    }

    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "SPU详情")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "storeId", value = "店铺ID"),
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "spuId", value = "商品ID"),
    })
    @GetMapping("info")
    public ResponseDto<GoblinStoreMgtGoodsInfoVo> info(@NotBlank(message = "店铺ID不能为空") @RequestParam String storeId,
                                                       @NotBlank(message = "商品ID不能为空") @RequestParam String spuId) {
        if (!goblinRedisUtils.hasStoreId(CurrentUtil.getCurrentUid(), storeId)) {
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        if (log.isDebugEnabled()) {
            log.debug("商品管理:SPU详情:[spuId={}]", spuId);
        }
        return ResponseDto.success(goblinstoreMgtGoodsService.goodsInfo(storeId, spuId));
    }

    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "商品编辑:SPU编辑", notes = "只修改商品信息，不包含规格相关信息")
    @PostMapping("edit_spu")
    public ResponseDto<Object> editSpu(@Valid @RequestBody GoblinStoreMgtGoodsAddParam storeMgtGoodsAddParam) {
        String currentUid = CurrentUtil.getCurrentUid();
        String storeId = storeMgtGoodsAddParam.getStoreId();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) {
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        if (CollectionUtils.isEmpty(storeMgtGoodsAddParam.getImageList())) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品图片不能为空");
        }
        GoblinGoodsInfoVo mgtGoodsInfoVo = goblinMongoUtils.getMgtGoodsInfoVo(storeId, storeMgtGoodsAddParam.getName());
        if (null != mgtGoodsInfoVo && !mgtGoodsInfoVo.getSpuId().equals(storeMgtGoodsAddParam.getSpuId())) {
            return ResponseDto.failure(ErrorMapping.get("149007"));
        }
        String cateSid = storeMgtGoodsAddParam.getCateSid(), cateTid = storeMgtGoodsAddParam.getCateTid();
        List<GoblinSelfGoodsCategoryVo> selfGoodsCategoryVos = goblinStoreMgtExtraService.listCategoryVo();
        if (selfGoodsCategoryVos.stream().noneMatch(r -> r.getCateId().equals(storeMgtGoodsAddParam.getCateFid()) && r.getGrade().equals("1"))) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品分类1无效");
        }
        if (StringUtils.isNotBlank(cateSid) && selfGoodsCategoryVos.stream().noneMatch(r -> r.getCateId().equals(cateSid) && r.getGrade().equals("2"))) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品分类2无效");
        }
        if (StringUtils.isNotBlank(cateTid) && selfGoodsCategoryVos.stream().noneMatch(r -> r.getCateId().equals(cateTid) && r.getGrade().equals("3"))) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品分类3无效");
        }
        GoblinGoodsInfoVo goodsInfoVo;
        if (StringUtils.isBlank(storeMgtGoodsAddParam.getSpuId())
                || null == (goodsInfoVo = goblinRedisUtils.getGoodsInfoVo(storeMgtGoodsAddParam.getSpuId()))
                || !goodsInfoVo.getDelFlg().equals("0")) {
            return ResponseDto.failure(ErrorMapping.get("149010"));
        }
        if (log.isDebugEnabled()) {
            log.debug("商品管理:商品编辑:SPU编辑:[GoblinStoreMgtGoodsAddParam={}]", JsonUtils.toJson(storeMgtGoodsAddParam));
        }
        return ResponseDto.success(goblinstoreMgtGoodsService.goodsEditSpu(currentUid, storeMgtGoodsAddParam, goodsInfoVo));
    }

    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "商品编辑:SKU编辑", notes = "只修改单品信息，不包含商品信息")
    @PostMapping("edit_sku")
    public ResponseDto<Object> editSku(@Valid @RequestBody GoblinStoreMgtGoodsEditSkuParam storeMgtGoodsEditSkuParam) {
        String currentUid = CurrentUtil.getCurrentUid();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeMgtGoodsEditSkuParam.getStoreId())) {
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        // TODO: 2022/1/5 zhanggb +分类-ISBN校验

        GoblinGoodsSkuInfoVo mgtGoodsSkuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(storeMgtGoodsEditSkuParam.getSkuId());
        if (StringUtils.isBlank(storeMgtGoodsEditSkuParam.getSkuId())
                || null == mgtGoodsSkuInfoVo || !mgtGoodsSkuInfoVo.getDelFlg().equals("0")
                || !mgtGoodsSkuInfoVo.getStoreId().equals(storeMgtGoodsEditSkuParam.getStoreId())) {
            return ResponseDto.failure(ErrorMapping.get("149011"));
        }
        GoblinGoodsInfoVo goodsInfoVo = goblinRedisUtils.getGoodsInfoVo(mgtGoodsSkuInfoVo.getSpuId());
        if (null == goodsInfoVo || !goodsInfoVo.getDelFlg().equals("0")) {
            return ResponseDto.failure(ErrorMapping.get("149010"));
        }

        if (log.isDebugEnabled()) {
            log.debug("商品管理:商品编辑:SKU编辑:[GoblinStoreMgtGoodsEditSkuParam={}]", JsonUtils.toJson(storeMgtGoodsEditSkuParam));
        }
        storeMgtGoodsEditSkuParam.setStock(mgtGoodsSkuInfoVo.getStock());
        storeMgtGoodsEditSkuParam.setSkuStock(mgtGoodsSkuInfoVo.getSkuStock());
        String paramSkuId = storeMgtGoodsEditSkuParam.getSkuId();
        Integer operStock = storeMgtGoodsEditSkuParam.getOperStock();
        if (null != operStock && operStock != 0) {// 处理库存
            int operStockVal = Math.abs(operStock);
            Integer stock = mgtGoodsSkuInfoVo.getSkuStock();// 总库存
            Integer skuStock = mgtGoodsSkuInfoVo.getSkuStock();// SKU总库存

            int surplusStock = goblinRedisUtils.getSkuStock(null, paramSkuId);// 当前剩余库存
            if (operStock < 0 && surplusStock > 0 && surplusStock >= operStockVal) {// SKU实时库存充足时允许扣减
                if (goblinRedisUtils.decrSkuStock(null, paramSkuId, operStockVal) < 0) {// 过程中库存不足时，回滚库存，编辑无效
                    goblinRedisUtils.incrSkuStock(null, paramSkuId, operStockVal);
                    return ResponseDto.failure(ErrorMapping.get("149012"));
                } else {
                    storeMgtGoodsEditSkuParam.setSkuStock(skuStock - operStockVal);
                    storeMgtGoodsEditSkuParam.setStock(stock - operStockVal);
                }
            } else if (operStock > 0) {// 增加
                goblinRedisUtils.incrSkuStock(null, paramSkuId, operStockVal);
                storeMgtGoodsEditSkuParam.setSkuStock(skuStock + operStockVal);
                storeMgtGoodsEditSkuParam.setStock(stock + operStockVal);
            } else {
                return ResponseDto.failure(ErrorMapping.get("149012"));
            }
        }

        List<GoblinGoodsSpecDto> paramSkuSpecList = storeMgtGoodsEditSkuParam.getSkuSpecList();
        List<String> skuIdList = goodsInfoVo.getSkuIdList();
        Map<String, List<GoblinGoodsSpecDto>> otherSkuSpecListMap = new HashMap<>();
        Map<String, String> delSpuSpecMap = CollectionUtil.mapStringString();
        boolean beUpdateSpuSpecFlg = false;
        for (String skuId : skuIdList) {// 比对所有SKU规格信息
            GoblinGoodsSkuInfoVo existMgtGoodsSkuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(skuId);
            List<GoblinGoodsSpecDto> skuSpecList = existMgtGoodsSkuInfoVo.getSkuSpecList();
            otherSkuSpecListMap.put(skuId, skuSpecList);
            Map<String, String> editBefSkuSpecMap = skuSpecList.stream()
                    .collect(Collectors.toMap(GoblinGoodsSpecDto::getSpecName, GoblinGoodsSpecDto::getSpecVname, (k1, k2) -> k2));
            if (paramSkuSpecList.size() != editBefSkuSpecMap.size()) {
                log.warn("商品管理:商品编辑:SKU编辑:规格信息不一致[skuId={},editBefSkuSpecMap={},paramGoodsSpecDto={}]",
                        paramSkuId, editBefSkuSpecMap, paramSkuSpecList);
                return ResponseDto.failure(ErrorMapping.get("149014"));
            }
            boolean diffSpecFlg = false;
            for (GoblinGoodsSpecDto paramGoodsSpecDto : paramSkuSpecList) {// 入参规格逐个与当前商品所有SKU规格比对
                String editBefSkuSpecVname = editBefSkuSpecMap.get(paramGoodsSpecDto.getSpecName());
                if (null == editBefSkuSpecVname) {// 入参规格名称不存在于原SKU中，则参数有误
                    log.warn("商品管理:商品编辑:SKU编辑:规格信息不一致[skuId={},editBefSkuSpecMap={},paramGoodsSpecDto={}]",
                            paramSkuId, editBefSkuSpecMap, paramGoodsSpecDto);
                    return ResponseDto.failure(ErrorMapping.get("149014"));
                }
                if (!editBefSkuSpecVname.equals(paramGoodsSpecDto.getSpecVname())) {
                    diffSpecFlg = true;// 多个规格中只要存在一个不一致，即可跳过，标记为允许添加
                    break;
                }
            }
            if (skuId.equals(paramSkuId)) {
                otherSkuSpecListMap.remove(skuId);
                if (diffSpecFlg) {// 更改了规格，则同步修改SPU里的规格信息（新增 + 删除，不做更新）
                    Map<String, String> paramSkuSpecMap = paramSkuSpecList.stream()
                            .collect(Collectors.toMap(GoblinGoodsSpecDto::getSpecName, GoblinGoodsSpecDto::getSpecVname, (k1, k2) -> k2));
                    List<GoblinGoodsSpecVo> specVoList = goodsInfoVo.getSpecVoList();// SPU规格集
                    for (Map.Entry<String, String> entry : editBefSkuSpecMap.entrySet()) {
                        String specName = entry.getKey();
                        String oldSpecVname = entry.getValue();
                        for (GoblinGoodsSpecVo specVo : specVoList) {// SPU规格集遍历
                            if (specVo.getSpecName().equals(specName)) {// SPU规格集中筛选出当前所编辑SKU的规格
                                List<GoblinGoodsSpecValueVo> specValues = specVo.getSpecValues();// 筛选得到的SPU的规格对应值集合
                                String newSpecVname = paramSkuSpecMap.get(specVo.getSpecName());
                                if (!newSpecVname.equals(oldSpecVname)) {
                                    // 规格值集合中当前所编辑SKU规格值的索引
                                    int idx = IntStream.range(0, specValues.size())
                                            .filter(i -> specValues.get(i).getSpecVname().equals(newSpecVname)).findFirst().orElse(-1);
                                    if (idx == -1) {// 不存在则新增且处理旧规格值，存在则不做处理
                                        beUpdateSpuSpecFlg = true;

                                        specValues.add(GoblinGoodsSpecValueVo.getNew().setSpecVname(newSpecVname).setSpecVsort(specValues.size() + 2));
                                    }

                                    boolean toDelOldSpecVnameFlg = true;// 其他SKU中只要存在该规格值，即不可删除该规格值
                                    Set<Map.Entry<String, List<GoblinGoodsSpecDto>>> entries = otherSkuSpecListMap.entrySet();
                                    for (Map.Entry<String, List<GoblinGoodsSpecDto>> ent : entries) {
                                        for (GoblinGoodsSpecDto specDto : ent.getValue()) {
                                            if (specDto.getSpecName().equals(specName) && specDto.getSpecVname().equals(oldSpecVname)) {
                                                toDelOldSpecVnameFlg = false;
                                            }
                                        }
                                    }
                                    if (toDelOldSpecVnameFlg) {
                                        specValues.removeIf(rmr -> rmr.getSpecVname().equals(oldSpecVname));
                                        delSpuSpecMap.put(specName, oldSpecVname);
                                        beUpdateSpuSpecFlg = true;
                                    }
                                }
                            }
                        }
                    }
                }
                continue;
            }
            if (!diffSpecFlg) {
                log.warn("商品管理:商品编辑:SKU编辑:重复的规格信息[skuId={},editBefSkuSpecMap={},paramSkuSpecMap={}]",
                        paramSkuId, editBefSkuSpecMap, JsonUtils.toJson(paramSkuSpecList));
                return ResponseDto.failure(ErrorMapping.get("149015"));
            }
        }
        if (goblinstoreMgtGoodsService.goodsEditSku(currentUid, storeMgtGoodsEditSkuParam, goodsInfoVo, delSpuSpecMap, beUpdateSpuSpecFlg)) {
            mgtGoodsSkuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(paramSkuId);
            mgtGoodsSkuInfoVo.setSurplusStock(goblinRedisUtils.getSkuStock(null, paramSkuId));
            return ResponseDto.success(mgtGoodsSkuInfoVo);
        } else {
            if (null != operStock && operStock != 0) {// 处理库存:回滚
                int operStockVal = Math.abs(operStock);
                if (operStock > 0) {// 增加的减回去
                    goblinRedisUtils.decrSkuStock(null, paramSkuId, operStockVal);
                } else {// 扣减的加回去
                    goblinRedisUtils.incrSkuStock(null, paramSkuId, operStockVal);
                }
            }
            return ResponseDto.failure(ErrorMapping.get("149013"));
        }
    }

    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "商品编辑:SKU添加")
    @PutMapping("edit_sku/add")
    public ResponseDto<Object> editSkuAdd(@Valid @RequestBody GoblinStoreMgtGoodsEditSkuParam storeMgtGoodsEditSkuParam) {
        String currentUid = CurrentUtil.getCurrentUid();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeMgtGoodsEditSkuParam.getStoreId())) {
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        if (storeMgtGoodsEditSkuParam.getPrice().compareTo(BigDecimal.ZERO) <= 0
                || storeMgtGoodsEditSkuParam.getPriceMember().compareTo(BigDecimal.ZERO) <= 0) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "价格无效");
        }
        if (null == storeMgtGoodsEditSkuParam.getStock() || storeMgtGoodsEditSkuParam.getStock() <= 0) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "库存无效");
        }
        GoblinGoodsInfoVo goodsInfoVo = goblinRedisUtils.getGoodsInfoVo(storeMgtGoodsEditSkuParam.getSpuId());
        if (null == goodsInfoVo || !goodsInfoVo.getDelFlg().equals("0")
                || !goodsInfoVo.getStoreId().equals(storeMgtGoodsEditSkuParam.getStoreId())) {
            return ResponseDto.failure(ErrorMapping.get("149010"));
        }
        List<String> skuIdList = goodsInfoVo.getSkuIdList();
        List<GoblinGoodsSpecDto> paramSkuSpecDtoList = storeMgtGoodsEditSkuParam.getSkuSpecList();
        for (String skuId : skuIdList) {// 比对所有SKU规格信息
            GoblinGoodsSkuInfoVo mgtGoodsSkuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(skuId);
            if (mgtGoodsSkuInfoVo.getSkuSpecList().size() != paramSkuSpecDtoList.size()) {
                log.warn("商品管理:商品编辑:SKU添加:规格信息有误[skuSpecMap={},paramSkuSpecMap={}]", JsonUtils.toJson(mgtGoodsSkuInfoVo.getSkuSpecList()), JsonUtils.toJson(paramSkuSpecDtoList));
                return ResponseDto.failure(ErrorMapping.get("149014"));
            }

            Map<String, String> skuSpecMap = mgtGoodsSkuInfoVo.getSkuSpecList().stream()
                    .collect(Collectors.toMap(GoblinGoodsSpecDto::getSpecName, GoblinGoodsSpecDto::getSpecVname, (k1, k2) -> k2));

            boolean diffSpecFlg = false;
            for (GoblinGoodsSpecDto goodsSpecDto : paramSkuSpecDtoList) {
                String skuSpecVname = skuSpecMap.get(goodsSpecDto.getSpecName());
                if (null == skuSpecVname) {
                    return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "规格无效");
                }
                if (!skuSpecVname.equals(goodsSpecDto.getSpecVname())) {
                    diffSpecFlg = true;// 多个规格中只要存在一个不一致，即可跳过，标记为允许添加
                    break;
                }
            }
            if (!diffSpecFlg) {
                log.warn("商品管理:商品编辑:SKU添加:重复的规格信息[skuSpecMap={},paramSkuSpecMap={}]", skuSpecMap, JsonUtils.toJson(paramSkuSpecDtoList));
                return ResponseDto.failure(ErrorMapping.get("149015"));
            }
        }
        List<GoblinGoodsSpecVo> specVoList = goodsInfoVo.getSpecVoList();
        if (CollectionUtils.isEmpty(specVoList)) {
            if (null == specVoList) specVoList = ObjectUtil.getGoblinGoodsSpecVoArrayList();
            int size = paramSkuSpecDtoList.size();
            for (int i = 0; i < size; i++) {
                GoblinGoodsSpecDto specDto = paramSkuSpecDtoList.get(i);
                ArrayList<GoblinGoodsSpecValueVo> specValueVoList = ObjectUtil.getGoblinGoodsSpecValueVoArrayList();
                specValueVoList.add(GoblinGoodsSpecValueVo.getNew().setSpecVname(specDto.getSpecVname()).setSpecVsort(i));
                specVoList.add(GoblinGoodsSpecVo.getNew().setSpecName(specDto.getSpecName()).setSpecSort(i).setSpecValues(specValueVoList));
            }
        } else {
            Map<String, String> paramSkuSpecMap = paramSkuSpecDtoList.stream()
                    .collect(Collectors.toMap(GoblinGoodsSpecDto::getSpecName, GoblinGoodsSpecDto::getSpecVname, (k1, k2) -> k2));
            for (GoblinGoodsSpecVo specVo : specVoList) {// 同步添加SPU规格信息
                List<GoblinGoodsSpecValueVo> specValues = specVo.getSpecValues();
                String paramSkuSpecVname = paramSkuSpecMap.get(specVo.getSpecName());
                if (StringUtils.isBlank(paramSkuSpecVname)) {
                    return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "规格无效");
                }
                if (specValues.stream().noneMatch(r -> r.getSpecVname().equals(paramSkuSpecVname))) {
                    specValues.add(GoblinGoodsSpecValueVo.getNew().setSpecVname(paramSkuSpecVname).setSpecVsort(specValues.size()));
                }
            }
        }

        if (log.isDebugEnabled()) {
            log.debug("商品管理:商品编辑:SKU添加:[GoblinStoreMgtGoodsEditSkuParam={}]", JsonUtils.toJson(storeMgtGoodsEditSkuParam));
        }
        goblinstoreMgtGoodsService.goodsEditSkuAdd(currentUid, storeMgtGoodsEditSkuParam, goodsInfoVo);
        return ResponseDto.success();
    }

    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "商品编辑:SKU删除")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "storeId", value = "店铺ID"),
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "skuId", value = "单品ID"),
    })
    @PostMapping("edit_sku/del")
    public ResponseDto<Object> editSkuDel(@NotBlank(message = "店铺ID不能为空") String storeId,
                                          @NotBlank(message = "单品ID不能为空") String skuId) {
        String currentUid = CurrentUtil.getCurrentUid();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) {
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        GoblinGoodsSkuInfoVo mgtGoodsSkuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(skuId);
        if (null == mgtGoodsSkuInfoVo || !mgtGoodsSkuInfoVo.getDelFlg().equals("0") || !mgtGoodsSkuInfoVo.getStoreId().equals(storeId)) {
            return ResponseDto.failure(ErrorMapping.get("149011"));
        }
        if (mgtGoodsSkuInfoVo.getShelvesStatus().equals("3")) {
            return ResponseDto.failure(ErrorMapping.get("149016"));
        }
        GoblinGoodsInfoVo mgtGoodsInfoVo = goblinRedisUtils.getGoodsInfoVo(mgtGoodsSkuInfoVo.getSpuId());
        if (null == mgtGoodsInfoVo || !mgtGoodsInfoVo.getDelFlg().equals("0")) {
            log.warn("商品管理:商品编辑:SKU删除警告:SPU不存在或已删除[uid={},skuId={}]", currentUid, skuId);
            return ResponseDto.failure(ErrorMapping.get("149010"));
        }
        boolean delResultFlg = goblinstoreMgtGoodsService.goodsEditSkuDel(currentUid, mgtGoodsSkuInfoVo, mgtGoodsInfoVo);
        return delResultFlg ? ResponseDto.success() : ResponseDto.failure(ErrorMapping.get("149003"));
    }

//    @ApiOperationSupport(order = 10)
//    @ApiOperation(value = "商品编辑:SKU批改")
//    @ApiImplicitParams({
//            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "storeId", value = "店铺ID"),
//            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "spuId", value = "商品ID"),
//            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "batField", value = "批量修改属性"),
//            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "batFieldVal", value = "批量修改属性值"),
//    })
//    @PostMapping("edit_sku/bat")
//    public ResponseDto<Object> editSkuBat(@NotBlank(message = "店铺ID不能为空") String storeId,
//                                          @NotBlank(message = "商品ID不能为空") String spuId,
//                                          @NotBlank(message = "批量修改属性不能为空") String batField,
//                                          @NotBlank(message = "批量修改属性值不能为空") String batFieldVal) {
//        if (!goblinRedisUtils.hasStoreId(CurrentUtil.getCurrentUid(), storeId)) {
//            return ResponseDto.failure(ErrorMapping.get("149002"));
//        }
//        return ResponseDto.success(goblinstoreMgtGoodsService.goodsEditSkuBat(spuId, batField, batFieldVal));
//    }
}
