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

import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.constant.LnsRegex;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.goblin.constant.GoblinGoodsShowInMallHelper;
import com.liquidnet.service.goblin.dto.GoblinGoodsSpecDto;
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 io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@ApiModel(value = "GoblinStoreMgtGoodsAddParam", description = "商品管理:添加商品入参")
@Data
public class GoblinStoreMgtGoodsAddParam implements Serializable {
    private static final long serialVersionUID = -5101611616626164702L;
    @ApiModelProperty(position = 10, required = true, value = "店铺ID")
    @NotNull(message = "店铺ID不能为空")
    private String storeId;
    @ApiModelProperty(position = 11, required = false, value = "商品ID[编辑时必传]")
    private String spuId;

    /**
     * ---------------------------- 基本信息 ----------------------------
     **/

    @ApiModelProperty(position = 12, required = true, value = "商品名称[36]")
    @NotBlank(message = "商品名称不能为空")
    @Size(max = 36, message = "商品名称长度超限")
    private String name;
    @ApiModelProperty(position = 13, required = false, value = "商品名称[128]")
    @Size(max = 128, message = "商品副名称长度超限")
    private String subtitle;
    @ApiModelProperty(position = 14, required = false, value = "商品销售价-原价[20,2]")
    private BigDecimal sellPrice;

    @ApiModelProperty(position = 15, required = true, value = "商品一级分类ID[30]")
    @NotBlank(message = "商品分类ID不能为空")
    private String cateFid;
    @ApiModelProperty(position = 16, required = true, value = "商品二级分类ID[30]")
    private String cateSid;
    @ApiModelProperty(position = 17, required = true, value = "商品三级分类ID[30]")
    private String cateTid;

    @ApiModelProperty(position = 18, required = false, value = "商品简介[256]", example = "商品简介...")
    @Size(max = 256, message = "商品简介内容过长")
    private String intro;

    @ApiModelProperty(position = 19, required = false, value = "商品标签列表")
    private List<String> tagList;
    @ApiModelProperty(position = 20, required = true, value = "商品图片列表")
    private List<String> imageList;
    @ApiModelProperty(position = 21, required = false, value = "商品图片封面")
    @Size(max = 256, message = "商品图片封面URL过长")
    private String coverPic;
    @ApiModelProperty(position = 22, required = false, value = "商品视频地址")
    @Size(max = 256, message = "商品视频地址URL过长")
    private String video;

    /**
     * ---------------------------- 价格库存 ----------------------------
     **/

    @ApiModelProperty(position = 23, required = true, value = "规格展现方式[1-常规|2-组合]", allowableValues = "1,2", example = "1")
    @NotBlank(message = "规格展现方式不能为空")
    @Pattern(regexp = "\\b(1|2)\\b", message = "规格展现方式参数无效")
    private String specMode;
    @ApiModelProperty(position = 24, required = false, value = "SKU规格信息[初次添加商品必填]")
//    @NotNull(message = "SKU规格信息不能为空")
    @Valid
    private List<GoblinStoreMgtGoodsAddSkuParam> skuParamList;
    @ApiModelProperty(position = 25, required = true, value = "物流模版", example = "松鼠德邦")
    @Size(max = 50, message = "物流模版ID过长")
    private String logisticsTemplate;
    @ApiModelProperty(position = 26, required = false, value = "商品编码[默认为系统编码，也可手动输入商家自己的编码]")
    @Pattern(regexp = LnsRegex.Valid.ALPHABET_NUMBER_UNDER_50, message = "商品编码格式或长度有误")
    private String spuNo;
    @ApiModelProperty(position = 26, required = true, value = "ERP类型[WANGDIAN-旺店通]")
    @Pattern(regexp = "\\b(WANGDIAN)\\b", message = "ERP类型无效")
    private String erpType;
    @ApiModelProperty(position = 26, required = false, value = "ERP货品编号[商品对应在ERP的商品编码，默认为空]")
    @Size(max = 40, message = "ERP货品编号长度限制40")
    private String spuErpCode;

    /**
     * ---------------------------- 商品介绍 ----------------------------
     **/

    @ApiModelProperty(position = 27, required = true, value = "商品详情", example = "商品详情...")
    @Size(max = 10000, message = "商品详情内容过长")
    private String details;

    /**
     * ---------------------------- 销售属性 ----------------------------
     **/

    @ApiModelProperty(position = 28, required = true, value = "上架处理方式[1-等待手动上架|2-直接上架售卖|3-预约定时上架]", example = "1")
    @NotNull(message = "上架处理方式不能为空")
    @Pattern(regexp = "\\b(1|2|3)\\b", message = "规格展现方式参数无效")
    private String shelvesHandle;
    @ApiModelProperty(position = 29, required = false, value = "预约上架时间[yyyy-MM-dd HH:mm:ss][上架处理方式为3-预约定时上架时需要指定]")
    @Pattern(regexp = LnsRegex.Valid.DATETIME_FULL, message = "预约上架时间格式有误")
    private String shelvesTime;
    @ApiModelProperty(position = 30, required = false, value = "商品有效期[yyyy-MM-dd]")
    @Pattern(regexp = LnsRegex.Valid.DATETIME_YMD, message = "商品有效期格式有误")
    private String spuValidity;
    @ApiModelProperty(position = 31, required = true, value = "是否虚拟商品[0-否|1-是]", allowableValues = "0,1", example = "0")
    @Pattern(regexp = "\\b(0|1)\\b", message = "是否虚拟商品参数无效")
    private String virtualFlg;
    @ApiModelProperty(position = 31, required = false, value = "是否展示到商城[0-否|1-是]", allowableValues = "0,1", example = "1")
    @Min(value = 0, message = "是否展示到商城参数无效")
    @Max(value = 1, message = "是否展示到商城参数无效")
    private Integer showInMall;

    /**
     * ---------------------------- 服务保障 ----------------------------
     **/

    @ApiModelProperty(position = 32, required = false, value = "商品服务支持ID列表")
    private List<String> ssidList;

    /**
     * ---------------------------- 专属标签 ----------------------------
     **/

    @ApiModelProperty(position = 33, required = false, value = "商品关联音乐人、艺术家、品牌方、厂牌列表")
    private List<String> extagList;

    /**
     * ---------------------------- AR标签 ----------------------------
     **/

    @ApiModelProperty(position = 33, required = false, value = "商品关联音乐人、艺术家、品牌方、厂牌、AR列表")
    private List<String> artagList;


    /**
     * 生成SPU
     *
     * @return GoblinGoodsInfoVo
     */
    public GoblinGoodsInfoVo initGoodsInfoVo() {
        GoblinGoodsInfoVo vo = GoblinGoodsInfoVo.getNew();
        vo.setStoreId(this.getStoreId());
        if (StringUtils.isBlank(this.getSpuId())) {
            vo.setSpuId(IDGenerator.nextMilliId2());
        } else {
            vo.setSpuId(this.getSpuId());
        }
        if (StringUtils.isBlank(this.getSpuNo())) {
            vo.setSpuNo(vo.getSpuId());
        } else {
            vo.setSpuNo(this.getSpuNo());
        }
        vo.setSpuType(0);
        vo.setName(this.getName());
        vo.setSubtitle(this.getSubtitle());
        vo.setSellPrice(this.getSellPrice());
//        vo.setPriceGe(BigDecimal.ZERO);
//        vo.setPriceLe(BigDecimal.ZERO);
        vo.setIntro(this.getIntro());
        vo.setDetails(this.getDetails());
        vo.setCoverPic(StringUtils.isBlank(this.getCoverPic()) ? this.getImageList().get(0) : this.getCoverPic());
        vo.setVideo(this.getVideo());
        vo.setSpecMode(this.getSpecMode());
        vo.setCateFid(this.getCateFid());
        vo.setCateSid(this.getCateSid());
        vo.setCateTid(this.getCateTid());
//        vo.setStoreCateFid(null);
//        vo.setStoreCateSid(null);
//        vo.setStoreCateTid(null);
//        vo.setBrandId(null);
        vo.setShelvesHandle(this.getShelvesHandle());
        vo.setShelvesTime(this.getShelvesTime());
        vo.setSpuValidity(this.getSpuValidity());
        vo.setVirtualFlg(this.getVirtualFlg());
        vo.setShowInMall(GoblinGoodsShowInMallHelper.defaultFromRequest(this.getShowInMall()));
        vo.setStatus("3");
//        vo.setReason(null);
//        vo.setShelvesStatus("0");
        if (vo.getShelvesHandle().equals("2")) {
            vo.setShelvesStatus("3");// `上架处理方式`:2-直接上架售卖，直接上架
            vo.setShelvesAt(LocalDateTime.now());
        } else {
            vo.setShelvesStatus("0");
        }
        vo.setSpuAppear("0");
        vo.setDelFlg("0");
//        vo.setShelvesAt(null);
        vo.setImageList(this.getImageList());
        vo.setLogisticsTemplate(this.getLogisticsTemplate());
//        vo.setCreatedBy();
//        vo.setCreatedAt();
//        vo.setUpdatedBy();
//        vo.setUpdatedAt();
//        vo.setSpecVoList();
//        vo.setTagVoList();
//        vo.setServiceSupportVoList();
//        vo.setExtagVoList();
        vo.setErpType(StringUtils.isBlank(this.getErpType()) ? "WANGDIAN" : this.getErpType());
        vo.setSpuErpCode(StringUtils.trim(this.getSpuErpCode()));
        return vo;
    }

    /**
     * 编辑SPU参数整理
     *
     * @return GoblinGoodsInfoVo
     */
    public GoblinGoodsInfoVo initEditGoodsInfoVo() {
        GoblinGoodsInfoVo vo = GoblinGoodsInfoVo.getNew();
        vo.setStoreId(this.getStoreId());
        vo.setSpuId(this.getSpuId());
        vo.setSpuNo(this.getSpuNo());
        vo.setSpuType(0);
        vo.setName(this.getName());
        vo.setSubtitle(this.getSubtitle());
        vo.setSellPrice(this.getSellPrice());
        vo.setIntro(this.getIntro());
        vo.setDetails(this.getDetails());
        vo.setCoverPic(StringUtils.isBlank(this.getCoverPic()) ? this.getImageList().get(0) : this.getCoverPic());
        vo.setVideo(this.getVideo());
        vo.setSpecMode(this.getSpecMode());
        vo.setCateFid(this.getCateFid());
        vo.setCateSid(this.getCateSid());
        vo.setCateTid(this.getCateTid());
        vo.setShelvesHandle(this.getShelvesHandle());
        vo.setShelvesTime(this.getShelvesTime());
        vo.setSpuValidity(this.getSpuValidity());
        vo.setVirtualFlg(this.getVirtualFlg());
        vo.setShowInMall(GoblinGoodsShowInMallHelper.defaultFromRequest(this.getShowInMall()));
        vo.setImageList(this.getImageList());
        vo.setLogisticsTemplate(this.getLogisticsTemplate());
//        vo.setErpType();// 暂不考虑更改ERP类型
        vo.setSpuErpCode(StringUtils.trim(this.getSpuErpCode()));
        return vo;
    }

    /**
     * 生成SKU列表以及SPU规格等信息
     *
     * @param goodsInfoVo  GoblinGoodsInfoVo
     * @param vos          List<GoblinGoodsSkuInfoVo>
     * @param goodsSpecVos List<GoblinGoodsSpecVo>
     */
    public void initGoodsSkuInfoVo(GoblinGoodsInfoVo goodsInfoVo, List<GoblinGoodsSkuInfoVo> vos,
                                   List<GoblinGoodsSpecVo> goodsSpecVos) {
        List<GoblinStoreMgtGoodsAddSkuParam> mgtGoodsAddSkuParamList = this.getSkuParamList();
        List<String> skuIdList = CollectionUtil.arrayListString();
        BigDecimal priceGe = BigDecimal.ZERO, priceLe = BigDecimal.ZERO;
        int size = mgtGoodsAddSkuParamList.size(), skuSpecSize = 0;
        for (int i = 0; i < size; i++) {
            GoblinStoreMgtGoodsAddSkuParam addSkuParam = mgtGoodsAddSkuParamList.get(i);
            String skuId = addSkuParam.getSkuId();

            GoblinGoodsSkuInfoVo skuInfoVo = GoblinGoodsSkuInfoVo.getNew();
            if (StringUtils.isBlank(skuId)) {
                skuInfoVo.setSkuId(goodsInfoVo.getSpuId().concat(StringUtils.right(String.valueOf(System.nanoTime()), 5)));
            } else {
                skuInfoVo.setSkuId(skuId);
            }
            skuInfoVo.setSpuId(goodsInfoVo.getSpuId());
            if (StringUtils.isNotBlank(addSkuParam.getSkuNo())) {
                skuInfoVo.setSkuNo(addSkuParam.getSkuNo());
            } else {
                skuInfoVo.setSkuNo(goodsInfoVo.getSpuNo());
            }
            if (StringUtils.isNotBlank(addSkuParam.getSkuBarCode())) {
                skuInfoVo.setSkuBarCode(addSkuParam.getSkuBarCode());
            } else {
                skuInfoVo.setSkuBarCode(goodsInfoVo.getSpuNo());
            }
//            skuInfoVo.setName(goodsInfoVo.getName());
            skuInfoVo.setSubtitle(goodsInfoVo.getSubtitle());
            skuInfoVo.setSkuPic(addSkuParam.getSkuPic());
            skuInfoVo.setSkuIsbn(addSkuParam.getSkuIsbn());
            skuInfoVo.setStock(addSkuParam.getStock());
            skuInfoVo.setSkuStock(skuInfoVo.getStock());
            skuInfoVo.setWarningStock(addSkuParam.getWarningStock());
            skuInfoVo.setSellPrice(addSkuParam.getSellPrice());
            skuInfoVo.setPrice(addSkuParam.getPrice());
            skuInfoVo.setPriceMember(null == addSkuParam.getPriceMember() ? addSkuParam.getPrice() : addSkuParam.getPriceMember());
            skuInfoVo.setWeight(addSkuParam.getWeight());
            skuInfoVo.setBuyFactor(addSkuParam.getBuyFactor());
            skuInfoVo.setBuyRoster(addSkuParam.getBuyRoster());
            skuInfoVo.setBuyLimit(addSkuParam.getBuyLimit());
            skuInfoVo.setStoreId(goodsInfoVo.getStoreId());
            skuInfoVo.setSkuValidity(DateUtil.Formatter.yyyyMMddHHmmss.parse(addSkuParam.getSkuValidity()));
            skuInfoVo.setVirtualFlg(goodsInfoVo.getVirtualFlg());
            skuInfoVo.setStatus("3");// 没有审核流程，默认通过
//            skuInfoVo.setReason();
            skuInfoVo.setShelvesStatus(goodsInfoVo.getShelvesStatus());
            skuInfoVo.setSkuAppear(StringUtils.isBlank(addSkuParam.getSkuAppear()) ? "0" : addSkuParam.getSkuAppear());
            skuInfoVo.setDelFlg("0");
//            skuInfoVo.setShelvesAt();
            skuInfoVo.setCreatedBy(goodsInfoVo.getCreatedBy());
            skuInfoVo.setCreatedAt(goodsInfoVo.getCreatedAt());
//            skuInfoVo.setUpdatedBy();
//            skuInfoVo.setUpdatedAt();
            skuInfoVo.setLogisticsTemplate(goodsInfoVo.getLogisticsTemplate());
            skuInfoVo.setSkuErpCode(StringUtils.trim(addSkuParam.getSkuErpCode()));
            skuInfoVo.setErpType(goodsInfoVo.getErpType());
            skuInfoVo.setErpWarehouseNo(StringUtils.trim(addSkuParam.getErpWarehouseNo()));
            if (StringUtils.equals(addSkuParam.getErpHosting(), "1")) {
                skuInfoVo.setErpHosting(1);
                if (StringUtils.isBlank(goodsInfoVo.getSpuErpCode())) {
                    ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("149022");
                    throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
                }
                if (StringUtils.isBlank(skuInfoVo.getSkuErpCode())) {
                    ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("149023");
                    throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
                }
                if (StringUtils.isBlank(skuInfoVo.getErpWarehouseNo())) {
                    ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("149024");
                    throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
                }
            } else {
                skuInfoVo.setErpHosting(0);
            }

            List<GoblinGoodsSpecDto> skuSpecList = addSkuParam.getSkuSpecList();
            skuInfoVo.setSkuSpecList(skuSpecList);

            for (GoblinGoodsSkuInfoVo goodsSkuInfoVo : vos) {// 规格比对
                Map<String, String> skuSpecMap = goodsSkuInfoVo.getSkuSpecList().stream()
                        .collect(Collectors.toMap(GoblinGoodsSpecDto::getSpecName, GoblinGoodsSpecDto::getSpecVname, (k1, k2) -> k2));
                boolean diffSpecFlg = false;
                for (GoblinGoodsSpecDto goodsSpecDto : skuSpecList) {
                    String specName = goodsSpecDto.getSpecName();
                    if (!skuSpecMap.get(specName).equals(goodsSpecDto.getSpecVname())) {
                        diffSpecFlg = true;// 多个规格中只要存在一个不一致，即可跳过，标记为允许添加
                        break;
                    }
                }
                if (!diffSpecFlg) {// 重复的规格信息
                    ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("149006");
                    throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
                }
            }
            vos.add(skuInfoVo);

            skuIdList.add(skuInfoVo.getSkuId());
            priceGe = priceGe.compareTo(BigDecimal.ZERO) == 0 ? skuInfoVo.getPrice() : (priceGe.compareTo(skuInfoVo.getPrice()) > 0 ? skuInfoVo.getPrice() : priceGe);
            priceLe = priceLe.compareTo(skuInfoVo.getPrice()) < 0 ? skuInfoVo.getPrice() : priceLe;

            if (CollectionUtils.isEmpty(skuSpecList) || (skuSpecSize > 0 && skuSpecSize != skuSpecList.size())) {
                ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("149006");
                throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
            }

            String skuname = "";
            int specSize = skuSpecList.size();// SKU包含的规格数量
            skuSpecSize = i == 0 ? specSize : skuSpecSize;// 标记第一个SKU的规格数量，用于校验
            List<String> skuSpecNListTmp = CollectionUtil.arrayListString();// 标记单个SKU的规格名称，用于校验
            for (int j = 0; j < specSize; j++) {
                GoblinGoodsSpecDto specDto = skuSpecList.get(j);
                String specName = specDto.getSpecName().trim();
                String specVname = specDto.getSpecVname().trim();
                skuname = skuname.concat(specVname);

                GoblinGoodsSpecValueVo specValueVo = GoblinGoodsSpecValueVo.getNew().setSpecVname(specVname).setSpecVsort(i);
                if (i == 0) {
                    if (goodsSpecVos.stream().anyMatch(r -> r.getSpecName().equals(specName))) {// 单SKU重复的规格
                        ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("149006");
                        throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
                    }
                    ArrayList<GoblinGoodsSpecValueVo> specValueVos = new ArrayList<>();
                    specValueVos.add(specValueVo);
                    goodsSpecVos.add(GoblinGoodsSpecVo.getNew().setSpecName(specName).setSpecSort(j + 1).setSpecValues(specValueVos));
                } else {
                    Optional<GoblinGoodsSpecVo> filterGoodsSpecOptional = goodsSpecVos.stream().filter(r -> r.getSpecName().equals(specName)).findAny();
                    if (filterGoodsSpecOptional.isPresent()) {// 存在该规格
                        if (filterGoodsSpecOptional.get().getSpecValues().stream().noneMatch(r -> r.getSpecVname().equals(specVname))) {
                            // 且不包含该规格值，则补充规格对应的值
                            filterGoodsSpecOptional.get().getSpecValues().add(specValueVo);
                        }
                    } else {// 不存在该规格，则不同SKU规格不一致
                        ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("149006");
                        throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
                    }
                }
                if (!skuSpecNListTmp.isEmpty() && skuSpecNListTmp.contains(specName)) {// 单SKU重复的规格
                    ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("149006");
                    throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
                }
                skuSpecNListTmp.add(specName);
            }
            skuInfoVo.setName(skuname);
        }
        goodsInfoVo.setPriceGe(priceGe);
        goodsInfoVo.setPriceLe(priceLe);
        goodsInfoVo.setSpecVoList(goodsSpecVos);
        goodsInfoVo.setSkuIdList(skuIdList);
    }
}
