package com.cyksj.service.mange.goods;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.util.Jsons;
import com.cyksj.mapper.DistributeGoodsSkuAlertMapper;
import com.cyksj.mapper.GoodsDonMapper;
import com.cyksj.mapper.GoodsDonSkuMapper;
import com.cyksj.mapper.GoodsDonSpecMapper;
import com.cyksj.model.entity.*;
import com.cyksj.model.manage.request.ReqGoodsSkuInsert;
import com.cyksj.model.manage.request.ReqGoodsSkuSpec;
import com.cyksj.model.manage.request.ReqGoodsSpecSingle;
import com.cyksj.model.request.CombinationSkuReq;
import com.cyksj.service.mange.CmsGoodsDonSpecService;
import com.cyksj.service.translations.BackInfoTranslationsService;
import com.fasterxml.jackson.databind.JavaType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * @author chan
 * @date 2022/9/27 5:19 PM
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CmsGoodsDonSpecServiceImpl extends ServiceImpl<GoodsDonSpecMapper, GoodsDonSpec> implements CmsGoodsDonSpecService {
	private final GoodsDonMapper goodsDonMapper;

	private final GoodsDonSkuMapper goodsDonSkuMapper;

	private final DistributeGoodsSkuAlertMapper distributeGoodsSkuAlertMapper;

	private final BackInfoTranslationsService backInfoTranslationsService;

	private final HttpServletRequest request;

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void insertOrUpdateSkuSpec(ReqGoodsSkuInsert insert, Boolean isUpdate) throws Exception {
		GoodsDon goods = goodsDonMapper.selectById(insert.getGoodsId());
		if (null == goods) {
			throw new RuntimeException("找不到商品spu.");
		}
		String lang = request.getHeader("lang");
		GoodsDonSpec loveSpec = this.getOne(Wrappers.lambdaQuery(GoodsDonSpec.class).eq(GoodsDonSpec::getGoodsId, insert.getGoodsId()));
		Map<String, List<ReqGoodsSkuSpec>> dbSpecMap = null;
		Map<Integer, ReqGoodsSkuSpec.Node> dbNodeMap = null;
		if (null != loveSpec) {
			insert.setId(loveSpec.getId());
			String specsJson = loveSpec.getSpecsJson();
			dbSpecMap = Jsons.parseList(specsJson, ReqGoodsSkuSpec.class).stream().collect(Collectors.groupingBy(ReqGoodsSkuSpec::getKey));
		}
		if (isUpdate && loveSpec == null) {
			throw BusinessRuntimeException.getInstance("所更新的平台id:{0}属性不存在", insert.getGoodsId());
		}

		List<ReqGoodsSkuSpec> specs = insert.getSpecs();
		if (null == specs || specs.isEmpty()) {
			throw new RuntimeException("缺少商品总规格.");
		}

		// 属性最大id
		Integer maxId = 0;
		if (loveSpec != null && loveSpec.getMaxId() != null) {
			maxId = loveSpec.getMaxId();
		}
		// 统计总属性数
		Integer total = 0;
		// 判断id是否有重复
		Map<Integer, ReqGoodsSpecSingle> map = null;
		// 规格数量
		int specNumber = specs.size();

		dbNodeMap = checkUpdateGoodsSpec(goods.getId(), dbSpecMap, dbNodeMap, specs);

		for (ReqGoodsSkuSpec spec : specs) {
			if (StringUtils.isBlank(spec.getKey())) {
				throw new RuntimeException("存在空白规格名.");
			}

			List<ReqGoodsSkuSpec.Node> values = spec.getValues();
			if (null == values || values.isEmpty()) {
				throw new RuntimeException("规格[" + spec.getKey() + "]中缺少属性.");
			}
			total += values.size();
			for (ReqGoodsSkuSpec.Node e : values) {
				if (null == e.getId() || e.getId() < 0) {
					e.setId(maxId + 1);
				}
				if (StringUtils.isBlank(e.getValue())) {
					throw new RuntimeException("规格[" + spec.getKey() + "]中存在空白属性.");
				}
				if (e.getId() > maxId) {
					maxId = e.getId();
				}
				//新增时 实物价格要填入
				if (goods.getType() == 2 && insert.getId()  == null && (e.getPrice() == null || e.getPrice().compareTo(BigDecimal.ZERO) < 0)) {
					throw BusinessRuntimeException.getInstance("实物规格:{0}对应价格请输入", e.getValue());
				}

				if (null == map) {
					map = new HashMap<>(16);
				}
				String benefitsList = e.getBenefitsList();
				if (StrUtil.isNotBlank(benefitsList)) {
					Set<GoodsDonSku> benefitsSkuIds = Jsons.parseSet(benefitsList, GoodsDonSku.class);
					e.setBenefitsList(Jsons.toJson(benefitsSkuIds));
				}
				syncSpecNodeSku(goods.getId(), dbNodeMap, e, lang);

				ReqGoodsSpecSingle single = new ReqGoodsSpecSingle();
				single.setId(e.getId());
				single.setKey(spec.getKey());
				single.setName(e.getValue());
				map.put(e.getId(), single);
			}
		}

		if (map.size() != total) {
			throw new RuntimeException("规格中存在重复id.");
		}

		GoodsDonSpec spec = new GoodsDonSpec();
		spec.setId(insert.getId());
		spec.setGoodsId(insert.getGoodsId());
		spec.setMaxId(maxId);
		spec.setSpecsJson(Jsons.toJson(specs));
		spec.setSpecNumber(specNumber);
		spec.setSpecMapping(Jsons.toJson(map));
		if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
			//spec
			backInfoTranslationsService.saveOrUpdateBackInfoTranslations(BackInfoTranslations.Type.spec, spec.getId(), spec, lang);
			//sku
			List<GoodsDonSku> goodsDonSkus = goodsDonSkuMapper.selectList(Wrappers.lambdaQuery(GoodsDonSku.class)
					.eq(GoodsDonSku::getGoodsId, goods.getId()));
			List<GoodsDonSku> resetSkuSpec = resetSkuSpec(goodsDonSkus, spec);
			resetSkuSpec.stream().forEach(sku -> backInfoTranslationsService.saveOrUpdateBackInfoTranslations(BackInfoTranslations.Type.sku, sku.getId(), sku, lang));
		} else {
			if (insert.getId() != null) {
				this.updateById(spec);
				return;
			}
			this.save(spec);
		}
	}

	@Override
	public void skuAppend(ReqGoodsSkuInsert insert, GoodsDon goods) throws Exception {

		GoodsDonSpec loveSpec = this.getOne(Wrappers.lambdaQuery(GoodsDonSpec.class).eq(GoodsDonSpec::getGoodsId, insert.getGoodsId()));
		if (null == loveSpec) {
			throw new RuntimeException("该商品未设置总规格, 请设置总规格.");
		}

		List<ReqGoodsSkuInsert.Sku> skus = insert.getSkus();
		if (null == skus || skus.isEmpty()) {
			throw new RuntimeException("参数错误.");
		}
		int specNumber = loveSpec.getSpecNumber();

		JavaType type = Jsons.javaType().constructMapType(HashMap.class, Integer.class, ReqGoodsSpecSingle.class);
		Map<Integer, ReqGoodsSpecSingle> map = Jsons.parseObject(loveSpec.getSpecMapping(), type);

		StringBuilder builder = new StringBuilder();
		List<ReqGoodsSpecSingle> specList = null;
		GoodsDonSku goodsDonSku = null;

		// 判断属性是否属于同一个key
		Set<String> set = null;

		for (ReqGoodsSkuInsert.Sku sku : insert.getSkus()) {
			// 跳过空值的sku
			// 解析sku的规格属性
			final String specIds = sku.getSpecIds();
			if (StringUtils.isBlank(specIds)) {
				throw new RuntimeException("请选择商品的规格.");
			}
			int[] ids = Jsons.parseObject(specIds, int[].class);
//            if (ids.length != specNumber) {
//                throw new RuntimeException("sku规格数量 与 总规格数量 不一致.");
//            }

			// init
			builder.delete(0, builder.length());
			if (null == specList) {
				specList = new ArrayList<>(specNumber);
			} else {
				specList.clear();
			}
			if (null == set) {
				int capacity = (specNumber + 1) * 4 / 3 + 1;
				set = new HashSet<>(capacity);
			} else {
				set.clear();
			}

			for (int id : ids) {
				ReqGoodsSpecSingle single = map.get(id);
				if (null == single) {
					throw new RuntimeException("总规格属性id中 不存在 sku中的id.");
				}
				builder.append(single.getName()).append(';');
				specList.add(single);
				set.add(single.getKey());
			}
//            if (set.size() != specNumber) {
//                throw new RuntimeException("sku中存在多个属性属于同一个规格.");
//            }

			String specVal = builder.toString();
			String specJson = Jsons.toJson(specList);

			if (null == goodsDonSku) {
				goodsDonSku = new GoodsDonSku();
				goodsDonSku.setGoodsId(insert.getGoodsId());
			}
			BeanUtil.copyProperties(sku, goodsDonSku);
			String specIdsStr = Jsons.toJson(ids);
			//升序
			Arrays.sort(ids);
			String dupSpecIds = Jsons.toJson(ids);
			GoodsDonSku specIds_exists = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class)
					.and(qr -> qr.eq(GoodsDonSku::getDupSpecIds, dupSpecIds).or().eq(GoodsDonSku::getSpecIds, specIdsStr))
					.eq(GoodsDonSku::getGoodsId, goods.getId())
					.last("limit 1"));
			if (specIds_exists != null) {
				log.info("库中存在相同二级分类的规格,spec_ids:{}", dupSpecIds);
				continue;
			}
			goodsDonSku.setSpecIds(specIdsStr);
			goodsDonSku.setDupSpecIds(dupSpecIds);
			goodsDonSku.setSpecVal(specVal);
			goodsDonSku.setSpecJson(specJson);
			String benefitsList = goodsDonSku.getBenefitsList();
			if (StrUtil.isNotBlank(benefitsList)) {
				Set<GoodsDonSku> benefitsSkuIds = Jsons.parseSet(benefitsList, GoodsDonSku.class);
				goodsDonSku.setIsBenefits(true);
				goodsDonSku.setBenefitsList(Jsons.toJson(benefitsSkuIds));
			}
			if (goods.getType() == 1) {
				if (sku.getMonths() != null && sku.getMonths() > 0 && sku.getDays() != null && sku.getDays() > 0)
					throw BusinessRuntimeException.getInstance("续费天数和续费月数不能同时存在");
				if (sku.getMonths() == null && sku.getDays() == null)
					throw BusinessRuntimeException.getInstance("请输入对应续费时间");
			}
			String specificGoodsIds = goodsDonSku.getSpecificGoodsIds();
			if (StrUtil.isNotBlank(specificGoodsIds)) {
				Set<Long> specificGids = Jsons.parseSet(specificGoodsIds, Long.class);
				if (specificGids.isEmpty()) {
					goodsDonSku.setSpecificPrice(BigDecimal.ZERO);
				} else {
					Integer count = goodsDonMapper.selectCount(Wrappers.lambdaQuery(GoodsDon.class)
							.in(GoodsDon::getId, specificGids)
							.eq(GoodsDon::getStatus, true)
							.eq(GoodsDon::getDeleted, true));
					if (count != specificGids.size()) {
						throw BusinessRuntimeException.getInstance("存在被删除或已下架的平台");
					}
					BigDecimal specificPrice = goodsDonSku.getSpecificPrice();
					if (specificPrice == null || specificPrice.compareTo(BigDecimal.ZERO) <= 0) {
						throw BusinessRuntimeException.getInstance("请输入正确的特定价格");
					}
				}
			}
			if (StrUtil.isNotEmpty(goodsDonSku.getUserOwns())) {
				List<Long> userOwnsList = Jsons.parseList(goodsDonSku.getUserOwns(), Long.class);
				if (CollUtil.isEmpty(userOwnsList)) {
					goodsDonSku.setUserOwns(null);
				} else {
					goodsDonSku.setUserOwns(userOwnsList.toString());
				}
			}
			goodsDonSkuMapper.insert(goodsDonSku);

			DistributeGoodsSkuAlert distributeGoodsSkuAlert = new DistributeGoodsSkuAlert();
			distributeGoodsSkuAlert.setGoodsId(goods.getId());
			distributeGoodsSkuAlert.setSkuId(goodsDonSku.getId());
			distributeGoodsSkuAlertMapper.insert(distributeGoodsSkuAlert);
		}
	}

	@Override
	public void combinationSku(Long goodsId, List<CombinationSkuReq> combinations) throws Exception {
		GoodsDon goodsDon = goodsDonMapper.selectById(goodsId);
		if (goodsDon == null) throw BusinessRuntimeException.getInstance("平台不存在");
		if (goodsDon.getType() != 2) {
			throw BusinessRuntimeException.getInstance("暂只支持实物规格");
		}
		GoodsDonSpec loveSpec = this.getOne(Wrappers.lambdaQuery(GoodsDonSpec.class).eq(GoodsDonSpec::getGoodsId, goodsId));
		if (null == loveSpec) {
			throw new RuntimeException("该商品未设置总规格, 请设置总规格.");
		}
		String specsJson = loveSpec.getSpecsJson();
		List<ReqGoodsSkuSpec> specsList = Jsons.parseList(specsJson, ReqGoodsSkuSpec.class);
		Map<String, List<ReqGoodsSkuSpec>> specValueMap = specsList.stream().collect(Collectors.groupingBy(ReqGoodsSkuSpec::getKey));
		if (combinations.isEmpty()) {
			throw BusinessRuntimeException.getInstance("请选择对应的规格组合");
		}
		List<ReqGoodsSkuInsert.Sku> skus = new LinkedList<>();
		ReqGoodsSkuInsert reqGoodsSkuInsert = new ReqGoodsSkuInsert();
		reqGoodsSkuInsert.setGoodsId(goodsId);
		List<List<Integer>> specIdLists = new LinkedList<>();
		CombinationSkuReq request = combinations.get(0);
		List<ReqGoodsSkuSpec> reqGoodsSkuSpecs = specValueMap.get(request.getKey());
		if (reqGoodsSkuSpecs == null) {
			throw BusinessRuntimeException.getInstance("传入的总规格属性:{0}不存在", request.getKey());
		}
		Map<Integer, List<ReqGoodsSkuSpec.Node>> nodeIdMap = reqGoodsSkuSpecs.get(0).getValues().stream().collect(Collectors.groupingBy(ReqGoodsSkuSpec.Node::getId));
		if (CollUtil.isNotEmpty(request.getValues())) {
			unifiedHandleCombinationSku(combinations, request.getValues(), specValueMap, nodeIdMap, specIdLists, skus);
		} else {
			ReqGoodsSkuSpec reqGoodsSkuSpec = reqGoodsSkuSpecs.get(0);
			unifiedHandleCombinationSku(combinations,reqGoodsSkuSpec.getValues(),specValueMap, nodeIdMap,specIdLists,skus);
		}
		reqGoodsSkuInsert.setSkus(skus);
		skuAppend(reqGoodsSkuInsert, goodsDon);
	}

	public void unifiedHandleCombinationSku(List<CombinationSkuReq> combinations, List<ReqGoodsSkuSpec.Node> values, Map<String, List<ReqGoodsSkuSpec>> specValueMap, Map<Integer, List<ReqGoodsSkuSpec.Node>> nodeIdMap, List<List<Integer>> specIdLists, List<ReqGoodsSkuInsert.Sku> skus) throws Exception {
		for (ReqGoodsSkuSpec.Node node_value : values) {
			ReqGoodsSkuInsert.Sku sku = new ReqGoodsSkuInsert.Sku();
			sku.setPrice(BigDecimal.ZERO);
			List<Integer> specIds = new LinkedList<>();
			unifiedHandleSecondCombinationSku(node_value, nodeIdMap, sku, specIds);
			recurCombinationSku(combinations, combinations.size(), 1, 1, specIds, specIdLists, sku, specValueMap, skus);
		}
	}


	public void unifiedHandleSecondCombinationSku(ReqGoodsSkuSpec.Node temp_node, Map<Integer, List<ReqGoodsSkuSpec.Node>> nodeIdMap, ReqGoodsSkuInsert.Sku sku, List<Integer> specIds) {
		List<ReqGoodsSkuSpec.Node> nodes = nodeIdMap.get(temp_node.getId());
		if (CollUtil.isEmpty(nodes)) {
			throw BusinessRuntimeException.getInstance("{0}规格不存在", temp_node.getValue());
		}
		ReqGoodsSkuSpec.Node node = nodes.get(0);
		BigDecimal price = node.getPrice();
		if (price == null && node.getValue().contains("无")) {
			price = BigDecimal.ZERO;
		}
		if (price == null) {
			throw BusinessRuntimeException.getInstance("该实物子规格:{0}未配置价格", node.getValue());
		}
		sku.setPrice(sku.getPrice().add(price));
		specIds.add(temp_node.getId());
		if (StrUtil.isNotEmpty(node.getBenefitsList())) {
			sku.setIsBenefits(true);
			sku.setBenefitsList(node.getBenefitsList());
		}
	}

	/**
	 * @param combinations 传入的组合数据
	 * @param total        总共需要组合的大小
	 * @param has          已有组合数大小
	 * @param start        下一个组合数组下表
	 * @param specIds      组合规格ids
	 * @param sku          待插入库中的sku
	 * @param specValueMap 总规格库中对应values
	 */
	private void recurCombinationSku(List<CombinationSkuReq> combinations, Integer total, Integer has, Integer start, List<Integer> specIds, List<List<Integer>> specIdLists, ReqGoodsSkuInsert.Sku sku, Map<String, List<ReqGoodsSkuSpec>> specValueMap, List<ReqGoodsSkuInsert.Sku> skus) throws Exception {
		if (has == total) {
			if (specIdLists.contains(specIds)) {
				return;
			}
			sku.setSpecIds(Jsons.toJson(specIds));
			skus.add(sku);
			return;
		}
		CombinationSkuReq request = combinations.get(start);
		List<ReqGoodsSkuSpec> reqGoodsSkuSpecs = specValueMap.get(request.getKey());
		if (reqGoodsSkuSpecs == null) {
			throw BusinessRuntimeException.getInstance("总规格属性{0}不存在", request.getKey());
		}
		ReqGoodsSkuSpec reqGoodsSkuSpec = reqGoodsSkuSpecs.get(0);
		Map<Integer, List<ReqGoodsSkuSpec.Node>> nodeIdMap = reqGoodsSkuSpec.getValues().stream().collect(Collectors.groupingBy(ReqGoodsSkuSpec.Node::getId));
		if (CollUtil.isNotEmpty(request.getValues())) {
			createNewSkuAndRecurCombination(combinations, request.getValues(), nodeIdMap, has, start, specIds, specIdLists, sku, specValueMap, skus);
			return;
		}
		createNewSkuAndRecurCombination(combinations, reqGoodsSkuSpec.getValues(), nodeIdMap, has, start, specIds, specIdLists, sku, specValueMap, skus);
	}

	/**
	 * 新的规格 递归
	 */
	public void createNewSkuAndRecurCombination(List<CombinationSkuReq> combinations, List<ReqGoodsSkuSpec.Node> values, Map<Integer, List<ReqGoodsSkuSpec.Node>> nodeIdMap, Integer has, Integer start, List<Integer> specIds, List<List<Integer>> specIdLists, ReqGoodsSkuInsert.Sku sku, Map<String, List<ReqGoodsSkuSpec>> specValueMap, List<ReqGoodsSkuInsert.Sku> skus) throws Exception {
		for (ReqGoodsSkuSpec.Node node_value : values) {
			BigDecimal last_price = sku.getPrice();
			unifiedHandleSecondCombinationSku(node_value, nodeIdMap, sku, specIds);
			recurCombinationSku(combinations, combinations.size(), has + 1, start + 1, specIds, specIdLists, sku, specValueMap, skus);
			specIds.remove(node_value.getId());
			sku = new ReqGoodsSkuInsert.Sku();
			sku.setPrice(last_price);
		}
	}

	/**
	 * 更新删除总属性 一级分类 校验
	 */
	public Map<Integer, ReqGoodsSkuSpec.Node> checkUpdateGoodsSpec(Long goodsId, Map<String, List<ReqGoodsSkuSpec>> dbSpecMap, Map<Integer, ReqGoodsSkuSpec.Node> dbNodeMap, List<ReqGoodsSkuSpec> specs) {
		if (CollUtil.isNotEmpty(dbSpecMap)) {
			Map<String, List<ReqGoodsSkuSpec>> updateSpecMap = specs.stream().collect(Collectors.groupingBy(ReqGoodsSkuSpec::getKey));
			dbNodeMap = new ConcurrentHashMap<>();
			for (String key : dbSpecMap.keySet()) {
				List<ReqGoodsSkuSpec> reqGoodsSkuSpecs = updateSpecMap.get(key);
				if (CollUtil.isNotEmpty(reqGoodsSkuSpecs)) {
					ReqGoodsSkuSpec reqGoodsSkuSpec = reqGoodsSkuSpecs.get(0);
					if (CollUtil.isEmpty(reqGoodsSkuSpec.getValues())) {
						//删除整个一级分类key
						String specFirstKey = reqGoodsSkuSpec.getKey();
						GoodsDonSku sku = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class)
								.eq(GoodsDonSku::getGoodsId, goodsId)
								.like(GoodsDonSku::getSpecJson, specFirstKey).last("limit 1"));
						if (sku != null) {
							throw BusinessRuntimeException.getInstance("删除总规格分类,存在使用该总规格分类的规格");
						}
					} else {
						Map<Integer, List<ReqGoodsSkuSpec.Node>> updateSecondMap = reqGoodsSkuSpec.getValues().stream().filter(node -> node.getId() != null).collect(Collectors.groupingBy(ReqGoodsSkuSpec.Node::getId));
						ReqGoodsSkuSpec dbReqGoodsSkuSpec = dbSpecMap.get(key).get(0);
						for (ReqGoodsSkuSpec.Node dbSecondValue : dbReqGoodsSkuSpec.getValues()) {
							if (updateSecondMap.get(dbSecondValue.getId()) == null) {
								GoodsDonSku sku = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class)
										.eq(GoodsDonSku::getGoodsId, goodsId)
										.apply("JSON_CONTAINS(spec_ids,'" + dbSecondValue.getId() + "')").last("limit 1"));
								if (sku != null) {
									throw BusinessRuntimeException.getInstance("删除总规格分类,存在使用该总规格分类的规格");
								}
							}
							dbNodeMap.put(dbSecondValue.getId(), dbSecondValue);
						}
					}
				}
				//去除总规格分类时
				//校验是否已引用该属性规格
				if (CollUtil.isEmpty(reqGoodsSkuSpecs)) {
					ReqGoodsSkuSpec dbReqGoodsSkuSpec = dbSpecMap.get(key).get(0);
					//删除整个一级分类key
					String specFirstKey = dbReqGoodsSkuSpec.getKey();
					GoodsDonSku sku = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class)
							.eq(GoodsDonSku::getGoodsId, goodsId)
							.like(GoodsDonSku::getSpecJson, specFirstKey).last("limit 1"));
					if (sku != null) {
						throw BusinessRuntimeException.getInstance("删除总规格分类,存在使用该总规格分类的规格");
					}
				}
			}
			return dbNodeMap;
		}
		return null;
	}

	/**
	 * 更新二级分类标题价格等 同步库中sku
	 */
	public void syncSpecNodeSku(Long goodsId, Map<Integer, ReqGoodsSkuSpec.Node> dbNodeMap, ReqGoodsSkuSpec.Node e, String lang) {
		if (CollUtil.isNotEmpty(dbNodeMap)) {
			ReqGoodsSkuSpec.Node dbNode = dbNodeMap.get(e.getId());
			if (dbNode == null) {
				return;
			}
			AtomicBoolean isUpdateTitle = new AtomicBoolean(false);
			AtomicBoolean isUpdatePrice = new AtomicBoolean(false);
			AtomicBoolean isUpdateBenefits = new AtomicBoolean(false);
			if (!StrUtil.equals(dbNode.getValue(), e.getValue())) {
				isUpdateTitle.set(true);
			}
			if (e.getPrice() == null) {
				e.setPrice(BigDecimal.ZERO);
			}
			if (dbNode.getPrice() != null && e.getPrice().compareTo(dbNode.getPrice()) != 0) {
				isUpdatePrice.set(true);
			}
			if (!StrUtil.equals(dbNode.getBenefitsList(), e.getBenefitsList())) {
				isUpdateBenefits.set(true);
			}
			if (isUpdateTitle.get() || isUpdatePrice.get() || isUpdateBenefits.get()) {
				List<GoodsDonSku> goodsDonSkus = goodsDonSkuMapper.selectList(Wrappers.lambdaQuery(GoodsDonSku.class)
						.eq(GoodsDonSku::getGoodsId, goodsId));

				goodsDonSkus.forEach(sku -> {
					try {
						List<Integer> specIdsList = Jsons.parseList(sku.getSpecIds(), Integer.class);
						if (specIdsList.contains(dbNode.getId())) {
							if (isUpdateTitle.get()) {
								sku.setSpecJson(StrUtil.replace(sku.getSpecJson(), dbNode.getValue(), e.getValue()));
								sku.setSpecVal(StrUtil.replace(sku.getSpecVal(), dbNode.getValue(), e.getValue()));
							}
							if (isUpdatePrice.get()) {
								if (specIdsList.size() == 1) {
									sku.setPrice(e.getPrice());
								} else {
									sku.setPrice(sku.getPrice().subtract(dbNode.getPrice()).add(e.getPrice()));
								}
							}
							if (isUpdateBenefits.get()) {
								if (StrUtil.isEmpty(e.getBenefitsList())) {
									sku.setBenefitsList(StrUtil.EMPTY);
								} else {
									try {
										sku.setBenefitsList(e.getBenefitsList());
									} catch (Exception exception) {
									}
								}
							}
							if (StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
								goodsDonSkuMapper.updateById(sku);
							}
						}
					} catch (Exception exception) {
					}
				});
			}
		}
	}

	//多语言设置sku
	public List<GoodsDonSku> resetSkuSpec(List<GoodsDonSku> skus, GoodsDonSpec loveSpec) throws Exception {
		StringBuilder builder = new StringBuilder();
		List<ReqGoodsSpecSingle> specList = null;
		JavaType type = Jsons.javaType().constructMapType(HashMap.class, Integer.class, ReqGoodsSpecSingle.class);
		Map<Integer, ReqGoodsSpecSingle> map = Jsons.parseObject(loveSpec.getSpecMapping(), type);
		int specNumber = loveSpec.getSpecNumber();
		List<GoodsDonSku> reSkuList = new ArrayList<>();
		GoodsDonSku reSku = null;
		for (GoodsDonSku sku : skus) {
			final String specIds = sku.getSpecIds();
			if (StringUtils.isBlank(specIds)) {
				throw new RuntimeException("请选择商品的规格.");
			}
			int[] ids = Jsons.parseObject(specIds, int[].class);

			// init
			builder.delete(0, builder.length());
			if (null == specList) {
				specList = new ArrayList<>(specNumber);
			} else {
				specList.clear();
			}
			for (int id : ids) {
				ReqGoodsSpecSingle single = map.get(id);
				if (null == single) {
					throw new RuntimeException("总规格属性id中 不存在 sku中的id.");
				}
				builder.append(single.getName()).append(';');
				specList.add(single);
			}
			reSku = new GoodsDonSku();
			String specVal = builder.toString();
			String specJson = Jsons.toJson(specList);
			reSku.setId(sku.getId());
			reSku.setSpecVal(specVal);
			reSku.setSpecJson(specJson);
			reSkuList.add(reSku);
		}
		return reSkuList;
	}
}
