package com.hzs.retail.sale.controller.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hzs.common.core.constant.*;
import com.hzs.common.core.domain.R;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.enums.retail.ERetailWaresPrice;
import com.hzs.common.core.exception.ServiceException;
import com.hzs.common.core.service.RedisService;
import com.hzs.common.core.utils.*;
import com.hzs.common.domain.member.account.CuMemberAccount;
import com.hzs.common.domain.member.base.CuMember;
import com.hzs.common.domain.member.ext.CuMemberAccountExt;
import com.hzs.common.domain.sale.ext.BdWaresDetailExt;
import com.hzs.common.domain.sale.ext.SaOrderExt;
import com.hzs.common.domain.sale.ext.SaOrderWaresLimitExt;
import com.hzs.common.domain.sale.order.*;
import com.hzs.common.domain.sale.wares.BdWaresRange;
import com.hzs.common.domain.system.base.BdStorehouse;
import com.hzs.common.domain.system.config.BdGrade;
import com.hzs.common.security.utils.SecurityUtils;
import com.hzs.member.account.IMemberAccountServiceApi;
import com.hzs.member.base.IMemberServiceApi;
import com.hzs.retail.sale.controller.service.IRetailOrderPostageService;
import com.hzs.retail.sale.controller.service.IRetailOrderService;
import com.hzs.retail.sale.param.RetailOrderOtherParam;
import com.hzs.retail.sale.param.RetailOrderParam;
import com.hzs.retail.sale.param.RetailOrderRegisterParam;
import com.hzs.retail.sale.param.RetailOrderUpgradeParam;
import com.hzs.sale.order.param.OrderItemsParam;
import com.hzs.sale.order.param.WaresNumberParam;
import com.hzs.sale.order.service.*;
import com.hzs.sale.order.service.impl.SaOrderHandle;
import com.hzs.sale.wares.service.IBdWaresDetailService;
import com.hzs.sale.wares.service.IBdWaresExtendService;
import com.hzs.sale.wares.service.IBdWaresRangeService;
import com.hzs.system.base.ICurrencyServiceApi;
import com.hzs.system.base.dto.CurrencyDTO;
import com.hzs.system.config.IGradeServiceApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 新零售订单服务
 */
@Slf4j
@Service
public class RetailOrderServiceImpl implements IRetailOrderService {

    @Autowired
    private SaOrderHandle saOrderHandle;
    @Autowired
    private ISaOrderService iSaOrderService;
    @Autowired
    private ISaOrderItemsService iSaOrderItemsService;
    @Autowired
    private ISaOrderWaresService iSaOrderWaresService;
    @Autowired
    private IBdWaresExtendService iBdWaresExtendService;
    @Autowired
    private IBdWaresDetailService iBdWaresDetailService;
    @Autowired
    private IBdWaresRangeService iBdWaresRangeService;
    @Autowired
    private IRetailOrderPostageService iRetailOrderPostageService;
    @Autowired
    private ISaOrderTempService iSaOrderTempService;
    @Autowired
    private ISaOrderWaresLimitService iSaOrderWaresLimitService;

    @Autowired
    private RedisService redisService;

    @DubboReference
    IGradeServiceApi iGradeServiceApi;
    @DubboReference
    ICurrencyServiceApi iCurrencyServiceApi;
    @DubboReference
    IMemberServiceApi iMemberServiceApi;
    @DubboReference
    IMemberAccountServiceApi iMemberAccountServiceApi;


    @Override
    public String confirmRegOrder(RetailOrderRegisterParam registerParam, List<BdGrade> gradeList) {
        // 新会员
        CuMember newMember = new CuMember();
        newMember.setMemberName(registerParam.getMemberName());
        newMember.setPhone(registerParam.getPhone());
        // 封装订单信息
        SaOrderExt saOrderExt = this.createSaOrder(registerParam, gradeList, newMember);

        // 订单缓存（60分钟有效，防止在线支付回调慢）
        redisService.setCacheObject(CacheConstants.RETAIL_TEMP_ORDER + registerParam.getPkCreator() + registerParam.getOrderCode(), saOrderExt, CacheConstants.RETAIL_ORDER_EXPIRE_TIME * 2, TimeUnit.MINUTES);
        registerParam.setPkGrade(newMember.getPkSettleGrade());
        registerParam.setPkAwards(newMember.getPkAwards());
        // 缓存订单参数（30分钟有效）
        redisService.setCacheObject(CacheConstants.RETAIL_TEMP_REG_PARAM + registerParam.getPkCreator() + registerParam.getOrderCode(), registerParam, CacheConstants.RETAIL_ORDER_EXPIRE_TIME * 2, TimeUnit.MINUTES);

        // 保存订单时间信息
        this.saveOrderTemp(registerParam.getPkCreator(), registerParam.getOrderCode(), JSONUtil.toJsonStr(saOrderExt), JSONUtil.toJsonStr(registerParam));

        return null;
    }

    @Override
    public String confirmUpgOrder(RetailOrderUpgradeParam upgradeParam) {
        // 升级会员
        CuMember upgradeMember = upgradeParam.getUpgradeMember();
        // 封装订单信息
        SaOrderExt saOrderExt = this.createSaOrder(upgradeParam, null, upgradeMember);

        // 订单缓存（60分钟有效，防止在线支付回调慢）
        redisService.setCacheObject(CacheConstants.RETAIL_TEMP_ORDER + upgradeParam.getPkCreator() + upgradeParam.getOrderCode(), saOrderExt, CacheConstants.RETAIL_ORDER_EXPIRE_TIME * 2, TimeUnit.MINUTES);
        upgradeParam.setPkGrade(upgradeMember.getPkSettleGrade());
        // 缓存订单参数（30分钟有效）
        redisService.setCacheObject(CacheConstants.RETAIL_TEMP_UPG_PARAM + upgradeParam.getPkCreator() + upgradeParam.getOrderCode(), upgradeParam, CacheConstants.RETAIL_ORDER_EXPIRE_TIME * 2, TimeUnit.MINUTES);

        // 保存订单时间信息
        this.saveOrderTemp(upgradeParam.getPkCreator(), upgradeParam.getOrderCode(), JSONUtil.toJsonStr(saOrderExt), JSONUtil.toJsonStr(upgradeParam));

        return null;
    }

    @Override
    public String confirmOtherOrder(RetailOrderOtherParam orderParam) {
        // 购买会员
        CuMember buyMember = orderParam.getBuyMember();
        // 封装订单信息
        SaOrderExt saOrderExt = this.createSaOrder(orderParam, null, buyMember);

        // 订单缓存（60分钟有效，防止在线支付回调慢）
        redisService.setCacheObject(CacheConstants.RETAIL_TEMP_ORDER + orderParam.getPkCreator() + orderParam.getOrderCode(), saOrderExt, CacheConstants.RETAIL_ORDER_EXPIRE_TIME * 2, TimeUnit.MINUTES);
        // 缓存订单参数（30分钟有效）
        redisService.setCacheObject(CacheConstants.RETAIL_TEMP_OTHER_PARAM + orderParam.getPkCreator() + orderParam.getOrderCode(), orderParam, CacheConstants.RETAIL_ORDER_EXPIRE_TIME * 2, TimeUnit.MINUTES);

        // 保存订单时间信息
        this.saveOrderTemp(orderParam.getPkCreator(), orderParam.getOrderCode(), JSONUtil.toJsonStr(saOrderExt), JSONUtil.toJsonStr(orderParam));

        return null;
    }

    @Override
    public SaOrderExt createSaOrder(RetailOrderParam orderParam, List<BdGrade> gradeList, CuMember cuMember) {
        // 需要计算等级，以及商品价格
        if (CollectionUtil.isEmpty(gradeList)) {
            gradeList = iGradeServiceApi.getRetailGradeList().getData();
        }

        // 封装订单
        SaOrderExt saOrderExt = this.packageSaOrder(orderParam, cuMember);
        if (null != cuMember) {
            saOrderExt.setMemberCode(cuMember.getMemberCode());
            saOrderExt.setMemberName(cuMember.getMemberName());
            saOrderExt.setMemberPhone(cuMember.getPhone());
        } else {
            saOrderExt.setMemberName(orderParam.getMemberName());
            saOrderExt.setMemberPhone(orderParam.getPhone());
        }
        orderParam.setOrderCode(saOrderExt.getOrderCode());

        // 获取汇率
        CurrencyDTO currency = iCurrencyServiceApi.getCurrency(orderParam.getPkCountry()).getData();
        // 封装订单明细
        List<SaOrderItems> orderItemsList = this.createSaOrderItems(orderParam, gradeList, cuMember, saOrderExt, currency);

        // 订单金额
        BigDecimal orderAmount = BigDecimal.ZERO;
        // 订单业绩
        BigDecimal orderAchieve = BigDecimal.ZERO;
        // 订单考核业绩
        BigDecimal orderAssAchieve = BigDecimal.ZERO;

        for (SaOrderItems orderItems : orderItemsList) {
            if (EYesNo.NO.getIntValue() == orderItems.getIsGift()) {
                // 不是赠品
                orderAmount = ComputeUtil.computeAddMultiply(orderAmount, orderItems.getPrice(), orderItems.getQuantity());
                orderAchieve = ComputeUtil.computeAddMultiply(orderAchieve, orderItems.getAchievement(), orderItems.getQuantity());
                orderAssAchieve = ComputeUtil.computeAddMultiply(orderAssAchieve, orderItems.getAssAchievement(), orderItems.getQuantity());
            }
        }
        saOrderExt.setOrderItemsList(orderItemsList);
        saOrderExt.setOrderAmount(orderAmount.setScale(2, RoundingMode.HALF_UP));
        saOrderExt.setOrderAchieve(orderAchieve);
        saOrderExt.setUploadAchieve(orderAchieve);
        saOrderExt.setOrderAssAchieve(orderAssAchieve);
        saOrderExt.setPkRate(currency.getPkId());
        if (null != cuMember) {
            saOrderExt.setPkGradeOld(cuMember.getPkSettleGrade());
        }

        if (ESpecialArea.RETAIL_REGISTER.getValue() == orderParam.getSpecialArea()
                || ESpecialArea.RETAIL_UPGRADE.getValue() == orderParam.getSpecialArea()) {
            // 注册、升级订单，计算会员等级
            BdGrade newGrade = iSaOrderService.calculateGrade(orderParam.getSpecialArea(), orderParam.getOrderItemsParams(), gradeList,
                    cuMember, orderParam.getSystemType(), orderParam.getIsPay());
            if (null == newGrade) {
                throw new ServiceException("会员不满足升级条件");
            }
            saOrderExt.setPkGrade(newGrade.getPkId());
            // 会员信息
            if (null != cuMember) {
                cuMember.setPkSettleGrade(newGrade.getPkId());
                if (cuMember.getPkAwards() == null) {
                    cuMember.setPkAwards(newGrade.getPkAwards());
                }
            }
        }

        return saOrderExt;
    }

    @Override
    public List<SaOrderItems> createSaOrderItems(RetailOrderParam orderParam, List<BdGrade> gradeList,
                                                 CuMember cuMember, SaOrderExt saOrderExt, CurrencyDTO currency) {
        // 需要查询盒数商品
        List<String> boxWaresList = BoxProductUtil.getBoxProductListBySystemType(null);

        // 订单明细信息
        List<SaOrderItems> orderItemsList = new ArrayList<>();
        if (null == currency) {
            currency = iCurrencyServiceApi.getCurrency(orderParam.getPkCountry()).getData();
        }

        // 商品+产品明细
        List<BdWaresDetailExt> waresDetailExtList = getWaresDetailExtList(ESpecialArea.getRetailSpecialAreaValue(orderParam.getSpecialArea()), orderParam.getOrderItemsParams(), cuMember, orderParam.getSystemType());
        // 包邮邮费
        BigDecimal freePostage = BigDecimal.ZERO;
        // 邮费模板map（key：邮费模板ID，value：邮费订单明细）
        Map<Integer, List<SaOrderItems>> postageMap = new HashMap<>(ComputeUtil.mapInitCapacity(waresDetailExtList.size()));

        // 当前盒数
        int boxNum = 0;

        // 2025.03.11 添加需求，复购专区、重消专区，指定盒数商品每用户每月限购50件
//        this.checkWaresLimit(cuMember, orderParam.getSpecialArea(), waresDetailExtList, boxWaresList, gradeList);

        // 遍历生成订单明细数据
        for (BdWaresDetailExt waresDetailExt : waresDetailExtList) {
            // 订单明细
            SaOrderItems orderItems = saOrderHandle.getSaOrderItems(cuMember, saOrderExt, currency, orderItemsList, waresDetailExt);

            // 不是赠品，需要累积包邮邮费
            if (EYesNo.NO.getIntValue() == waresDetailExt.getIsGift()) {
                // 包邮金额
                freePostage = freePostage.add(orderItems.getPrice().multiply(new BigDecimal(orderItems.getQuantity())));
                if (EYesNo.NO.getIntValue() == waresDetailExt.getIsFreeMail()) {
                    // 不包邮，处理邮费模板map
                    saOrderHandle.setPostageTmpMap(orderParam.getTranType(), postageMap, waresDetailExt, orderItems);
                }

                if (boxWaresList.contains(waresDetailExt.getWaresCode())) {
                    // 商品是盒数商品，需要累计数量
                    boxNum += orderItems.getWaresQuantity();
                }
            }
        }

        // 计算订单邮费
        String postageStr = iRetailOrderPostageService.calculatePostage(freePostage, postageMap, orderParam);
        if (null != postageStr) {
            throw new ServiceException(postageStr);
        }
        if (null != saOrderExt) {
            // 订单邮费
            saOrderExt.setPostage(orderParam.getPostage());
            // 订单指定商品盒数
            saOrderExt.setBoxNum(boxNum);
        }
        return orderItemsList;
    }

    /**
     * 获取商品及产品详情
     *
     * @param specialArea      所属专区
     * @param orderItemsParams 订单参数列表
     * @param cuMember         订单会员（复购使用）
     * @param systemTyype      系统类型
     * @return
     */
    private List<BdWaresDetailExt> getWaresDetailExtList(Integer specialArea, List<OrderItemsParam> orderItemsParams, CuMember cuMember, Integer systemTyype) {
        // 商品编号 + sku列表找到所有的商品信息
        List<BdWaresDetailExt> bdWaresDetailExtList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(orderItemsParams)) {
            List<BdWaresDetailExt> waresDetailExtList = iBdWaresDetailService.queryWaresDetailByCondition(specialArea, ETransportType.LAND.getValue(), orderItemsParams, systemTyype);
            // 复购处理极差
            setWaresRange(specialArea, waresDetailExtList, cuMember);
            if (waresDetailExtList.size() > 0) {
                bdWaresDetailExtList.addAll(waresDetailExtList);
            }
        }
        return bdWaresDetailExtList;
    }


    /**
     * 设置商品的极差
     *
     * @param specialArea        所属专区
     * @param waresDetailExtList 商品明细
     * @param cuMember           订单会员
     */
    private void setWaresRange(Integer specialArea, List<BdWaresDetailExt> waresDetailExtList, CuMember cuMember) {
        // 复购专区，处理极差
        if (EOrderType.RETAIL_REPURCHASE.getValue() == specialArea
                || EOrderType.RETAIL_CONSUME.getValue() == specialArea) {
            // 2024.12.30 添加需求，复消也需要处理级差
            Map<String, List<BdWaresDetailExt>> waresDetailExtMap = new HashMap<>();
            List<Integer> specsSkuList = new ArrayList<>();
            waresDetailExtList.forEach(waresDetailExt -> {
                String key = waresDetailExt.getPkId().toString() + waresDetailExt.getPkWaresSpecsSku();
                if (waresDetailExtMap.containsKey(key)) {
                    waresDetailExtMap.get(key).add(waresDetailExt);
                } else {
                    List<BdWaresDetailExt> tmpWaresDetailExtList = new ArrayList<>();
                    tmpWaresDetailExtList.add(waresDetailExt);
                    waresDetailExtMap.put(key, tmpWaresDetailExtList);
                }
                specsSkuList.add(waresDetailExt.getPkWaresSpecsSku());
            });
            int level = cuMember.getPkSettleGrade();
            int rangeType = ERangeType.GRADE.getValue();
            if (specsSkuList.size() == 0) {
                return;
            }
            List<BdWaresRange> bdWaresRangeList = iBdWaresRangeService.querySkuWaresRangeByCondition(cuMember.getPkSettleCountry(), rangeType, level, specsSkuList);
            bdWaresRangeList.forEach(bdWaresRange -> {
                String key = bdWaresRange.getPkWaresDetail().toString() + bdWaresRange.getPkWaresSpecsSku();
                if (waresDetailExtMap.containsKey(key)) {
                    for (BdWaresDetailExt bdWaresDetailExt : waresDetailExtMap.get(key)) {
                        bdWaresDetailExt.setPrice(bdWaresRange.getPrice());
                        bdWaresDetailExt.setAchieve(bdWaresRange.getAchieve());
                        bdWaresDetailExt.setAssAchieve(bdWaresRange.getAssAchieve());
                    }
                }
            });
        }
    }

    /**
     * 根据购买盒数，返回商品价格
     *
     * @param boxNum    盒数
     * @param gradeList 等级列表（倒序排序）
     * @return
     */
    private BigDecimal getWaresPrice(int boxNum, List<BdGrade> gradeList) {
        // 去掉升级条件带有累计盒数的（V4,V5）并且升级购买合数小于等于订单商品盒数的，再进行等级值倒序排序
        gradeList = gradeList.stream().filter(tmpGrade -> tmpGrade.getBoxTotal() == 0 && tmpGrade.getBoxNumber() <= boxNum).sorted(Comparator.comparingInt(BdGrade::getGradeValue).reversed()).collect(Collectors.toList());

        for (BdGrade bdGrade : gradeList) {
            if (boxNum > bdGrade.getBoxNumber()) {
                // 盒数大于等于购买盒数
                return ERetailWaresPrice.getEnumByValue(bdGrade.getGradeValue()).getPrice();
            }
        }
        return ERetailWaresPrice.V0.getPrice();
    }

    /**
     * 封装订单信息
     *
     * @param orderParam 订单入参
     * @return
     */
    private SaOrderExt packageSaOrder(RetailOrderParam orderParam, CuMember cuMember) {
        SaOrderExt saOrderExt = new SaOrderExt();
        if (StringUtils.isNotEmpty(orderParam.getOrderCode())) {
            saOrderExt.setOrderCode(orderParam.getOrderCode());
        } else {
            saOrderExt.setOrderCode(saOrderHandle.createOrderCode(EOrderPrefix.ORDER_CODE.getValue()));
        }
        saOrderExt.setOrderAmount(BigDecimal.ZERO);
        saOrderExt.setOrderAchieve(BigDecimal.ZERO);
        saOrderExt.setOrderAssAchieve(BigDecimal.ZERO);
        saOrderExt.setPkMember(cuMember.getPkId());
        saOrderExt.setOrderType(orderParam.getSpecialArea());
        saOrderExt.setPkReference(null != cuMember.getPkParent() ? cuMember.getPkParent() : orderParam.getPkParent());
        saOrderExt.setRecName(orderParam.getRecName());
        saOrderExt.setRecPhone(orderParam.getRecPhone());
        saOrderExt.setRecProvince(orderParam.getRecProvince());
        saOrderExt.setRecCity(orderParam.getRecCity());
        saOrderExt.setRecCounty(orderParam.getRecCounty());
        saOrderExt.setRecAddress(orderParam.getRecAddress());
        if (orderParam.getRecProvince() != null) {
            // 根据收货省获取仓库
            BdStorehouse bdStorehouse = iCurrencyServiceApi.queryBdStorehouseByProvince(orderParam.getRecProvince()).getData();
            if (bdStorehouse != null) {
                saOrderExt.setPkStorehouse(bdStorehouse.getPkId());
            }
        }
        saOrderExt.setRemark(orderParam.getRemark());
        saOrderExt.setTranType(orderParam.getTranType());
        saOrderExt.setDeliveryWay(EDelivery.EMPTY.getValue() != orderParam.getDeliveryWay() ? orderParam.getDeliveryWay() : EDelivery.FAST_MAIL.getValue());
        saOrderExt.setOrderStatus(EOrderStatus.WAIT_PAY.getValue());
        saOrderExt.setPkCreator(orderParam.getPkCreator());
        saOrderExt.setPkCountry(orderParam.getPkCountry());
        saOrderExt.setPkVertex(cuMember.getPkVertex());
        saOrderExt.setCreationTime(new Date());
        saOrderExt.setSystemType(orderParam.getSystemType());
        return saOrderExt;
    }

    @Override
    public CuMemberAccountExt getMemberAccount(Long pkMember) {
        CuMemberAccount memberAccount = new CuMemberAccount();
        memberAccount.setPkMember(pkMember);
        memberAccount.setPkCountry(CountryConstants.CHINA_COUNTRY);
        List<CuMemberAccountExt> list = iMemberAccountServiceApi.queryMemberAccountByCondition(memberAccount).getData();
        if (CollectionUtil.isNotEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public R<CuMemberAccountExt> validMemberAccount(Long pkMember, String payPwd) {
        CuMemberAccountExt cuMemberAccountExt = this.getMemberAccount(SecurityUtils.getUserId());
        if (null == cuMemberAccountExt) {
            return R.fail("会员账户异常，请联系客服处理");
        }
        // 验证密码
        if (!SecurityUtils.matchesPassword(payPwd, cuMemberAccountExt.getPayPwd())) {
            return R.fail("支付密码输入错误，请重新输入");
        }
        // 验证账户状态、钱包状态
        if (cuMemberAccountExt.getAccountStatus() != EAccountStatus.NORMAL.getValue()) {
            return R.fail("会员账户存在异常，请及时联系客服");
        }
        return R.ok(cuMemberAccountExt);
    }

    @Override
    public CuMember packageCuMember(RetailOrderParam orderParam) {
        String email = null;
        if (Validator.isEmail(orderParam.getPhone())) {
            // 邮箱
            email = orderParam.getPhone();
        }

        // 获取新的订单编号
        CuMember cuMember = CuMember.builder()
                .memberName(orderParam.getMemberName())
                .nickName(orderParam.getMemberName())
                .phone(orderParam.getPhone())
                .pkSettleCountry(CountryConstants.CHINA_COUNTRY)
                .loginPwd(SecurityUtils.encryptPassword(SysConstants.LOGIN_PASSWORD))
                .loginPassword(SysConstants.LOGIN_PASSWORD)
                .payPwd(SecurityUtils.encryptPassword(SysConstants.PAY_PASSWORD))
                .payPassword(SysConstants.PAY_PASSWORD)
                .source(orderParam.getSource() == null ? EDataSource.H5.getValue() : orderParam.getSource())
                .pkParent(orderParam.getPkParent())
                .accountStatus(EAccountStatus.NORMAL.getValue())
                .pkCenterCode(orderParam.getPkCreator())
                // 这个时候是待支付，等支付的时候变为支付，可以跟待支付公用
                .payStatus(EPayStatus.UNPAID.getValue())
                .category(ECategory.NORMAL.getValue())
                .orderSource(EOrderSource.SOLID.getValue())
                .consumeMoney(BigDecimal.ZERO)
                .consumeAchieve(BigDecimal.ZERO)
                .registerAuthority(ERegistrationAuthority.ORDINARY.getValue())
                .email(email)
                .build();
        cuMember.setCustomerType(ECustomerType.NORMAL.getValue());
        cuMember.setPkCountry(orderParam.getPkCountry());
        cuMember.setCreationTime(new Date());
        cuMember.setPkCreator(orderParam.getPkCreator());

        if (null == orderParam.getCreatorMember()) {
            orderParam.setCreatorMember(iMemberServiceApi.getRetailMember(orderParam.getPkCreator(), null).getData());
        }
        cuMember.setPkVertex(orderParam.getCreatorMember().getPkVertex());
        cuMember.setPkTeamCode(orderParam.getCreatorMember().getPkTeamCode());
        // 系统类型使用购买人的
        cuMember.setSystemType(orderParam.getCreatorMember().getSystemType());

        // 获取会员编号、会员主键
        cuMember = iMemberServiceApi.createRetailMemberIdAndCode(cuMember).getData();

        return cuMember;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String payRegOrder(SaOrderExt saOrderExt, CuMember newMember, CuMemberAccountExt memberAccountExt) {
        // 保存订单以及明细
        this.saveOrder(saOrderExt);

        newMember.setPkRegisterGrade(newMember.getPkSettleGrade());
        newMember.setCreationTime(new Date());
        newMember.setPkCreator(saOrderExt.getPkCreator());
        newMember.setConsumeMoney(saOrderExt.getOrderAmount());
        newMember.setConsumeAchieve(saOrderExt.getOrderAchieve());
        // 有效期按20年来处理，休止期按21年
        newMember.setExpireDate(DateUtils.beforeMonthLastDate(DateUtils.addYears(newMember.getCreationTime(), 20)));
        newMember.setStopDate(DateUtils.addMonths(newMember.getExpireDate(), 12));

        // 处理会员激活
        this.handleMemberActivate(newMember, saOrderExt);
        // 保存会员信息，扣减账户等
        // 调用其他服务保存会员信息、会员注册信息
        R<?> saveResult = iMemberServiceApi.saveRetailMember(newMember, saOrderExt, memberAccountExt);
        if (!saveResult.isSuccess()) {
            log.error("新零售 payRegSaOrder 会员注册失败，{}", saveResult.getMsg());
            throw new RuntimeException("会员注册失败");
        }

        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String payUpgOrder(SaOrderExt saOrderExt, CuMember updateGradeMember, CuMemberAccountExt memberAccountExt) {
        // 保存订单以及明细
        this.saveOrder(saOrderExt);

        updateGradeMember.setModifiedTime(new Date());
        updateGradeMember.setPkModified(saOrderExt.getPkCreator());

        // 处理会员激活
        this.handleMemberActivate(updateGradeMember, saOrderExt);
        // 更新会员信息，扣减账户等
        // 调用其他服务保存会员信息、会员升级信息
        R<?> saveResult = iMemberServiceApi.updateRetailMember(updateGradeMember, saOrderExt, memberAccountExt);
        if (!saveResult.isSuccess()) {
            log.error("新零售 payUpgOrder 会员升级失败，{}", saveResult.getMsg());
            throw new RuntimeException("会员升级失败");
        }

        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String payOtherOrder(SaOrderExt saOrderExt, CuMember buyMember, CuMemberAccountExt memberAccountExt) {
        // 保存订单以及明细
        this.saveOrder(saOrderExt);

        // 处理会员激活
        Boolean activateFlag = this.handleMemberActivate(buyMember, saOrderExt);
        // 扣减账户等
        // 调用其他服务保存更新会员账户等
        R<?> saveResult = iMemberServiceApi.otherRetailMember(buyMember, saOrderExt, memberAccountExt, activateFlag);
        if (!saveResult.isSuccess()) {
            log.error("新零售 payOtherOrder 会员其它订单失败，{}", saveResult.getMsg());
            throw new RuntimeException("下单支付失败");
        }

        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String onlinePaymentCallBack(Long pkMember, String orderCode) {
        String resultStr;

        // 获取缓存订单
        SaOrderExt saOrderExt = redisService.getCacheObject(CacheConstants.RETAIL_TEMP_ORDER + pkMember + orderCode);
        if (null == saOrderExt) {
            return "在线支付订单已经不存在";
        }

        // 在线支付的订单支付方式为钱包
        saOrderExt.setPayType(EOrderPayType.ONLINE.getValue());

        if (EOrderType.RETAIL_REGISTER.getValue() == saOrderExt.getOrderType()) {
            // 注册订单
            // 获取缓存参数
            RetailOrderRegisterParam registerParam = redisService.getCacheObject(CacheConstants.RETAIL_TEMP_REG_PARAM + pkMember + orderCode);
            if (null == registerParam) {
                return "在线支付注册会员不存在";
            }
            // 封装会员信息
            CuMember newMember = this.packageCuMember(registerParam);
            newMember.setPkSettleGrade(registerParam.getPkGrade());
            newMember.setPkAwards(registerParam.getPkAwards());

            saOrderExt.setPkMember(newMember.getPkId());
            saOrderExt.setRegionProvince(registerParam.getRegionProvince());
            saOrderExt.setRegionCity(registerParam.getRegionCity());
            saOrderExt.setRegionCounty(registerParam.getRegionCounty());

            resultStr = this.payRegOrder(saOrderExt, newMember, null);
        } else {
            // 其它订单
            // 查询购买会员
            CuMember cuMember = iMemberServiceApi.getRetailMember(pkMember, null).getData();
            if (null == cuMember) {
                return "会员信息不存在";
            }
            if (EOrderType.RETAIL_UPGRADE.getValue() == saOrderExt.getOrderType()) {
                // 获取缓存参数
                RetailOrderUpgradeParam upgradeParam = redisService.getCacheObject(CacheConstants.RETAIL_TEMP_UPG_PARAM + pkMember + orderCode);
                if (null == upgradeParam) {
                    return "在线支付升级会员不存在";
                }

                // 升级订单
                cuMember.setPkSettleGrade(saOrderExt.getPkGrade());

                saOrderExt.setRegionProvince(upgradeParam.getRegionProvince());
                saOrderExt.setRegionCity(upgradeParam.getRegionCity());
                saOrderExt.setRegionCounty(upgradeParam.getRegionCounty());

                resultStr = this.payUpgOrder(saOrderExt, cuMember, null);
            } else {
                // 其它订单
                resultStr = this.payOtherOrder(saOrderExt, cuMember, null);
            }
        }
        if (null == resultStr) {
            iSaOrderTempService.remove(Wrappers.<SaOrderTemp>lambdaQuery()
                    .eq(SaOrderTemp::getPkMember, pkMember)
                    .eq(SaOrderTemp::getOrderCode, orderCode)
            );
        }
        return resultStr;
    }

    /**
     * 保存订单以及明细
     *
     * @param saOrderExt 订单信息
     */
    private void saveOrder(SaOrderExt saOrderExt) {
        saOrderExt.setPayTime(new Date());
        saOrderExt.setOrderStatus(EOrderStatus.PAY.getValue());
        iSaOrderService.save(saOrderExt);

        // 订单商品拆分数据
        List<SaOrderWares> orderWaresList = new ArrayList<>();
        // 订单商品map（key：商品主键-商品价格，value：商品数量）
        Map<String, Integer> orderWaresMap = new HashMap<>();
        // 商品销量数据
        List<WaresNumberParam> waresNumberList = new ArrayList<>();
        // 商品销量map（key：商品主键，value：商品数量）
        Map<Integer, Integer> waresNumberMap = new HashMap<>();
        // 商品限购列表
        List<SaOrderWaresLimit> waresLimitList = new ArrayList<>();
        // 商品限购map（key：商品主键，value：商品数量）
        Map<Integer, Integer> waresLimitMap = new HashMap<>();

        // 盒数商品
        List<String> boxWaresList = BoxProductUtil.getBoxProductListBySystemType(saOrderExt.getSystemType());

        for (SaOrderItems saOrderItems : saOrderExt.getOrderItemsList()) {
            saOrderItems.setPkOrder(saOrderExt.getPkId());
            saOrderItems.setOrderStatus(EOrderStatus.PAY.getValue());
            saOrderItems.setPkCreator(saOrderExt.getPkCreator());
            saOrderItems.setCreationTime(saOrderExt.getCreationTime());

            // 指定商品拆分 并且 非赠品
            if (boxWaresList.contains(saOrderItems.getWareCode())
                    && EYesNo.NO.getIntValue() == saOrderItems.getIsGift()) {
                // key: 商品ID-商品价格（产品价格*产品数量）
                String key = saOrderItems.getPkWares() + "-" + (saOrderItems.getPrice().multiply(new BigDecimal(saOrderItems.getQuantity())));
                orderWaresMap.merge(key, saOrderItems.getWaresQuantity(), Integer::sum);

                waresLimitMap.merge(saOrderItems.getPkWares(), saOrderItems.getWaresQuantity(), Integer::sum);
            }
            // 商品销量累计
            waresNumberMap.merge(saOrderItems.getPkWares(), saOrderItems.getWaresQuantity(), Integer::sum);
        }
        iSaOrderItemsService.saveBatch(saOrderExt.getOrderItemsList());

        if (orderWaresMap.size() > 0) {
            // 处理订单商品拆分数据
            for (String key : orderWaresMap.keySet()) {
                SaOrderWares saOrderWares = SaOrderWares.builder()
                        .pkOrder(saOrderExt.getPkId())
                        .pkWares(Integer.parseInt(key.split("-")[0]))
                        .waresPrice(new BigDecimal(key.split("-")[1]))
                        .waresQuantity(orderWaresMap.get(key))
                        .build();
                saOrderWares.setPkCreator(saOrderExt.getPkCreator());
                saOrderWares.setCreationTime(saOrderExt.getCreationTime());
                orderWaresList.add(saOrderWares);
            }
        }
        if (waresNumberMap.size() > 0) {
            // 处理订单商品销量、会员商品限购
            for (Integer key : waresNumberMap.keySet()) {
                waresNumberList.add(WaresNumberParam.builder()
                        .pkWares(key)
                        .number(waresNumberMap.get(key))
                        .build());
            }
        }
        if (ESpecialArea.RETAIL_REPURCHASE.getValue() == saOrderExt.getOrderType()
                || ESpecialArea.RETAIL_RESCISSION.getValue() == saOrderExt.getOrderType()) {
            if (waresLimitMap.size() > 0) {
                String limitDate = DateUtils.parseDateToFormat(DateUtils.YYYYMM, new Date());
                for (Integer key : waresLimitMap.keySet()) {
                    SaOrderWaresLimit saOrderWaresLimit = SaOrderWaresLimit.builder()
                            .pkMember(saOrderExt.getPkMember())
                            .orderType(saOrderExt.getOrderType())
                            .pkWares(key)
                            .waresQuantity(waresLimitMap.get(key))
                            .limitDate(limitDate)
                            .build();
                    saOrderWaresLimit.setPkCreator(saOrderExt.getPkCreator());
                    saOrderWaresLimit.setCreationTime(saOrderExt.getCreationTime());
                    saOrderWaresLimit.setPkCountry(saOrderExt.getPkCountry());
                    waresLimitList.add(saOrderWaresLimit);
                }
            }
        }

        if (orderWaresList.size() > 0) {
            // 订单商品拆分表
            iSaOrderWaresService.saveBatch(orderWaresList);
        }
        if (waresNumberList.size() > 0) {
            // 更新商品销量表
            iBdWaresExtendService.updateWaresSalesAccrual(waresNumberList);
        }
        if (waresLimitList.size() > 0) {
            // 更新会员商品限购
            iSaOrderWaresLimitService.saveBatchLimit(waresLimitList);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long savePickOrder(SaOrder saOrder, List<SaOrderItems> saOrderItemsList) {
        // 保存订单
        iSaOrderService.save(saOrder);

        for (SaOrderItems saOrderItems : saOrderItemsList) {
            saOrderItems.setPkOrder(saOrder.getPkId());
        }
        iSaOrderItemsService.saveBatch(saOrderItemsList);

        return saOrder.getPkId();
    }

    /**
     * 保存订单临时信息
     *
     * @param pkCreator 会员ID
     * @param orderCode 订单编号
     * @param tempOrder 订单信息
     * @param tempParam 参数信息
     */
    private void saveOrderTemp(Long pkCreator, String orderCode, String tempOrder, String tempParam) {
        try {
            iSaOrderTempService.save(SaOrderTemp.builder()
                    .pkMember(pkCreator)
                    .orderCode(orderCode)
                    .tempOrder(tempOrder)
                    .tempParam(tempParam)
                    .build());
        } catch (Exception e) {
            log.error("保存订单临时信息失败");
        }
    }

    /**
     * 处理会员激活
     *
     * @param cuMember
     * @param saOrder
     * @return
     */
    private Boolean handleMemberActivate(CuMember cuMember, SaOrderExt saOrder) {
        if ((null == cuMember.getIsActivate() || EYesNo.YES.getIntValue() != cuMember.getIsActivate())
                && (EOrderType.RETAIL_REGISTER.getValue() == saOrder.getOrderType() || EOrderType.RETAIL_UPGRADE.getValue() == saOrder.getOrderType())
        ) {
            // 会员激活状态为空 或 未激活，并且是 注册、升级 订单，判断会员是否激活
            if (saOrder.getBoxNum() > 0) {
                // 存在指定盒数商品
                cuMember.setIsActivate(EYesNo.YES.getIntValue());
                if (EPayStatus.UNPAID.getValue() == cuMember.getPayStatus()) {
                    cuMember.setPayTime(saOrder.getPayTime());
                    cuMember.setPayStatus(EPayStatus.PAID.getValue());
                }
                return true;
            }
        }
        return false;
    }

    /**
     * 2025.03.11 添加需求，复购专区、重消专区，指定盒数商品每用户每月限购50件
     *
     * @param cuMember           会员
     * @param specialArea        所属专区
     * @param waresDetailExtList 购买商品列表
     * @param boxWaresList       盒数商品列表
     * @param gradeList          等级列表
     * @return
     */
    private void checkWaresLimit(CuMember cuMember, Integer specialArea, List<BdWaresDetailExt> waresDetailExtList, List<String> boxWaresList, List<BdGrade> gradeList) {
        if (null == gradeList) {
            return;
        }
        String limitDate = DateUtils.parseDateToFormat(DateUtils.YYYYMM, new Date());
        // 商品数量map（key: 商品编号，value: 商品数量）
        Map<String, Integer> waresNumMap = new HashMap<>();
        // 商品信息map（key: 商品编号，value: 商品名称）
        Map<String, String> waresNameMap = new HashMap<>();
        for (BdWaresDetailExt waresDetailExt : waresDetailExtList) {
            if ((ESpecialArea.RETAIL_REPURCHASE.getValue() == specialArea)
                    && boxWaresList.contains(waresDetailExt.getWaresCode())
                    && EYesNo.NO.getIntValue() == waresDetailExt.getIsGift()
            ) {
                // 2025.03.11 添加需求，复购专区、重消专区，指定盒数商品每月每人限购50件（赠品排除）
                waresNumMap.merge(waresDetailExt.getWaresCode(), waresDetailExt.getWaresQuantity(), Integer::sum);
                waresNameMap.put(waresDetailExt.getWaresCode(), waresDetailExt.getWaresName());
            }
        }

        if (!waresNumMap.isEmpty()) {
            // 根据会员等级进行限购处理
            BdGrade bdGrade = gradeList.stream().filter(tmpGrade -> tmpGrade.getPkId().equals(cuMember.getPkSettleGrade())).findFirst().get();

            // 会员、VIP、合伙人，每月限购1套
            Integer limitNum = RetailConstants.V1_LIMIT;

            if (EGrade.VIP.getValue() == bdGrade.getGradeValue()
                    || EGrade.S_VIP.getValue() == bdGrade.getGradeValue()) {
                // 会员、VIP、合伙人，每月限购10套
                limitNum = RetailConstants.V4_LIMIT;
            } else if (EGrade.BRANCH_COMPANY.getValue() == bdGrade.getGradeValue()) {
                // 分公司，每月限购25套
                limitNum = RetailConstants.V6_LIMIT;
            } else if (EGrade.COMPANY.getValue() == bdGrade.getGradeValue()) {
                // 总公司，不限购给一个很大的值
                limitNum = RetailConstants.V7_LIMIT;
            }

            for (String key : waresNumMap.keySet()) {
                if (waresNumMap.get(key) > limitNum) {
                    throw new ServiceException("商品【" + waresNameMap.get(key) + "】每月限购 " + limitNum + " 件");
                }
            }

            List<SaOrderWaresLimitExt> limitList = iSaOrderWaresLimitService.listWaresList(cuMember.getPkId(), specialArea, limitDate, new ArrayList<>(waresNumMap.keySet()));
            if (CollectionUtil.isNotEmpty(limitList)) {
                for (SaOrderWaresLimitExt waresLimitExt : limitList) {
                    Integer waresNum = waresNumMap.get(waresLimitExt.getWaresCode());
                    if (null != waresNum
                            && waresNum + waresLimitExt.getWaresQuantity() > limitNum) {
                        throw new ServiceException("商品【" + waresLimitExt.getWaresName() + "】每月限购 " + limitNum + " 件");
                    }
                }
            }
        }
    }

}
