
package com.tmerclub.cloud.product.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.tmerclub.cloud.api.auth.bo.UidInfoBO;
import com.tmerclub.cloud.api.auth.constant.SysTypeEnum;
import com.tmerclub.cloud.api.delivery.feign.DeliveryFeignClient;
import com.tmerclub.cloud.api.product.feign.WarehouseFeignClient;
import com.tmerclub.cloud.api.delivery.vo.ShopTransportVO;
import com.tmerclub.cloud.api.feign.SearchSpuFeignClient;
import com.tmerclub.cloud.api.platform.config.FeignShopConfig;
import com.tmerclub.cloud.api.product.constant.CategoryLevel;
import com.tmerclub.cloud.api.product.util.ProductLangUtil;
import com.tmerclub.cloud.api.supplier.feign.SupplierDetailFeignClient;
import com.tmerclub.cloud.api.supplier.vo.SupplierApiDetailVO;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.constant.ExcelConstant;
import com.tmerclub.cloud.common.constant.StatusEnum;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.i18n.I18nMessage;
import com.tmerclub.cloud.common.i18n.LanguageEnum;
import com.tmerclub.cloud.common.order.constant.DeliveryType;
import com.tmerclub.cloud.common.product.constant.SpuType;
import com.tmerclub.cloud.common.product.constant.StockPointType;
import com.tmerclub.cloud.common.product.constant.SupplierSpuType;
import com.tmerclub.cloud.common.product.dto.*;
import com.tmerclub.cloud.common.product.vo.*;
import com.tmerclub.cloud.common.product.vo.search.SpuSearchVO;
import com.tmerclub.cloud.common.response.ResponseEnum;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.common.util.*;
import com.tmerclub.cloud.product.constant.SpuExportError;
import com.tmerclub.cloud.product.constant.WriteOfNumEnum;
import com.tmerclub.cloud.product.dto.SpuPageSearchDTO;
import com.tmerclub.cloud.product.handler.ProductCommentWriteHandler;
import com.tmerclub.cloud.product.mapper.SpuMapper;
import com.tmerclub.cloud.product.model.BrandLang;
import com.tmerclub.cloud.product.service.*;
import com.tmerclub.cloud.product.vo.*;
import com.tmerclub.cloud.product.service.*;
import com.tmerclub.cloud.product.vo.*;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * spu信息
 *
 * @author tmerclub
 * @date 2020-10-28 15:27:24
 */
@Service
public class SpuExcelServiceImpl implements SpuExcelService {

    @Autowired
    private SpuMapper spuMapper;
    @Autowired
    private SpuService spuService;
    @Autowired
    private SkuService skuService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private CategoryShopService categoryShopService;
    @Autowired
    private BrandService brandService;
    @Autowired
    private BrandShopService brandShopService;
    @DubboReference
    private DeliveryFeignClient deliveryFeignClient;
    @DubboReference
    private SupplierDetailFeignClient supplierDetailFeignClient;
    @DubboReference
    private SearchSpuFeignClient searchSpuFeignClient;
    @Autowired
    private FeignShopConfig feignShopConfig;
    @Autowired
    private WarehouseFeignClient warehouseFeignClient;

    /**
     * 商品显示信息
     */
    public static final String ENABLE = "上架";
    public static final String DISABLE = "下架";
    public static final String OFFLINE = "违规下架";
    public static final String WAIT_AUDIT = "等待审核";
    public static final String PORTION_ENABLE = "部分上架";
    public static final String PORTION_DISABLE = "部分下架";
    public static final String[] DELIVERY_MODE = {
            DeliveryType.STATION.description(),
            DeliveryType.SAME_CITY.description(),
            StrUtil.concat(Boolean.TRUE, DeliveryType.STATION.description(), "且", DeliveryType.SAME_CITY.description())
    };
    public static final String[] SUPPLIER_DELIVERY_MODE = {
            DeliveryType.DELIVERY.description()
    };
    public static final String[] STATUS_MODE = {ENABLE, DISABLE};

    /**
     * 运费模板
     */
    public static final String DELIVERY_FREE = "包邮";
    public static final Long DELIVERY_FREE_ID = 0L;
    public static final String DELIVERY_FIXED = "固定运费";
    public static final Long DELIVERY_FIXED_ID = -1L;
    /**
     * 发货方式
     */
    public static final String SUPPLIER_SHIPMENTS = "供应商发货";
    public static final String WAREHOUSE_SHIPMENTS = "仓库发货";
    /**
     * 商品类别 0.实物商品 1. 虚拟商品 2.组合商品
     */
    public static final String PHYSICAL_SPU = "实物商品";
    public static final String VIRTUAL_SPU = "虚拟商品";
    public static final String COMBO_SPU = "组合商品";
    public static final String YES = "是";
    public static final String NO = "否";
    public static final String REPEATEDLY = "多次核销";
    public static final String WITHOUT = "无需核销";
    public static final String SINGLE = "单次核销";
    public static final String UNLIMITED = "无限次";
    public static final String CUSTOMIZATION = "自定义";
    public static final String LONG_TERM = "长期有效";
    public static final String[] MULTISHOP_LMOLD_MODE = {PHYSICAL_SPU, VIRTUAL_SPU};
    public static final String[] MOLD_MODE = {PHYSICAL_SPU, VIRTUAL_SPU,COMBO_SPU};
    public static final String[] WRITE_MODE = {REPEATEDLY, WITHOUT, SINGLE};
    public static final String[] IS_REFUND_MODE = {NO, YES};
    private static final Pattern DAY = Pattern.compile("天", Pattern.LITERAL);
    private static final String DAY_STR = "天";
    private static final String WITHOUT_STR = "0";
    private static final String REPEATEDLY_STR = "1";
    private static final String SINGLE_STR = "1";
    private static final String UNLIMITED_STR = "-1";
    public static final int INT = 1024;
    /**
     * 品牌
     */
    public static final int BRAND_INDEX = 7;
    /**
     * 平台分类
     */
    public static final int CATEGORY_INDEX = 8;
    /**
     * 店铺分类
     */
    public static final int SHOP_CATEGORY_INDEX = 9;
    /**
     * 配送方式
     */
    public static final int DELIVERY_MODE_INDEX = 10;
    /**
     * 运费模板
     */
    public static final int DELIVERY_TEMPLATE_INDEX = 11;
    /**
     * 状态
     */
    public static final int STATUS_INDEX = 13;
    /**
     * 商品类别
     */
    public static final int MOLD_INDEX = 14;

    /**
     * 核销次数
     */
    public static final int WRITE_INDEX = 15;

    /**
     * 是否可以退款
     */
    public static final int IS_REFUND_INDEX = 20;

    private static final Logger log = LoggerFactory.getLogger(SpuExcelServiceImpl.class);

    private static final Pattern IMG_URL = Pattern
            .compile(".*?(image/gif|image/jpeg|image/png|image/jpg|image/bmp)");
    private static final Pattern IMG_URL_SUFFIX = Pattern
            .compile(".*?(gif|jpeg|png|jpg|bmp)");

    @Override
    public List<SpuExcelVO> excelSpuList(SpuPageSearchDTO spuDTO) {
        Integer sysType = AuthUserContext.get().getSysType();
        if (Objects.equals(sysType, SysTypeEnum.SUPPLIER.value())) {
            spuDTO.setSupplierId(AuthUserContext.get().getTenantId());
            spuDTO.setSupplierSpuType(SupplierSpuType.YES.value());
            spuDTO.setShopId(-1L);
        } else {
            spuDTO.setShopId(AuthUserContext.get().getTenantId());
        }
        List<SpuExcelVO> list = spuMapper.excelSpuList(spuDTO);
        if (CollUtil.isEmpty(list)) {
            return list;
        }
        Set<Long> categoryIds = new HashSet<>(Constant.INITIAL_CAPACITY);
        List<Long> spuIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (SpuExcelVO spuExcelVO : list) {
            spuIds.add(spuExcelVO.getSpuId());
            categoryIds.add(spuExcelVO.getCategoryId());
            categoryIds.add(spuExcelVO.getShopCategoryId());
        }
        // 获取分类列表
        List<CategoryVO> categoryList = categoryService.listByCategoryIds(categoryIds);
        ProductLangUtil.categoryList(categoryList);
        Map<Long, CategoryVO> categoryMap = categoryList.stream().collect(Collectors.toMap(CategoryVO::getCategoryId, c -> c));
        // 获取sku信息列表
        List<SpuExcelVO> skuList = skuService.excelSkuList(spuIds);
        Map<Long, List<SpuExcelVO>> skuMap = skuList.stream().collect(Collectors.groupingBy(SpuExcelVO::getSpuId));
        List<SpuExcelVO> spuExcelList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 店铺运费模板
        Map<Long, String> transportMap = new HashMap<>();
        transportMap.put(DELIVERY_FIXED_ID, DELIVERY_FIXED);
        transportMap.put(DELIVERY_FREE_ID, DELIVERY_FREE);
        ServerResponseEntity<List<ShopTransportVO>> response = deliveryFeignClient.listTransportByShopId(Objects.equals(sysType, SysTypeEnum.SUPPLIER.value()) ? spuDTO.getSupplierId() : spuDTO.getShopId());
        if (!Objects.equals(response.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(response.getMsg());
        }
        transportMap.putAll(response.getData().stream().collect(Collectors.toMap(ShopTransportVO::getTransportId, ShopTransportVO::getTransName)));
        int index = 1;
        for (SpuExcelVO spuExcelVO : list) {
            List<SpuExcelVO> skuData = skuMap.get(spuExcelVO.getSpuId());
            if (CollUtil.isEmpty(skuData)) {
                continue;
            }
            spuExcelVO.setSeq(String.valueOf(index));
            spuExcelVO.setDeliveryTemplate(transportMap.get(spuExcelVO.getDeliveryTemplateId()));
            spuExcelVO.setDeliveryAmount(spuExcelVO.getDeliveryAmount() != null && spuExcelVO.getDeliveryTemplate() != null ? AnalysisUtil.conversionPrices(spuExcelVO.getDeliveryAmount()) : "");
            // 状态
            spuExcelVO.setStatus(getStatus(spuExcelVO.getStatus()));
            setVirtualInfo(spuExcelVO);
            // 配送方式
            SpuVO.DeliveryModeVO deliveryModeVO = Json.parseObject(spuExcelVO.getDeliveryMode(), SpuVO.DeliveryModeVO.class);
            if (Objects.equals(spuExcelVO.getSpuMold(), VIRTUAL_SPU) || Objects.equals(spuExcelVO.getSpuType(), SpuType.ACTIVE.value())) {
                spuExcelVO.setDeliveryMode(DeliveryType.NOT_DELIVERY.description() + Constant.COMMA);
            } else {
                String delivery = getDelivery(deliveryModeVO);
                spuExcelVO.setDeliveryMode(delivery);
            }
            handleSpuExcelInfo(categoryMap, skuData, spuExcelList, spuExcelVO);
            index++;
        }
        return spuExcelList;
    }

    private static void setVirtualInfo(SpuExcelVO spuExcelVO) {
        // 虚拟商品信息
        spuExcelVO.setSpuMold(MOLD_MODE[Integer.valueOf(spuExcelVO.getSpuMold())]);
        String isRefundStr = spuExcelVO.getIsRefund() == null ? "" : (StrUtil.equals(spuExcelVO.getIsRefund(), SINGLE_STR) ? YES : NO);
        spuExcelVO.setIsRefund(isRefundStr);
        //虚拟商品的核销信息
        if (StrUtil.equals(spuExcelVO.getSpuMold(), VIRTUAL_SPU)) {
            spuExcelVO.setWriteOffNum(WriteOfNumEnum.getNameByNum(Integer.parseInt(spuExcelVO.getWriteOffNum())));
            spuExcelVO.setWriteOffMultipleCount(StrUtil.equals(spuExcelVO.getWriteOffMultipleCount(), UNLIMITED_STR) ? "" : spuExcelVO.getWriteOffMultipleCount());
            if (StrUtil.equals(spuExcelVO.getWriteOffTime(), UNLIMITED_STR)) {
                spuExcelVO.setWriteOffTime(LONG_TERM);
                spuExcelVO.setWriteOffStart(null);
                spuExcelVO.setWriteOffEnd(null);
            } else {
                spuExcelVO.setWriteOffTime(StrUtil.equals(spuExcelVO.getWriteOffTime(), null) ? "" : spuExcelVO.getWriteOffTime() + "天");
            }
        } else {
            spuExcelVO.setWriteOffNum("");
        }
    }

    private static String getStatus(String status) {
        if (Objects.equals(status, StatusEnum.ENABLE.value().toString())) {
            return ENABLE;
        } else if (Objects.equals(status, StatusEnum.DISABLE.value().toString())) {
            return DISABLE;
        } else if (Objects.equals(status, StatusEnum.OFFLINE.value().toString())) {
            return OFFLINE;
        } else if (Objects.equals(status, StatusEnum.WAIT_AUDIT.value().toString())) {
            return WAIT_AUDIT;
        }
        return "";
    }

    private void handleSpuExcelInfo(Map<Long, CategoryVO> categoryMap, List<SpuExcelVO> skuData, List<SpuExcelVO> spuExcelList, SpuExcelVO spuExcelVO) {

        // 名称、卖点
        for (SpuLangVO spuLangVO : spuExcelVO.getSpuLangList()) {
            if (Objects.equals(spuLangVO.getLang(), LanguageEnum.LANGUAGE_ZH_CN.getLang())) {
                spuExcelVO.setNameZh(spuLangVO.getSpuName());
                spuExcelVO.setSellingPointZh(spuLangVO.getSellingPoint());
            }
        }
        // 商品详情
        for (SpuDetailVO spuDetailVO : spuExcelVO.getSpuDetailList()) {
            if (Objects.equals(spuDetailVO.getLang(), LanguageEnum.LANGUAGE_ZH_CN.getLang())) {
                spuExcelVO.setDetailZh(spuDetailVO.getDetail());
            }
        }
        String brandName = null;
        if (CollUtil.isNotEmpty(spuExcelVO.getBrandLangList())) {
            BrandLangVO brandLang = ProductLangUtil.handelBrandLang(spuExcelVO.getBrandLangList());
            brandName = brandLang.getName();
        }
        String shopCategoryName = null;
        // 店铺分类
        CategoryVO shopCategoryVO = categoryMap.get(spuExcelVO.getShopCategoryId());
        if (Objects.nonNull(shopCategoryVO)) {
            shopCategoryName = shopCategoryVO.getName();
        }
        String categoryName = null;
        // 平台分类
        CategoryVO categoryVO = categoryMap.get(spuExcelVO.getCategoryId());
        if (Objects.nonNull(categoryVO)) {
            categoryName = categoryVO.getName();
        }
        String delivery = spuExcelVO.getDeliveryMode();
        delivery = delivery.substring(0, delivery.length() - 1);
        String resourceUrl = feignShopConfig.getUploadFile().getResourceUrl();
        for (SpuExcelVO spuExcel : skuData) {
            spuExcel.setPriceFee(AnalysisUtil.conversionPrices(spuExcel.getPriceFee()));
            spuExcel.setMarketPriceFee(AnalysisUtil.conversionPrices(spuExcel.getMarketPriceFee()));
            spuExcel.setSeq(spuExcelVO.getSeq());
            spuExcel.setDeliveryTemplate(spuExcelVO.getDeliveryTemplate());
            spuExcel.setDeliveryAmount(spuExcelVO.getDeliveryAmount());
            spuExcel.setBrandName(brandName);
            spuExcel.setStatus(spuExcelVO.getStatus());
            spuExcel.setNameZh(spuExcelVO.getNameZh());
            spuExcel.setSellingPointZh(spuExcelVO.getSellingPointZh());
            spuExcel.setDetailZh(spuExcelVO.getDetailZh());
            spuExcel.setCategoryName(categoryName);
            spuExcel.setShopCategoryName(shopCategoryName);
            spuExcel.setDeliveryMode(delivery);
            spuExcel.setSpuMold(spuExcelVO.getSpuMold());
            spuExcel.setWriteOffTime(spuExcelVO.getWriteOffTime());
            spuExcel.setWriteOffNum(spuExcelVO.getWriteOffNum());
            spuExcel.setWriteOffMultipleCount(spuExcelVO.getWriteOffMultipleCount());
            spuExcel.setWriteOffEnd(spuExcelVO.getWriteOffEnd());
            spuExcel.setWriteOffStart(spuExcelVO.getWriteOffStart());
            spuExcel.setIsRefund(spuExcelVO.getIsRefund());
            spuExcel.setVirtualRemark(spuExcelVO.getVirtualRemark());
            spuExcel.setImgs(spuExcelVO.getImgs());
            spuExcel.setVideo(spuExcelVO.getVideo());
            // 补充图片，视频资源域名地址
            if (!ObjectUtils.isEmpty(spuExcel.getImgs())) {
                String[] imgArr = spuExcel.getImgs().split(ExcelConstant.COMMA_SPLIT);
                StringBuilder sb = new StringBuilder(Constant.INITIAL_CAPACITY);
                for (int i = 0; i < imgArr.length; i++) {
                    if (!imgArr[i].startsWith(ExcelConstant.URL_PREFIX)) {
                        imgArr[i] = resourceUrl + imgArr[i];
                    }
                    sb.append(imgArr[i]).append(ExcelConstant.COMMA_SPLIT);
                }
                spuExcel.setImgs(sb.substring(0, sb.toString().length() - 1));
            }
            if (!ObjectUtils.isEmpty(spuExcel.getVideo())
                    && !spuExcel.getVideo().startsWith(ExcelConstant.URL_PREFIX)) {
                spuExcel.setVideo(resourceUrl + spuExcelVO.getVideo());
            }
            spuExcelList.add(spuExcel);
        }
    }

    @Override
    public void exportExcel(List<SpuExcelVO> spuList, Map<Integer, List<String>> errorMap) {
        if (CollUtil.isEmpty(spuList)) {
            addSpuExcelError(errorMap, SpuExportError.OTHER, "导入文件为空");
            return;
        }
        for (SpuExcelVO spuExcelVO : spuList) {
            if (Objects.isNull(spuExcelVO.getSeq())) {
                addSpuExcelError(errorMap, SpuExportError.OTHER, "编号不能为空");
                return;
            }
            if (StrUtil.isNotBlank(spuExcelVO.getImgs())) {
                String[] split = spuExcelVO.getImgs().split(",");
                if (!checkPic(split, errorMap)) {
                    return;
                }
            }
            if (StrUtil.isNotBlank(spuExcelVO.getVideo())) {
                if (!checkVideo(spuExcelVO.getVideo(), errorMap)) {
                    return;
                }
            }
        }

        Integer sysType = AuthUserContext.get().getSysType();
        Long shopId = AuthUserContext.get().getTenantId();
        Set<Long> brandIds = new HashSet<>(Constant.INITIAL_CAPACITY);
        // 平台分类
        Map<String, Long> categoryMap = getCategoryList(Constant.PLATFORM_SHOP_ID);
        // 店铺分类
        Map<String, Long> shopCategoryMap = getCategoryList(shopId);
        //供应商没有店铺分类
        if (!Objects.equals(sysType, SysTypeEnum.SUPPLIER.value()) && MapUtil.isEmpty(shopCategoryMap)) {
            addSpuExcelError(errorMap, SpuExportError.OTHER, "请先创建店铺分类");
            return;
        }
        // 运费模板
        Map<String, Long> transportMap = new HashMap<>();
        transportMap.put(DELIVERY_FIXED, DELIVERY_FIXED_ID);
        transportMap.put(DELIVERY_FREE, DELIVERY_FREE_ID);
        ServerResponseEntity<List<ShopTransportVO>> response = deliveryFeignClient.listTransportByShopId(shopId);
        transportMap.putAll(response.getData().stream().collect(Collectors.toMap(ShopTransportVO::getTransName, ShopTransportVO::getTransportId)));
        if (MapUtil.isEmpty(transportMap)) {
            addSpuExcelError(errorMap, SpuExportError.OTHER, "请先创建运费模板");
            return;
        }
        // 品牌
        Set<String> brandNames = new HashSet<>(Constant.INITIAL_CAPACITY);
        for (SpuExcelVO spuExcel : spuList) {
            brandNames.add(spuExcel.getBrandName());
        }
        List<BrandLang> brandList = brandService.listBrandLangByBrandNames(brandNames, shopId);
        Map<String, List<BrandLang>> brandMap = brandList.stream().collect(Collectors.groupingBy(BrandLang::getName));
        Map<String, List<SpuExcelVO>> spuMap = spuList.stream().collect(Collectors.groupingBy(SpuExcelVO::getSeq));
        for (String seq : spuMap.keySet()) {
            List<SpuExcelVO> spuExcelList = spuMap.get(seq);
            SpuDTO spu = new SpuDTO();
            spu.setShopId(shopId);
            try {
                loadSpuData(spuExcelList, spu, categoryMap, shopCategoryMap, transportMap, brandMap, errorMap);
            } catch (Exception e) {
                addSpuExcelError(errorMap, SpuExportError.PRODUCT_DATA, e.getMessage());
                continue;
            }
            if (Objects.nonNull(spu.getBrandId())) {
                brandIds.add(spu.getBrandId());
            }
        }
        brandService.updateSpuCountByBrandIds(brandIds);
    }

    private boolean checkVideo(String video, Map<Integer, List<String>> errorMap) {
        try {
            URL url = new URL(video);
            String videoName = "video/mp4";
            String map4 = ".map4";
            String contentType = MediaTypeFactory.getMediaType(video).orElse(MediaType.APPLICATION_OCTET_STREAM).toString();
            if (Objects.equals(contentType, MediaType.APPLICATION_OCTET_STREAM.toString())) {
                contentType = url.openConnection().getHeaderField(Constant.CONTENT_TYPE);
            }
            if (!Objects.equals(contentType, videoName) || video.endsWith(map4)) {
                addSpuExcelError(errorMap, SpuExportError.OTHER, "上传视频格式错误");
                return false;
            }
        } catch (IOException e) {
            log.error("视频格式判断出错：{}", e.getMessage());
        }
        int length = getFileLength(video);
        //定义MB的计算常量
        int mb = 1024 << 10;
        DecimalFormat df = new DecimalFormat("0.00");
        float lengthByMb = Float.parseFloat(df.format(length / (float) mb));
        if (lengthByMb > Constant.FIFTY) {
            addSpuExcelError(errorMap, SpuExportError.OTHER, "上传视频大小超出限制");
            return false;
        }
        return true;
    }

    private int getFileLength(String url1) {
        int length = 0;
        URL url;
        try {
            url = new URL(url1);
            HttpURLConnection urlcon = (HttpURLConnection) url.openConnection();
            //根据响应获取文件大小
            length = urlcon.getContentLength();
            urlcon.disconnect();
        } catch (MalformedURLException e) {
            log.error("视频格式判断出错：{}", e.getMessage());
        } catch (IOException e) {
            log.error("IO异常：{}", e.getMessage());
        }
        return length;
    }

    private boolean checkPic(String[] split, Map<Integer, List<String>> errorMap) {
        if (split.length > Constant.NINE) {
            addSpuExcelError(errorMap, SpuExportError.OTHER, "最多上传9张图片");
            return false;
        }
        for (String s : split) {
            if (!isImgUrl(s)) {
                addSpuExcelError(errorMap, SpuExportError.OTHER, "上传图片格式错误");
                return false;
            }
        }
        return true;
    }

    private boolean isImgUrl(String url) {
        if (url == null || url.trim().length() == 0 || !url.contains(".")) {
            return false;
        }
        String suffix = url.substring(url.lastIndexOf('.'));
        try {
            return IMG_URL_SUFFIX.matcher(suffix).matches() || IMG_URL.matcher(new URL(url).openConnection().getHeaderField("content-type")).matches();
        } catch (IOException e) {
            log.error("图片格式判断出错:{}", e.getMessage());
        }
        return false;
    }

    private void addSpuExcelError(Map<Integer, List<String>> errorMap, SpuExportError spuExportError, String error) {
        List<String> list = errorMap.get(spuExportError.value());
        if (CollUtil.isEmpty(list)) {
            list = new ArrayList<>(0);
            errorMap.put(spuExportError.value(), list);
        }
        list.add(error);
    }

    private Map<String, Long> getCategoryList(Long shopId) {
        List<CategoryVO> categoryList;
        if (Objects.equals(shopId, Constant.PLATFORM_SHOP_ID)) {
            categoryList = categoryService.getShopSigningCategoryAndLangInfo(AuthUserContext.get().getTenantId());
        } else {
            categoryList = categoryService.listAndLangInfoByShopId(shopId);
        }
        categoryList.sort(Comparator.comparing(CategoryVO::getSeq).reversed().thenComparing(CategoryVO::getCategoryId));
        Map<String, Long> categoryNameMap = new HashMap<>(categoryList.size());
        Map<String, Long> categoryNameEnMap = new HashMap<>(categoryList.size());
        for (CategoryVO categoryVO : categoryList) {
            boolean isParentCategory = Objects.equals(categoryVO.getLevel(), CategoryLevel.First.value()) ||
                    (Objects.equals(shopId, Constant.PLATFORM_SHOP_ID) && Objects.equals(categoryVO.getLevel(), CategoryLevel.SECOND.value()));
            if (isParentCategory) {
                continue;
            }
            for (CategoryLangVO categoryLangVO : categoryVO.getCategoryLangList()) {
                String name = categoryLangVO.getName();
                if (Objects.equals(categoryLangVO.getLang(), LanguageEnum.LANGUAGE_ZH_CN.getLang()) && !categoryNameMap.containsKey(name)) {
                    categoryNameMap.put(name, categoryVO.getCategoryId());
                } else if (Objects.equals(categoryLangVO.getLang(), LanguageEnum.LANGUAGE_EN.getLang()) && !categoryNameMap.containsKey(name)) {
                    categoryNameEnMap.put(name, categoryVO.getCategoryId());
                }
            }
        }
        for (String key : categoryNameEnMap.keySet()) {
            if (!categoryNameMap.containsKey(key)) {
                categoryNameMap.put(key, categoryNameEnMap.get(key));
            }
        }
        return categoryNameMap;
    }

    @Override
    public String spuExportError(Map<Integer, List<String>> errorMap) {
        StringBuilder info = new StringBuilder(Constant.INITIAL_CAPACITY);
        for (Integer key : errorMap.keySet()) {
            List<String> list = errorMap.get(key);
            SpuExportError spuExportError = SpuExportError.instance(key);
            if (Objects.equals(spuExportError, SpuExportError.OTHER)) {
                info.append(list.toString()).append("\n");
                continue;
            }
            info.append(Objects.requireNonNull(spuExportError).errorInfo()).append(list.toString()).append("\n");
        }
        return info.toString();
    }

    @Override
    public void downloadModel(HttpServletResponse response) {
        UidInfoBO uidInfoBO = AuthUserContext.get();
        Long shopId = uidInfoBO.getTenantId();
        Integer sysType = uidInfoBO.getSysType();
        List<SpuExcelVO> list = new ArrayList<>(Constant.INITIAL_CAPACITY);
        list.add(new SpuExcelVO());
        Map<Integer, String[]> map = new HashMap<>(8);
        if (Objects.equals(sysType, SysTypeEnum.SUPPLIER.value())) {
            map.put(DELIVERY_MODE_INDEX - 1, SUPPLIER_DELIVERY_MODE);
            map.put(STATUS_INDEX - 1, STATUS_MODE);
        } else {
            map.put(DELIVERY_MODE_INDEX, DELIVERY_MODE);
            map.put(STATUS_INDEX, STATUS_MODE);
            map.put(MOLD_INDEX, MULTISHOP_LMOLD_MODE);
            map.put(WRITE_INDEX, WRITE_MODE);
            map.put(IS_REFUND_INDEX, IS_REFUND_MODE);
        }

        ServerResponseEntity<List<ShopTransportVO>> responseEntity = deliveryFeignClient.listTransportByShopId(shopId);
        List<ShopTransportVO> data = responseEntity.getData();
        String[] transNames = new String[data.size() + 2];
        for (int i = 0; i < data.size(); i++) {
            ShopTransportVO transport = data.get(i);
            transNames[i] = transport.getTransName();
        }
        transNames[transNames.length - 2] = DELIVERY_FREE;
        transNames[transNames.length - 1] = DELIVERY_FIXED;
        if (Objects.equals(sysType, SysTypeEnum.SUPPLIER.value())) {
            map.put(DELIVERY_TEMPLATE_INDEX - 1, transNames);
        } else {
            map.put(DELIVERY_TEMPLATE_INDEX, transNames);
        }

        // 平台分类
        List<CategoryShopVO> categoryShopList = categoryShopService.listByShopId(shopId, AuthUserContext.get().getSysType(), I18nMessage.getLang());
        map.put(CATEGORY_INDEX, categoryShopList.stream().filter(category -> Objects.equals(category.getCategoryStatus(), StatusEnum.ENABLE.value()))
                .map(CategoryShopVO::getName).toArray(String[]::new));
        //店铺分类
        List<CategoryVO> shopCategoryList = categoryService.listEnable(shopId);
        //判断店铺分类是否为空
        if (!Objects.equals(sysType, SysTypeEnum.SUPPLIER.value())) {
            if (shopCategoryList.size() != 0) {
                ProductLangUtil.categoryList(shopCategoryList);
                map.put(SHOP_CATEGORY_INDEX, shopCategoryList.stream().map(CategoryVO::getName).toArray(String[]::new));
            }
        }
        // 品牌(下拉数据)
        BrandSigningVO brandSigningVO = brandShopService.listSigningByShopId(shopId, sysType);
        List<String> brandNames = new ArrayList<>(Constant.INITIAL_CAPACITY);
        if (Objects.nonNull(brandSigningVO)) {
            if (!CollectionUtils.isEmpty(brandSigningVO.getPlatformBrandList())) {
                brandNames = brandSigningVO.getPlatformBrandList().stream().map(BrandShopVO::getName).collect(Collectors.toList());
            }
            if (!CollectionUtils.isEmpty(brandSigningVO.getCustomizeBrandList())) {
                brandNames.addAll(brandSigningVO.getCustomizeBrandList().stream().map(BrandShopVO::getName).toList());
            }
        }
        if (!CollectionUtils.isEmpty(brandNames)) {
            String[] brandNameArr = new String[brandNames.size()];
            brandNames.toArray(brandNameArr);
            map.put(BRAND_INDEX, brandNameArr);
        }
        // 构建excel
        ExcelWriter excelWriter = null;
        try {
            // 先执行合并策略
            ExcelWriterBuilder excelWriterMerge = ExcelUtil.getExcelWriterMerge(response, SpuExcelVO.EXCEL_NAME, SpuExcelVO.MERGE_ROW_INDEX, SpuExcelVO.MERGE_COLUMN_INDEX);
            excelWriter = ExcelUtil.getExcelModel(excelWriterMerge, map, Constant.START_ROW).build();

            // 业务代码
            if (CollUtil.isNotEmpty(list)) {
                // 进行写入操作
                WriteSheet sheetWriter;
                if (Objects.equals(AuthUserContext.get().getSysType(), SysTypeEnum.SUPPLIER.value())) {
                    sheetWriter = EasyExcel.writerSheet(SupplierProdExcelVO.SHEET_NAME).head(SupplierProdExcelVO.class)
                            .registerWriteHandler(new ProductCommentWriteHandler(SysTypeEnum.SUPPLIER.value())).build();
                } else {
                    sheetWriter = EasyExcel.writerSheet(SpuExcelVO.SHEET_NAME).head(SpuExcelVO.class)
                            .registerWriteHandler(new ProductCommentWriteHandler(SysTypeEnum.MULTISHOP.value())).build();
                }
                excelWriter.write(list, sheetWriter);
            }
        } catch (Exception e) {
            log.error("导出excel失败", e);
        } finally {
            // 千万别忘记finish 会帮忙关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

    @Override
    public List<SupplierSpuExcelVO> excelSupplierSpuList(SpuPageSearchDTO spuDTO) {
        spuDTO.setShopId(AuthUserContext.get().getTenantId());
        List<SupplierSpuExcelVO> list = spuMapper.excelSupplierSpuList(spuDTO);
        if (CollUtil.isEmpty(list)) {
            return list;
        }
        Set<Long> categoryIds = new HashSet<>(Constant.INITIAL_CAPACITY);
        List<Long> spuIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (SupplierSpuExcelVO supplierSpuExcelVO : list) {
            spuIds.add(supplierSpuExcelVO.getSpuId());
            categoryIds.add(supplierSpuExcelVO.getCategoryId());
            categoryIds.add(supplierSpuExcelVO.getShopCategoryId());
        }
        // 获取分类列表
        List<CategoryVO> categoryList = categoryService.listByCategoryIds(categoryIds);
        ProductLangUtil.categoryList(categoryList);
        Map<Long, CategoryVO> categoryMap = categoryList.stream().collect(Collectors.toMap(CategoryVO::getCategoryId, c -> c));
        // 获取sku信息列表
        List<SupplierSpuExcelVO> skuList = skuService.excelSupplierSkuList(spuIds);
        Map<Long, List<SupplierSpuExcelVO>> skuMap = skuList.stream().collect(Collectors.groupingBy(SupplierSpuExcelVO::getSpuId));
        List<SupplierSpuExcelVO> spuExcelList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 店铺运费模板
        ServerResponseEntity<List<ShopTransportVO>> response = deliveryFeignClient.listTransportByShopId(spuDTO.getShopId());
        if (!Objects.equals(response.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(response.getMsg());
        }
        Map<Long, String> transportMap = response.getData().stream().collect(Collectors.toMap(ShopTransportVO::getTransportId, ShopTransportVO::getTransName));

        //供应商名称
        List<Long> supplierIds = list.stream().map(SupplierSpuExcelVO::getSupplierId).collect(Collectors.toList());
        ServerResponseEntity<List<SupplierApiDetailVO>> listServerResponseEntity = supplierDetailFeignClient.listBySupplierIds(supplierIds);
        Map<Long, String> supplierName = listServerResponseEntity.getData().stream().collect(Collectors.toMap(SupplierApiDetailVO::getSupplierId, SupplierApiDetailVO::getSupplierName));
        int index = 1;
        for (SupplierSpuExcelVO supplierSpuExcelVO : list) {
            List<SupplierSpuExcelVO> skuData = skuMap.get(supplierSpuExcelVO.getSpuId());
            if (CollUtil.isEmpty(skuData)) {
                continue;
            }
            //供应商名称
            supplierSpuExcelVO.setSupplierName(supplierName.get(supplierSpuExcelVO.getSupplierId()));
            //发货方式
            Integer supplierDeliveryType = supplierSpuExcelVO.getSupplierDeliveryType();
            supplierSpuExcelVO.setSupplierDelivery(supplierDeliveryType == 1 ? SUPPLIER_SHIPMENTS : WAREHOUSE_SHIPMENTS);
            //代销商品状态
            int status = Integer.parseInt(supplierSpuExcelVO.getStatus());
            Integer skuChoiceStatus = supplierSpuExcelVO.getSkuChoiceStatus();
            if (status == 1) {
                supplierSpuExcelVO.setCommissionSpuStatus(skuChoiceStatus == 1 ? ENABLE : PORTION_ENABLE);
            }
            if (status == 0) {
                supplierSpuExcelVO.setCommissionSpuStatus(skuChoiceStatus == 1 ? DISABLE : PORTION_DISABLE);
            }
            supplierSpuExcelVO.setSeq(String.valueOf(index));
            supplierSpuExcelVO.setDeliveryTemplate(transportMap.get(supplierSpuExcelVO.getDeliveryTemplateId()));
            // 状态
            supplierSpuExcelVO.setStatus(getStatus(supplierSpuExcelVO.getStatus()));
            // 配送方式
            SpuVO.DeliveryModeVO deliveryModeVO = Json.parseObject(supplierSpuExcelVO.getDeliveryMode(), SpuVO.DeliveryModeVO.class);
            String delivery = getDelivery(deliveryModeVO);
            supplierSpuExcelVO.setDeliveryMode(delivery);
            handleSupplierSpuExcelInfo(categoryMap, skuData, spuExcelList, supplierSpuExcelVO);
            index++;
        }
        return spuExcelList;
    }

    @Override
    public List<PlatformSpuExcelVO> excelPlatformSpuList(ProductSearchDTO productSearchDTO) {
        productSearchDTO.setLang(I18nMessage.getLang());
        ServerResponseEntity<List<SpuSearchVO>> responseEntity = searchSpuFeignClient.listExcelPlatformSpu(productSearchDTO);
        if (!responseEntity.isSuccess()) {
            throw new LuckException(responseEntity.getMsg());
        }
        List<SpuSearchVO> spuEsList = responseEntity.getData();
        if (CollUtil.isEmpty(spuEsList)) {
            return new ArrayList<>(0);
        }
        List<Long> spuIds = spuEsList.stream().map(SpuSearchVO::getSpuId).collect(Collectors.toList());
        Map<Long, SpuSearchVO> esSpuMap = spuEsList.stream().collect(Collectors.toMap(SpuSearchVO::getSpuId, c -> c));
        List<PlatformSpuExcelVO> platformSpuExcelVOList = spuMapper.listPlatformSpuExcel(spuIds);
        Set<Long> categoryIds = new HashSet<>(Constant.INITIAL_CAPACITY);
        Set<Long> deliveryTemplateIds = new HashSet<>(Constant.INITIAL_CAPACITY);
        for (PlatformSpuExcelVO spuExcelVO : platformSpuExcelVOList) {
            categoryIds.add(spuExcelVO.getCategoryId());
            categoryIds.add(spuExcelVO.getShopCategoryId());
            deliveryTemplateIds.add(spuExcelVO.getDeliveryTemplateId());
        }
        // 获取分类列表
        List<CategoryVO> categoryList = categoryService.listByCategoryIds(categoryIds);
        ProductLangUtil.categoryList(categoryList);
        Map<Long, CategoryVO> categoryMap = categoryList.stream().collect(Collectors.toMap(CategoryVO::getCategoryId, c -> c));

        List<PlatformSpuExcelVO> skuExcelList = BeanUtil.mapAsList(skuService.excelSkuList(spuIds), PlatformSpuExcelVO.class);
        Map<Long, List<PlatformSpuExcelVO>> skuMap = skuExcelList.stream().collect(Collectors.groupingBy(PlatformSpuExcelVO::getSpuId));
        List<PlatformSpuExcelVO> spuExcelList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 店铺运费模板
        ServerResponseEntity<List<ShopTransportVO>> response = deliveryFeignClient.listTransportByIds(new ArrayList<>(deliveryTemplateIds));
        if (!response.isSuccess()) {
            throw new LuckException(response.getMsg());
        }
        Map<Long, String> transportMap = response.getData().stream().collect(Collectors.toMap(ShopTransportVO::getTransportId, ShopTransportVO::getTransName));

        int index = 1;
        for (PlatformSpuExcelVO spuExcelVO : platformSpuExcelVOList) {
            List<PlatformSpuExcelVO> skuData = skuMap.get(spuExcelVO.getSpuId());
            SpuSearchVO spuSearchVO = esSpuMap.get(spuExcelVO.getSpuId());
            if (CollUtil.isEmpty(skuData)) {
                continue;
            }
            spuExcelVO.setSeq(String.valueOf(index));
            spuExcelVO.setShopName(Objects.isNull(spuSearchVO.getShopName()) ? spuSearchVO.getSupplierName() : spuSearchVO.getShopName());
            spuExcelVO.setDeliveryTemplate(transportMap.get(spuExcelVO.getDeliveryTemplateId()));
            spuExcelVO.setSpuTypeName(SpuType.getSpuTypeName(spuSearchVO.getSpuType()));
            // 状态
            if (Objects.equals(spuSearchVO.getSpuStatus(), StatusEnum.ENABLE.value())) {
                spuExcelVO.setStatus(ENABLE);
            } else if (Objects.equals(spuSearchVO.getSpuStatus(), StatusEnum.DISABLE.value())) {
                spuExcelVO.setStatus(DISABLE);
            } else if (Objects.equals(spuSearchVO.getSpuStatus(), StatusEnum.OFFLINE.value())) {
                spuExcelVO.setStatus(OFFLINE);
            } else if (Objects.equals(spuSearchVO.getSpuStatus(), StatusEnum.WAIT_AUDIT.value())) {
                spuExcelVO.setStatus(WAIT_AUDIT);
            }
            setPlatformVirtualInfo(spuExcelVO, spuSearchVO);
            // 配送方式
            SpuVO.DeliveryModeVO deliveryModeVO = Json.parseObject(spuExcelVO.getDeliveryMode(), SpuVO.DeliveryModeVO.class);
            String delivery = getDelivery(deliveryModeVO);
            if (Objects.equals(spuExcelVO.getSpuMold(), VIRTUAL_SPU) || Objects.equals(spuExcelVO.getSpuType(), SpuType.ACTIVE.value())) {
                spuExcelVO.setDeliveryMode(DeliveryType.NOT_DELIVERY.description() + Constant.COMMA);
            } else {
                spuExcelVO.setDeliveryMode(delivery);
            }
            handlePlatformSpuExcelInfo(categoryMap, skuData, spuExcelList, spuExcelVO);
            index++;
        }
        return spuExcelList;
    }

    private static void setPlatformVirtualInfo(PlatformSpuExcelVO spuExcelVO, SpuSearchVO spuSearchVO) {
        // 虚拟商品信息
        spuExcelVO.setSpuMold(MOLD_MODE[spuSearchVO.getSpuMold()]);
//        spuExcelVO.setSpuMold(Objects.equals(spuSearchVO.getSpuMold(), 1) ? VIRTUAL_SPU : PHYSICAL_SPU);
        //虚拟商品的核销信息
        if (StrUtil.equals(spuExcelVO.getSpuMold(), VIRTUAL_SPU)) {
            if (StrUtil.equals(spuExcelVO.getWriteOffNum(), WITHOUT_STR)) {
                spuExcelVO.setWriteOffNum(WITHOUT);
            } else if (Objects.equals(spuExcelVO.getWriteOffNum(), REPEATEDLY_STR)) {
                spuExcelVO.setWriteOffNum(REPEATEDLY);
            } else if (Objects.equals(spuExcelVO.getWriteOffNum(), SINGLE_STR)) {
                spuExcelVO.setWriteOffNum(SINGLE);
            }
            spuExcelVO.setWriteOffMultipleCount(StrUtil.equals(spuExcelVO.getWriteOffMultipleCount(), UNLIMITED_STR) ? UNLIMITED : spuExcelVO.getWriteOffMultipleCount());
            spuExcelVO.setWriteOffTime(StrUtil.equals(spuExcelVO.getWriteOffTime(), null) ? "" : spuExcelVO.getWriteOffTime() + DAY_STR);
        }
        spuExcelVO.setIsRefund(StrUtil.equals(spuExcelVO.getIsRefund(), SINGLE_STR) ? YES : NO);
        spuExcelVO.setIsTop(StrUtil.equals(spuExcelVO.getIsTop(), SINGLE_STR) ? YES : NO);
    }

    private String getDelivery(SpuVO.DeliveryModeVO deliveryModeVO) {
        String delivery = "";
        if (deliveryModeVO.getHasUserPickUp()) {
            delivery = DeliveryType.STATION.description() + Constant.COMMA;
        }
        if (deliveryModeVO.getHasCityDelivery()) {
            delivery = delivery + DeliveryType.SAME_CITY.description() + Constant.COMMA;
        }
        if (deliveryModeVO.getHasShopDelivery()) {
            delivery = delivery + DeliveryType.DELIVERY.description() + Constant.COMMA;
        }
        return delivery;
    }

    private void handlePlatformSpuExcelInfo(Map<Long, CategoryVO> categoryMap, List<PlatformSpuExcelVO> skuData, List<PlatformSpuExcelVO> spuExcelList, PlatformSpuExcelVO spuExcelVO) {

        String brandName = null;
        if (CollUtil.isNotEmpty(spuExcelVO.getBrandLangList())) {
            BrandLangVO brandLang = ProductLangUtil.handelBrandLang(spuExcelVO.getBrandLangList());
            brandName = brandLang.getName();
        }
        // 名称、卖点
        for (SpuLangVO spuLangVO : spuExcelVO.getSpuLangList()) {
            if (Objects.equals(spuLangVO.getLang(), LanguageEnum.LANGUAGE_ZH_CN.getLang())) {
                spuExcelVO.setSellingPointZh(spuLangVO.getSellingPoint());
                spuExcelVO.setNameZh(spuLangVO.getSpuName());
            }
        }
        String categoryName = null;
        // 平台分类
        CategoryVO categoryVO = categoryMap.get(spuExcelVO.getCategoryId());
        if (Objects.nonNull(categoryVO)) {
            categoryName = categoryVO.getName();
        }
        String shopCategoryName = null;
        // 店铺分类
        CategoryVO shopCategoryVO = categoryMap.get(spuExcelVO.getShopCategoryId());
        if (Objects.nonNull(shopCategoryVO)) {
            shopCategoryName = shopCategoryVO.getName();
        }
        String delivery = spuExcelVO.getDeliveryMode();
        delivery = delivery.substring(0, delivery.length() - 1);
        for (PlatformSpuExcelVO spuExcel : skuData) {
            spuExcel.setPriceFee(AnalysisUtil.conversionPrices(spuExcel.getPriceFee()));
            spuExcel.setShopName(spuExcelVO.getShopName());
            spuExcel.setSpuTypeName(spuExcelVO.getSpuTypeName());
            spuExcel.setMarketPriceFee(AnalysisUtil.conversionPrices(spuExcel.getMarketPriceFee()));
            spuExcel.setSeq(spuExcelVO.getSeq());
            spuExcel.setWaterSoldNum(spuExcelVO.getWaterSoldNum());
            spuExcel.setDeliveryTemplate(spuExcelVO.getDeliveryTemplate());
            spuExcel.setBrandName(brandName);
            spuExcel.setDeliveryTemplate(spuExcelVO.getDeliveryTemplate());
            spuExcel.setNameZh(spuExcelVO.getNameZh());
            spuExcel.setSellingPointZh(spuExcelVO.getSellingPointZh());
            spuExcel.setCategoryName(categoryName);
            spuExcel.setShopCategoryName(shopCategoryName);
            spuExcel.setDeliveryMode(delivery);
            spuExcel.setStatus(spuExcelVO.getStatus());
            spuExcel.setSpuMold(spuExcelVO.getSpuMold());
            spuExcel.setWriteOffTime(spuExcelVO.getWriteOffTime());
            spuExcel.setWriteOffNum(spuExcelVO.getWriteOffNum());
            spuExcel.setWriteOffMultipleCount(spuExcelVO.getWriteOffMultipleCount());
            spuExcel.setWriteOffStart(spuExcelVO.getWriteOffStart());
            spuExcel.setWriteOffEnd(spuExcelVO.getWriteOffEnd());
            spuExcel.setIsRefund(spuExcelVO.getIsRefund());
            spuExcel.setIsTop(spuExcelVO.getIsTop());
            spuExcel.setVirtualRemark(spuExcelVO.getVirtualRemark());
            spuExcelList.add(spuExcel);
        }
    }

    private void handleSupplierSpuExcelInfo(Map<Long, CategoryVO> categoryMap, List<SupplierSpuExcelVO> skuData, List<SupplierSpuExcelVO> spuExcelList, SupplierSpuExcelVO spuExcelVO) {

        String brandName = null;
        if (CollUtil.isNotEmpty(spuExcelVO.getBrandLangList())) {
            BrandLangVO brandLang = ProductLangUtil.handelBrandLang(spuExcelVO.getBrandLangList());
            brandName = brandLang.getName();
        }
        // 名称、卖点
        for (SpuLangVO spuLangVO : spuExcelVO.getSpuLangList()) {
            if (Objects.equals(spuLangVO.getLang(), LanguageEnum.LANGUAGE_ZH_CN.getLang())) {
                spuExcelVO.setSellingPointZh(spuLangVO.getSellingPoint());
                spuExcelVO.setNameZh(spuLangVO.getSpuName());
            }
        }
        String categoryName = null;
        String shopCategoryName = null;
        // 店铺分类
        CategoryVO shopCategoryVO = categoryMap.get(spuExcelVO.getShopCategoryId());
        if (Objects.nonNull(shopCategoryVO)) {
            shopCategoryName = shopCategoryVO.getName();
        }
        // 平台分类
        CategoryVO categoryVO = categoryMap.get(spuExcelVO.getCategoryId());
        if (Objects.nonNull(categoryVO)) {
            categoryName = categoryVO.getName();
        }
        String delivery = spuExcelVO.getDeliveryMode();
        delivery = delivery.substring(0, delivery.length() - 1);
        for (SupplierSpuExcelVO spuExcel : skuData) {
            spuExcel.setPriceFee(AnalysisUtil.conversionPrices(spuExcel.getPriceFee()));
            spuExcel.setMarketPriceFee(AnalysisUtil.conversionPrices(spuExcel.getMarketPriceFee()));
            spuExcel.setSeq(spuExcelVO.getSeq());
            spuExcel.setBrandName(brandName);
            spuExcel.setDeliveryTemplate(spuExcelVO.getDeliveryTemplate());
            spuExcel.setNameZh(spuExcelVO.getNameZh());
            spuExcel.setSellingPointZh(spuExcelVO.getSellingPointZh());
            spuExcel.setShopCategoryName(shopCategoryName);
            spuExcel.setCategoryName(categoryName);
            spuExcel.setDeliveryMode(delivery);
            spuExcel.setStatus(spuExcelVO.getStatus());
            spuExcel.setCommissionSpuStatus(spuExcelVO.getCommissionSpuStatus());
            spuExcel.setSupplierDelivery(spuExcelVO.getSupplierDelivery());
            spuExcel.setSupplyPrice(AnalysisUtil.conversionPrices(spuExcel.getSupplyPrice()));
            spuExcel.setSupplierName(spuExcelVO.getSupplierName());
            spuExcelList.add(spuExcel);
        }
    }

    /**
     * 获取spu信息
     *
     * @param spuList
     * @param spu
     * @param categoryMap     平台分类
     * @param shopCategoryMap 店铺分类
     * @param transportMap    运费模板
     * @param brandMap        品牌
     */
    private void loadSpuData(List<SpuExcelVO> spuList, SpuDTO spu, Map<String, Long> categoryMap, Map<String, Long> shopCategoryMap,
                             Map<String, Long> transportMap, Map<String, List<BrandLang>> brandMap, Map<Integer, List<String>> errorMap) {
        Integer sysType = AuthUserContext.get().getSysType();
        boolean init = false;
        List<SkuDTO> skuList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (SpuExcelVO spuExcelVO : spuList) {
            if (!init) {
                if (StrUtil.isBlank(spuExcelVO.getNameZh())) {
                    addSpuExcelError(errorMap, SpuExportError.SPU_NAME, spuExcelVO.getSeq());
                    return;
                }
                spu.setSpuCode(Objects.nonNull(spuExcelVO.getSpuCode()) ? spuExcelVO.getSpuCode() : null);
                // 商品国际化信息
                spu.setSpuLangList(new ArrayList<>(1));
                SpuLangDTO spuLangDTO = new SpuLangDTO(LanguageEnum.LANGUAGE_ZH_CN.getLang(), spuExcelVO.getNameZh(), spuExcelVO.getSellingPointZh());
                spuLangDTO.setDetail(spuExcelVO.getDetailZh());
                spu.getSpuLangList().add(spuLangDTO);
                spu.setBrandId(handleBrand(brandMap.get(spuExcelVO.getBrandName())));
                // 平台分类
                Long categoryId = categoryMap.get(spuExcelVO.getCategoryName());
                if (Objects.isNull(categoryId)) {
                    addSpuExcelError(errorMap, SpuExportError.PLATFORM_CATEGORY, spuExcelVO.getSeq());
                    return;
                }
                spu.setCategoryId(categoryId);
                // 店铺分类
                Long shopCategoryId = shopCategoryMap.get(spuExcelVO.getShopCategoryName());
                //供应商没有店铺分类
                if (Objects.equals(sysType, SysTypeEnum.SUPPLIER.value())) {
                    spu.setShopCategoryId(-1L);
                    spu.setSupplierSpuType(SupplierSpuType.YES.value());
                } else {
                    if (Objects.isNull(shopCategoryId)) {
                        addSpuExcelError(errorMap, SpuExportError.SHOP_CATEGORY, spuExcelVO.getSeq());
                        return;
                    }
                    spu.setShopCategoryId(shopCategoryId);
                    spu.setSupplierSpuType(SupplierSpuType.NO.value());
                }
                if (handleVirtual(spu, errorMap, spuExcelVO)) {
                    return;
                }
                spu.setDeliveryMode(getDeliveryMode(spuExcelVO.getDeliveryMode()));
                spu.setPreSaleType(Objects.isNull(spu.getPreSaleType()) ? -1 : spu.getPreSaleType());
                // 运费模板
                Long deliveryTemplateId = transportMap.get(spuExcelVO.getDeliveryTemplate());
                if (Objects.isNull(deliveryTemplateId) && !Objects.equals(spu.getSpuMold(), 1)) {
                    addSpuExcelError(errorMap, SpuExportError.DELIVER, spuExcelVO.getSeq());
                    return;
                }
                setSpuInfo(spu, spuExcelVO, deliveryTemplateId);
                init = true;
            }
            SkuDTO sku;
            try {
                //多规格商品  销售属性不能为空
                if (skuList.size() > 0 && StrUtil.isBlank(spuExcelVO.getPropertiesZh())) {
                    addSpuExcelError(errorMap, SpuExportError.PROPERTIES, spuExcelVO.getSeq());
                }
                sku = loadSkuData(spuExcelVO, spu, errorMap);
            } catch (Exception e) {
                if (!Objects.equals(e.getMessage(), ResponseEnum.DATA_ERROR.value())) {
                    addSpuExcelError(errorMap, SpuExportError.PRODUCT_DATA, spuExcelVO.getSeq());
                }
                return;
            }
            skuList.add(sku);
        }
        spu.setSkuList(skuList);
        setPrice(spu, skuList);
        // 保存商品信息
        spuService.save(spu);
    }

    private boolean handleVirtual(SpuDTO spu, Map<Integer, List<String>> errorMap, SpuExcelVO spuExcelVO) {
        // 虚拟商品信息
        if (Objects.equals(spuExcelVO.getIsRefund(), YES)) {
            spu.setIsRefund(1);
        } else {
            spu.setIsRefund(0);
        }
        if (Objects.equals(spuExcelVO.getSpuMold(), PHYSICAL_SPU)) {
            spu.setSpuMold(0);
            spu.setIsRefund(1);
            spu.setVirtualRemark(null);
            if (StrUtil.contains(spuExcelVO.getDeliveryMode(), DeliveryType.NOT_DELIVERY.description())) {
                addSpuExcelError(errorMap, SpuExportError.DELIVERY_TYPE, spuExcelVO.getSeq());
                return true;
            }
        } else if (Objects.equals(spuExcelVO.getSpuMold(), VIRTUAL_SPU)) {
            spu.setSpuMold(1);
            String writeOffNum = spuExcelVO.getWriteOffNum();
            String writeOffTime = spuExcelVO.getWriteOffTime();
            if (!StrUtil.equals(writeOffNum, WITHOUT) && Objects.isNull(writeOffTime)) {
                addSpuExcelError(errorMap, SpuExportError.VIRTUAL_DATA, spuExcelVO.getSeq());
                return true;
            }
            switch (writeOffNum) {
                case REPEATEDLY:
                    spu.setWriteOffNum(-1);
                    spu.setWriteOffMultipleCount(StrUtil.equals(spuExcelVO.getWriteOffMultipleCount(), UNLIMITED) || StrUtil.isBlank(spuExcelVO.getWriteOffMultipleCount()) ? -1 : Integer.parseInt(spuExcelVO.getWriteOffMultipleCount().replace("次", "")));
                    break;
                case WITHOUT:
                    spu.setWriteOffNum(0);
                    break;
                case SINGLE:
                    spu.setWriteOffNum(1);
                    break;
                default: break;
            }
            if (StrUtil.equals(spuExcelVO.getWriteOffNum(), WITHOUT)) {
                spu.setWriteOffTime(null);
            }else if (StrUtil.equals(writeOffTime, CUSTOMIZATION)) {
                spu.setWriteOffTime(0);
            } else if (StrUtil.equals(writeOffTime, LONG_TERM)) {
                spu.setWriteOffTime(-1);
            } else {
                spu.setWriteOffTime(Integer.parseInt(spuExcelVO.getWriteOffTime().replace(DAY_STR, "")));
            }
            spu.setWriteOffStart(spuExcelVO.getWriteOffStart());
            spu.setWriteOffEnd(spuExcelVO.getWriteOffEnd());
            spu.setVirtualRemark(spuExcelVO.getVirtualRemark());
            spu.setDeliveryMode(DeliveryType.NOT_DELIVERY.description());
        }
        return false;
    }

    private static void setSpuInfo(SpuDTO spu, SpuExcelVO spuExcelVO, Long deliveryTemplateId) {
        spu.setDeliveryTemplateId(deliveryTemplateId);
        if (Objects.nonNull(deliveryTemplateId) && deliveryTemplateId == -1L) {
            spu.setDeliveryAmount(Math.round(Arith.mul(Double.parseDouble(spuExcelVO.getDeliveryAmount()), Constant.PRICE_MAGNIFICATION)));
        }
        spu.setPriceFee(Constant.MIN_SPU_AMOUNT);
        spu.setMarketPriceFee(Constant.MIN_SPU_AMOUNT);
        if (Objects.equals(spuExcelVO.getStatus(), ENABLE)) {
            spu.setStatus(StatusEnum.ENABLE.value());
        } else {
            spu.setStatus(StatusEnum.DISABLE.value());
        }
        spu.setMainImgUrl(StrUtil.isNotBlank(spuExcelVO.getImgs()) ? spuExcelVO.getImgs().split(",")[0] : "");
        spu.setImgUrls(StrUtil.isNotBlank(spuExcelVO.getImgs()) ? spuExcelVO.getImgs() : "");
        spu.setVideo(spuExcelVO.getVideo());
        spu.setHasSkuImg(0);
        spu.setSpuType(SpuType.NORMAL.value());
        spu.setSeq(1);
        spu.setScoreFee(Constant.ZERO_LONG);
        if (Objects.isNull(spu.getSpuMold())) {
            spu.setSpuMold(0);
        }
    }

    private static void setPrice(SpuDTO spu, List<SkuDTO> skuList) {
        // 售价最小的sku，决定spu的售价以及市场价
        Long priceFee = Long.MAX_VALUE;
        Long marketPriceFee = Constant.MIN_SPU_AMOUNT;
        for (SkuDTO sku : skuList) {
            if (sku.getPriceFee() < priceFee) {
                priceFee = sku.getPriceFee();
                marketPriceFee = sku.getMarketPriceFee();
            }
        }
        if (priceFee == Long.MAX_VALUE) {
            priceFee = Constant.MIN_SPU_AMOUNT;
        }
        spu.setPriceFee(priceFee);
        spu.setMarketPriceFee(marketPriceFee);
    }

    private Long handleBrand(List<BrandLang> brandLangList) {
        if (CollUtil.isEmpty(brandLangList)) {
            return null;
        }
        if (brandLangList.size() > 1) {
            brandLangList.sort(Comparator.comparing(BrandLang::getLang).thenComparing(BrandLang::getBrandId).reversed());
        }
        return brandLangList.get(0).getBrandId();
    }


    /**
     * 获取spu配送类型信息
     *
     * @param data
     * @return
     */
    private String getDeliveryMode(String data) {
        SpuVO.DeliveryModeVO deliveryModeVO = new SpuVO.DeliveryModeVO();
        // 默认支持快递
        deliveryModeVO.setHasShopDelivery(Boolean.TRUE);
        deliveryModeVO.setHasCityDelivery(StrUtil.contains(data, DeliveryType.SAME_CITY.description()));
        deliveryModeVO.setHasUserPickUp(StrUtil.contains(data, DeliveryType.STATION.description()));
        return Json.toJsonString(deliveryModeVO);
    }

    /**
     * 获取sku数据
     *
     * @param spuExcelVO
     * @param spu
     * @param errorMap
     * @return
     */
    private SkuDTO loadSkuData(SpuExcelVO spuExcelVO, SpuDTO spu, Map<Integer, List<String>> errorMap) {
        spu.setTotalStock(0);
        SkuDTO sku = new SkuDTO();
        sku.setSkuLangList(new ArrayList<>(Constant.INITIAL_CAPACITY));
        StrUtil.isNotBlank(sku.getSkuName());
        sku.setPriceFee(conversionPricesToLong(spuExcelVO.getPriceFee()));
        sku.setMarketPriceFee(conversionPricesToLong(spuExcelVO.getMarketPriceFee()));
        sku.setStatus(StatusEnum.ENABLE.value());
        sku.setStock(getStock(spuExcelVO.getStock()));
        // 添加管理库存点数据
        StockPointSkuDTO stockPointSkuDTO = new StockPointSkuDTO();
        Long warehouseId = warehouseFeignClient.getDefaultIdByShopId(AuthUserContext.get().getTenantId(), AuthUserContext.get().getSysType()).getData();
        stockPointSkuDTO.setStockPointId(warehouseId);
        stockPointSkuDTO.setStockPointType(StockPointType.WAREHOUSE.getValue());
        stockPointSkuDTO.setType(0);
        stockPointSkuDTO.setStock(sku.getStock());
        sku.setStockPointList(Collections.singletonList(stockPointSkuDTO));
        spu.setTotalStock(spu.getTotalStock() + sku.getStock());
        sku.setPartyCode(spuExcelVO.getPartyCode());
        sku.setWeight(spuExcelVO.getWeight());
        sku.setVolume(spuExcelVO.getVolume());
        sku.setStockWarning(spuExcelVO.getStockWarning());
        sku.setScoreFee(Constant.ZERO_LONG);
        if (sku.getPriceFee() < spu.getPriceFee()) {
            spu.setPriceFee(sku.getPriceFee());
        }
        if (sku.getMarketPriceFee() < spu.getMarketPriceFee()) {
            spu.setMarketPriceFee(sku.getMarketPriceFee());
        }
        boolean blankSkuNameZh = StrUtil.isBlank(spuExcelVO.getSkuNameZh());
        boolean blankPropertiesZh = StrUtil.isBlank(spuExcelVO.getPropertiesZh());
        if (blankSkuNameZh && blankPropertiesZh) {
            return sku;
        }
        // 属性值及sku名称状态必须一致（都为空，或都有值）
        else if (!Objects.equals(blankPropertiesZh, blankSkuNameZh)) {
            addSpuExcelError(errorMap, blankPropertiesZh ? SpuExportError.SKU_NAME : SpuExportError.PROPERTIES, spuExcelVO.getSeq());
            throw new LuckException(ResponseEnum.DATA_ERROR);
        }


        sku.setSpuSkuAttrValues(new ArrayList<>(Constant.INITIAL_CAPACITY));
        String[] propertiesZh = spuExcelVO.getPropertiesZh().split(Constant.SEMICOLON);
        StringBuilder attrsZh = new StringBuilder(Constant.INITIAL_CAPACITY);
        StringBuilder attrsEn = new StringBuilder(Constant.INITIAL_CAPACITY);
        for (String s : propertiesZh) {
            SpuSkuAttrValueDTO spuSkuAttrValue = new SpuSkuAttrValueDTO();
            spuSkuAttrValue.setSpuSkuAttrValueLangList(new ArrayList<>(Constant.INITIAL_CAPACITY));
            setSpuSkuAttrValueLang(spuSkuAttrValue, s, attrsZh, LanguageEnum.LANGUAGE_ZH_CN.getLang());
            sku.getSpuSkuAttrValues().add(spuSkuAttrValue);
        }
        attrsZh.deleteCharAt(attrsZh.lastIndexOf(Constant.COMMA));
        // sku国际化信息
        sku.getSkuLangList().add(new SkuLangDTO(LanguageEnum.LANGUAGE_ZH_CN.getLang(), spuExcelVO.getSkuNameZh(), attrsZh.toString()));
        return sku;
    }

    /**
     * 插入属性数据
     *
     * @param spuSkuAttrValue
     * @param property
     * @param attrs
     * @param lang
     */
    private void setSpuSkuAttrValueLang(SpuSkuAttrValueDTO spuSkuAttrValue, String property, StringBuilder attrs, Integer lang) {
        String[] attr = property.split(Constant.COLON);
        attrs.append(attr[0]).append(Constant.COMMA);
        SpuSkuAttrValueLangDTO spuSkuAttrValueLangDTO = new SpuSkuAttrValueLangDTO();
        spuSkuAttrValueLangDTO.setLang(lang);
        spuSkuAttrValueLangDTO.setAttrName(attr[0]);
        spuSkuAttrValueLangDTO.setAttrValueName(attr[1]);
        spuSkuAttrValue.getSpuSkuAttrValueLangList().add(spuSkuAttrValueLangDTO);
    }

    /**
     * 获取sku库存
     *
     * @param stock
     * @return
     */
    private Integer getStock(Integer stock) {
        Integer minStock = 0;
        if (Objects.isNull(stock) || stock < minStock) {
            return minStock;
        }
        return stock;
    }

    /**
     * 金额Double格式转换Long
     *
     * @param num
     * @return
     */
    private Long conversionPricesToLong(String num) {
        long amount;
        try {
            amount = Math.round(Arith.mul(Double.parseDouble(num), Constant.PRICE_MAGNIFICATION));
            if (amount < Constant.MIN_SPU_AMOUNT) {
                amount = Constant.MIN_SPU_AMOUNT;
            }
            if (amount > Constant.MAX_SPU_AMOUNT) {
                amount = Constant.MAX_SPU_AMOUNT;
            }
        } catch (Exception e) {
            amount = Constant.MIN_SPU_AMOUNT;
        }
        return amount;
    }
}
