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

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.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.ResponseDto;
import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtGoodsSqbAddParam;
import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtGoodsSqbAddSkuParam;
import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtGoodsSqbEditSkuParam;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.service.manage.IGoblinStoreMgtExtraService;
import com.liquidnet.service.goblin.service.manage.IGoblinStoreMgtSqbGoodsService;
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.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 收钱吧商品管理
 */
@ApiSupport(order = 149005)
@Api(tags = "收钱吧商品管理")
@Slf4j
@Validated
@RestController
@RequestMapping("store/mgt/sqb/goods")
public class GoblinStoreMgtSqbGoodsController {

    @Autowired
    private IGoblinStoreMgtSqbGoodsService goblinstoreMgtSqbGoodsService;
    @Autowired
    private IGoblinStoreMgtExtraService goblinStoreMgtExtraService;
    @Autowired
    private GoblinRedisUtils goblinRedisUtils;
    @Autowired
    private GoblinMongoUtils goblinMongoUtils;

    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "SPU添加-收钱吧商品")
    @PostMapping("add")
    public ResponseDto<Object> add(@Valid @RequestBody GoblinStoreMgtGoodsSqbAddParam mgtGoodsSqbAddParam) {
        String currentUid = CurrentUtil.getCurrentUid(), storeId = mgtGoodsSqbAddParam.getStoreId();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) return ResponseDto.failure(ErrorMapping.get("149002"));
        if (log.isDebugEnabled()) {
            log.debug("收钱吧商品管理:SPU添加:[GoblinStoreMgtGoodsSqbAddParam={}]", JsonUtils.toJson(mgtGoodsSqbAddParam));
        }

        GoblinStoreMgtGoodsSqbAddSkuParam skuParam = mgtGoodsSqbAddParam.getSkuParam();
        if (Objects.isNull(skuParam)) {
            return ResponseDto.failure(ErrorMapping.get("149006"));
        }
        if (Objects.isNull(skuParam.getEffectAt()) || Objects.isNull(skuParam.getExpireAt())) {
            return ResponseDto.failure(ErrorMapping.get("149025"));
        }
        LocalDateTime effectAt = DateUtil.Formatter.yyyyMMddHHmmss.parse(skuParam.getEffectAt());
        LocalDateTime expireAt = DateUtil.Formatter.yyyyMMddHHmmss.parse(skuParam.getExpireAt());
        if (effectAt.isAfter(expireAt) || expireAt.isBefore(LocalDateTime.now())) {
            return ResponseDto.failure(ErrorMapping.get("149026"));
        }
        if (CollectionUtils.isEmpty(mgtGoodsSqbAddParam.getImageList())) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品图片不能为空");
        }

        String cateFid = mgtGoodsSqbAddParam.getCateFid(), cateSid = mgtGoodsSqbAddParam.getCateSid(), cateTid = mgtGoodsSqbAddParam.getCateTid();
        List<GoblinSelfGoodsCategoryVo> selfGoodsCategoryVos = goblinStoreMgtExtraService.listCategoryVo();
        if (selfGoodsCategoryVos.stream().noneMatch(r -> r.getCateId().equals(cateFid) && r.getGrade().equals("1"))) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品一级分类无效");
        }
        if (StringUtils.isNotBlank(cateSid)
                && selfGoodsCategoryVos.stream().noneMatch(r -> r.getCateId().equals(cateSid) && r.getGrade().equals("2"))) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品二级分类无效");
        }
        if (StringUtils.isNotBlank(cateTid)
                && selfGoodsCategoryVos.stream().noneMatch(r -> r.getCateId().equals(cateTid) && r.getGrade().equals("3"))) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品三级分类无效");
        }

        if (goblinMongoUtils.countMgtGoodsInfoVo(mgtGoodsSqbAddParam.getName()) > 0) {
            return ResponseDto.failure(ErrorMapping.get("149007"));
        }
        if (mgtGoodsSqbAddParam.getShelvesHandle().equals("3") && null == mgtGoodsSqbAddParam.getShelvesTime()) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "预约上架时间未指定");
        }

        GoblinGoodsInfoVo goodsInfoVo = mgtGoodsSqbAddParam.initGoodsInfoVo(currentUid, LocalDateTime.now());
        ArrayList<GoblinGoodsSpecVo> goodsSpecVoList = ObjectUtil.getGoblinGoodsSpecVoArrayList();
        List<GoblinGoodsSkuInfoVo> goodsSkuInfoVoList = ObjectUtil.getGoblinGoodsSkuInfoVoArrayList();
        mgtGoodsSqbAddParam.initGoodsSkuInfoVo(goodsInfoVo, goodsSkuInfoVoList, goodsSpecVoList);

        List<String> goodsTagIdList = mgtGoodsSqbAddParam.getTagList(),
                goodsExtagIdList = mgtGoodsSqbAddParam.getExtagList(),
                goodsArtagIdList = mgtGoodsSqbAddParam.getArtagList();
        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 = mgtGoodsSqbAddParam.getSsidList();
        if (!CollectionUtils.isEmpty(ssidList)) {
            goodsInfoVo.setServiceSupportVoList(goblinMongoUtils.getServiceSupportVos(ssidList));
        }
        goblinstoreMgtSqbGoodsService.sqbGoodsAdd(goodsInfoVo, goodsSkuInfoVoList);
        return ResponseDto.success(goodsInfoVo.getSpuId());
    }

    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "商品编辑:SPU编辑-收钱吧商品", notes = "只修改商品信息，不包含价格库存相关信息")
    @PutMapping("edit_spu")
    public ResponseDto<Object> editSpu(@Valid @RequestBody GoblinStoreMgtGoodsSqbAddParam mgtGoodsSqbEditParam) {
        String currentUid = CurrentUtil.getCurrentUid(), storeId = mgtGoodsSqbEditParam.getStoreId();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) return ResponseDto.failure(ErrorMapping.get("149002"));

        GoblinGoodsInfoVo mgtGoodsInfoVo;
        if (StringUtils.isBlank(mgtGoodsSqbEditParam.getSpuId())
                || null == (mgtGoodsInfoVo = goblinRedisUtils.getGoodsInfoVo(mgtGoodsSqbEditParam.getSpuId()))
                || !mgtGoodsInfoVo.getStoreId().equals(storeId)
                || !mgtGoodsInfoVo.getDelFlg().equals("0")) {
            return ResponseDto.failure(ErrorMapping.get("149010"));
        }
        if (mgtGoodsInfoVo.getSpuType() != 2) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "无效操作，该商品非券类商品");
        }
        if (!mgtGoodsInfoVo.getName().equals(mgtGoodsSqbEditParam.getName())
                && goblinMongoUtils.countMgtGoodsInfoVo(mgtGoodsSqbEditParam.getName()) > 0) {
            return ResponseDto.failure(ErrorMapping.get("149007"));
        }
        if (!mgtGoodsSqbEditParam.getShelvesHandle().equals(mgtGoodsInfoVo.getShelvesHandle())
                && mgtGoodsInfoVo.getShelvesStatus().equals("3")) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "上架处理方式只限商品未上架时变更");
        }

        String cateFid = mgtGoodsSqbEditParam.getCateFid(), cateSid = mgtGoodsSqbEditParam.getCateSid(), cateTid = mgtGoodsSqbEditParam.getCateTid();
        List<GoblinSelfGoodsCategoryVo> selfGoodsCategoryVos = goblinStoreMgtExtraService.listCategoryVo();
        if (selfGoodsCategoryVos.stream().noneMatch(r -> r.getCateId().equals(cateFid) && r.getGrade().equals("1"))) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品一级分类无效");
        }
        if (StringUtils.isNotBlank(cateSid)
                && selfGoodsCategoryVos.stream().noneMatch(r -> r.getCateId().equals(cateSid) && r.getGrade().equals("2"))) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品二级分类无效");
        }
        if (StringUtils.isNotBlank(cateTid)
                && selfGoodsCategoryVos.stream().noneMatch(r -> r.getCateId().equals(cateTid) && r.getGrade().equals("3"))) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "商品三级分类无效");
        }

        if (log.isDebugEnabled()) {
            log.debug("收钱吧商品管理:商品编辑:SPU编辑:[GoblinStoreMgtGoodsSqbAddParam={}]", JsonUtils.toJson(mgtGoodsSqbEditParam));
        }
        boolean resultFlg = goblinstoreMgtSqbGoodsService.sqbGoodsEditSpu(currentUid, mgtGoodsSqbEditParam, mgtGoodsInfoVo);
        return resultFlg ? ResponseDto.success() : ResponseDto.failure();
    }

    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "商品编辑:SKU编辑-收钱吧商品", notes = "只修改单品信息，不包含商品信息")
    @PostMapping("edit_sku")
    public ResponseDto<Object> editSku(@Valid @RequestBody GoblinStoreMgtGoodsSqbEditSkuParam mgtGoodsSqbEditSkuParam) {
        String currentUid = CurrentUtil.getCurrentUid(), storeId = mgtGoodsSqbEditSkuParam.getStoreId();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) {
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        String paramSkuId = mgtGoodsSqbEditSkuParam.getSkuId();
        GoblinGoodsSkuInfoVo mgtGoodsSkuInfoVo;
        if (StringUtils.isBlank(paramSkuId)
                || null == (mgtGoodsSkuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(paramSkuId))
                || !mgtGoodsSkuInfoVo.getStoreId().equals(storeId)
                || !mgtGoodsSkuInfoVo.getDelFlg().equals("0")) {
            return ResponseDto.failure(ErrorMapping.get("149011"));
        }
        if (mgtGoodsSkuInfoVo.getSkuType() != 2) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "无效操作，该商品非券类商品");
        }
        if (log.isDebugEnabled()) {
            log.debug("收钱吧商品管理:商品编辑:SKU编辑:[GoblinStoreMgtGoodsSqbEditSkuParam={}]", JsonUtils.toJson(mgtGoodsSqbEditSkuParam));
        }
        GoblinGoodsInfoVo goodsInfoVo = goblinRedisUtils.getGoodsInfoVo(mgtGoodsSkuInfoVo.getSpuId());
        mgtGoodsSqbEditSkuParam.setStock(mgtGoodsSkuInfoVo.getStock());
        mgtGoodsSqbEditSkuParam.setSkuStock(mgtGoodsSkuInfoVo.getSkuStock());
        Integer operStock = mgtGoodsSqbEditSkuParam.getOperStock();
        if (null != operStock && operStock != 0) {
            int operStockVal = Math.abs(operStock);
            Integer stock = mgtGoodsSkuInfoVo.getStock();
            Integer skuStock = mgtGoodsSkuInfoVo.getSkuStock();

            int surplusStock = goblinRedisUtils.getSkuStock(null, paramSkuId);
            if (operStock < 0 && surplusStock > 0 && surplusStock >= operStockVal) {
                if (goblinRedisUtils.decrSkuStock(null, paramSkuId, operStockVal) < 0) {
                    goblinRedisUtils.incrSkuStock(null, paramSkuId, operStockVal);
                    return ResponseDto.failure(ErrorMapping.get("149012"));
                } else {
                    mgtGoodsSqbEditSkuParam.setSkuStock(skuStock - operStockVal);
                    mgtGoodsSqbEditSkuParam.setStock(stock - operStockVal);
                }
            } else if (operStock > 0) {
                goblinRedisUtils.incrSkuStock(null, paramSkuId, operStockVal);
                mgtGoodsSqbEditSkuParam.setSkuStock(skuStock + operStockVal);
                mgtGoodsSqbEditSkuParam.setStock(stock + operStockVal);
            } else {
                return ResponseDto.failure(ErrorMapping.get("149012"));
            }
        }

        if (goblinstoreMgtSqbGoodsService.sqbGoodsEditSku(currentUid, mgtGoodsSqbEditSkuParam, goodsInfoVo)) {
            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"));
        }
    }
}
