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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.tmerclub.cloud.api.auth.constant.SysTypeEnum;
import com.tmerclub.cloud.api.feign.SearchOrderFeignClient;
import com.tmerclub.cloud.api.feign.SearchOrderRefundFeignClient;
import com.tmerclub.cloud.api.multishop.bo.EsShopDetailBO;
import com.tmerclub.cloud.api.multishop.bo.OrderChangeShopWalletAmountBO;
import com.tmerclub.cloud.api.multishop.feign.ShopDetailFeignClient;
import com.tmerclub.cloud.api.multishop.feign.ShopRefundAddrFeignClient;
import com.tmerclub.cloud.api.multishop.vo.ShopDetailVO;
import com.tmerclub.cloud.api.multishop.vo.ShopRefundAddrVO;
import com.tmerclub.cloud.api.order.bo.EsOrderRefundBO;
import com.tmerclub.cloud.api.order.constant.BuyerReasonType;
import com.tmerclub.cloud.api.order.constant.OrderStatus;
import com.tmerclub.cloud.api.order.constant.PurchaseOrderWaitStatus;
import com.tmerclub.cloud.api.order.vo.AccountOrderDetailVO;
import com.tmerclub.cloud.api.order.vo.OrderRefundProdEffectRespVO;
import com.tmerclub.cloud.api.order.vo.OrderRefundSimpleVO;
import com.tmerclub.cloud.api.order.vo.PageShopAccountOrderVO;
import com.tmerclub.cloud.api.payment.constant.PaySysType;
import com.tmerclub.cloud.api.seckill.dto.SecKillRefundDTO;
import com.tmerclub.cloud.api.seckill.feign.SeckillFeignClient;
import com.tmerclub.cloud.api.supplier.bo.SupplierDetailBO;
import com.tmerclub.cloud.api.supplier.feign.SupplierDetailFeignClient;
import com.tmerclub.cloud.api.supplier.feign.SupplierRefundAddrFeignClient;
import com.tmerclub.cloud.api.supplier.vo.SupplierApiRefundAddrVO;
import com.tmerclub.cloud.api.user.feign.UserFeignClient;
import com.tmerclub.cloud.api.user.vo.UserApiVO;
import com.tmerclub.cloud.api.vo.EsPageVO;
import com.tmerclub.cloud.common.cache.constant.OrderCacheNames;
import com.tmerclub.cloud.common.cache.util.RedisUtil;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.constant.SendTypeEnum;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.database.util.PageUtil;
import com.tmerclub.cloud.common.database.vo.PageVO;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.i18n.LanguageEnum;
import com.tmerclub.cloud.common.leaf.manager.SegmentManager;
import com.tmerclub.cloud.common.order.bo.PayRefundBO;
import com.tmerclub.cloud.common.order.bo.RefundNotifyBO;
import com.tmerclub.cloud.common.order.bo.RefundReductionStockBO;
import com.tmerclub.cloud.common.order.bo.RefundStockOperateBO;
import com.tmerclub.cloud.common.order.constant.*;
import com.tmerclub.cloud.common.order.dto.OrderRefundSearchDTO;
import com.tmerclub.cloud.common.order.util.OrderLangUtil;
import com.tmerclub.cloud.common.order.vo.*;
import com.tmerclub.cloud.common.product.constant.PreSaleType;
import com.tmerclub.cloud.common.product.constant.SpuMold;
import com.tmerclub.cloud.common.product.constant.SupplierDeliveryType;
import com.tmerclub.cloud.common.response.ResponseEnum;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.rocketmq.config.RocketMqConstant;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.common.util.PriceUtil;
import com.tmerclub.cloud.constant.DistributedIdKey;
import com.tmerclub.cloud.order.bo.mongo.MongoOrderRefundBO;
import com.tmerclub.cloud.order.bo.mongo.MongoOrderRefundItemBO;
import com.tmerclub.cloud.order.constant.*;
import com.tmerclub.cloud.order.constant.*;
import com.tmerclub.cloud.order.dto.OrderRefundInterventionDTO;
import com.tmerclub.cloud.order.dto.multishop.OrderRefundDTO;
import com.tmerclub.cloud.order.manager.MongoOrderRefundManager;
import com.tmerclub.cloud.order.mapper.OrderRefundInterventionMapper;
import com.tmerclub.cloud.order.mapper.OrderRefundMapper;
import com.tmerclub.cloud.order.mapper.OrderRefundSettlementMapper;
import com.tmerclub.cloud.order.model.*;
import com.tmerclub.cloud.order.service.*;
import com.tmerclub.cloud.order.model.*;
import com.tmerclub.cloud.order.service.*;
import com.tmerclub.cloud.order.vo.OrderRefundInterventionVO;
import com.tmerclub.cloud.order.vo.OrderRefundVO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单退款记录信息
 *
 * @author tmerclub
 * @date 2020-12-05 14:13:50
 */
@Service
public class OrderRefundServiceImpl implements OrderRefundService {

    private static final Logger logger = LoggerFactory.getLogger(OrderRefundServiceImpl.class);

    @Autowired
    private OrderRefundMapper orderRefundMapper;
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderItemService orderItemService;
    @Autowired
    private OrderRefundAddrService orderRefundAddrService;
    @Autowired
    private OrderRefundSettlementMapper orderRefundSettlementMapper;
    @Autowired
    private RocketMQTemplate orderRefundSuccessServiceTemplate;
    @Autowired
    private RocketMQTemplate orderRefundSuccessSettlementTemplate;
    @Autowired
    private RocketMQTemplate orderSettlementShopByAllinpayTemplate;
    @Autowired
    private RocketMQTemplate refundSuccessNotifySupplierTemplate;
    @Autowired
    private RocketMQTemplate orderRefundSuccessStockTemplate;
    @Autowired
    private RocketMQTemplate sendNotifyToShopTemplate;
    @Autowired
    private RocketMQTemplate sendNotifyToUserTemplate;
    @Autowired
    private RocketMQTemplate seckillOrderRefundMqTemplate;
    @Autowired
    private RocketMQTemplate orderRefundTemplate;
    @Autowired
    private OrderSettlementService orderSettlementService;
    @Autowired
    private SegmentManager segmentManager;
    @Autowired
    private MongoOrderRefundManager mongoOrderRefundManager;
    @Autowired
    private OrderVirtualInfoService orderVirtualInfoService;
    @Autowired
    private RocketMQTemplate orderRefundPaymentTemplate;
    @Autowired
    private OrderRefundInterventionMapper orderRefundInterventionMapper;
    @DubboReference
    private UserFeignClient userFeignClient;
    @DubboReference
    private SeckillFeignClient seckillFeignClient;
    @DubboReference
    private ShopDetailFeignClient shopDetailFeignClient;
    @DubboReference
    private SearchOrderFeignClient searchOrderFeignClient;
    @DubboReference
    private ShopRefundAddrFeignClient shopRefundAddrFeignClient;
    @DubboReference
    private SupplierRefundAddrFeignClient supplierRefundAddrFeignClient;
    @DubboReference
    private SearchOrderRefundFeignClient searchOrderRefundFeignClient;
    @DubboReference
    private SupplierDetailFeignClient supplierDetailFeignClient;


    @Override
    public EsPageVO<EsOrderRefundVO> page(PageDTO pageDTO, OrderRefundSearchDTO orderRefundPage) {
        orderRefundPage.setPageNum(pageDTO.getPageNum());
        orderRefundPage.setPageSize(pageDTO.getPageSize());
        // 替换成es的分页查询
        ServerResponseEntity<EsPageVO<EsOrderRefundVO>> orderRefundResponseEntity = searchOrderRefundFeignClient.pageOrderRefund(orderRefundPage);
        if (!orderRefundResponseEntity.isSuccess()) {
            logger.error("查询订单退款记录信息失败，失败原因：{}", orderRefundResponseEntity.getMsg());
            throw new LuckException(orderRefundResponseEntity.getMsg());
        }
        for (EsOrderRefundVO esOrderVO : orderRefundResponseEntity.getData().getList()) {
            Map<Long, List<EsOrderRefundItemVO>> comboMap = esOrderVO.getOrderItems().stream()
                    .filter(order -> Objects.equals(order.getActivityType(), OrderActivityType.COMBO_PROD.value()))
                    .collect(Collectors.groupingBy(EsOrderRefundItemVO::getActivityId));
            if (MapUtil.isEmpty(comboMap)) {
                continue;
            }
            Iterator<EsOrderRefundItemVO> iterator = esOrderVO.getOrderItems().iterator();
            while (iterator.hasNext()) {
                EsOrderRefundItemVO orderItem = iterator.next();
                if (Objects.equals(orderItem.getActivityType(), OrderActivityType.COMBO_PROD.value())) {
                    iterator.remove();
                }
                orderItem.setComboList(comboMap.get(orderItem.getOrderItemId()));
            }
        }
        return orderRefundResponseEntity.getData();
    }

    @Override
    public OrderRefundVO getByRefundId(Long refundId) {
        return orderRefundMapper.getByRefundId(refundId);
    }

    @Override
    public OrderRefundVO getDetailByRefundId(Long refundId) {
        OrderRefundVO orderRefundVO = orderRefundMapper.getByRefundId(refundId);
        List<OrderRefundVO> processingOrderRefunds = orderRefundMapper.getProcessingOrderRefundByOrderId(orderRefundVO.getOrderId());
        // 如果是整单退款,判断一下能否进行平台介入,如果有其他正在进行的就不能进行
        if(Objects.equals(orderRefundVO.getRefundType(), RefundType.ALL.value())){
            orderRefundVO.setCanApplyRefund(CollectionUtil.isEmpty(processingOrderRefunds));
        }else {
            List<OrderRefundVO> filterOrderRefunds = processingOrderRefunds.stream().filter(orderRefund -> Objects.equals(orderRefund.getOrderItemId(), 0L) || Objects.equals(orderRefund.getOrderItemId(), orderRefundVO.getOrderItemId())).toList();
            orderRefundVO.setCanApplyRefund(CollectionUtil.isEmpty(filterOrderRefunds));
        }
        // 获取订单数据
        Order order = orderService.getOrderAndOrderItemData(orderRefundVO.getOrderId(), orderRefundVO.getShopId());
        orderRefundVO.setPayTime(order.getPayTime());
        orderRefundVO.setActualTotal(order.getActualTotal());
        orderRefundVO.setOrderStatus(order.getStatus());
        orderRefundVO.setRefundStatus(order.getRefundStatus());
        orderRefundVO.setShopName(order.getShopName());
        orderRefundVO.setOrderScore(order.getOrderScore());
        orderRefundVO.setOrderItems(new ArrayList<>(0));
        orderRefundVO.setPayType(order.getPayType());
        orderRefundVO.setPlatformFreeFreightAmount(order.getPlatformFreeFreightAmount());
        orderRefundVO.setPaySysType(order.getPaySysType());
        for (OrderItem orderItem : order.getOrderItems()) {
            RefundOrderItemVO refundOrderItemVO = BeanUtil.map(orderItem, RefundOrderItemVO.class);
            refundOrderItemVO.setRefundScore(orderItem.getUseScore());
            if (Objects.isNull(refundOrderItemVO.getRefundScore())) {
                refundOrderItemVO.setRefundScore(0L);
            }
            orderRefundVO.getOrderItems().add(refundOrderItemVO);
        }

        orderRefundVO.setBuyerReasonValue(BuyerReasonType.instance(orderRefundVO.getBuyerReason()).getCn());
        List<RefundOrderItemVO> orderItems = orderRefundVO.getOrderItems();
        getRefundTypeByOrderItem(orderRefundVO, orderRefundVO.getRefundType());
        // 不是整单退款
        if (!Objects.equals(orderRefundVO.getRefundType(), RefundType.ALL.value())) {
            orderItems.removeIf(next -> !Objects.equals(orderRefundVO.getOrderItemId(), next.getOrderItemId()));
            logger.info("不是整单退款，退款订单项信息：{}", orderItems);
        }
        OrderLangUtil.orderRefundVOList(orderRefundVO.getOrderItems());
        // 如果有平台介入信息，添加一下介入信息
        handleIntervention(orderRefundVO);
        return orderRefundVO;
    }

    @Override
    public void save(OrderRefund orderRefund) {
        Long userId = AuthUserContext.get().getUserId();
        orderRefund.setRefundId(segmentManager.getSegmentIdWithDateTime(DistributedIdKey.tmerclub_REFUND, userId));
        orderRefundMapper.save(orderRefund);
    }

    @Override
    public void update(OrderRefund orderRefund) {
        orderRefundMapper.update(orderRefund);
    }

    @Override
    public void deleteById(Long refundId) {
        orderRefundMapper.deleteById(refundId);
    }

    @Override
    public boolean checkRefundDate(Order order) {
        // 判断是否超过支持的退款天数
        if (Objects.equals(order.getStatus(), OrderStatus.SUCCESS.value())) {
            long finallyTime = order.getFinallyTime().getTime();
            long currentTime = System.currentTimeMillis();
            int miniTime = Constant.MAX_FINALLY_REFUND_TIME * 24 * 60 * 60 * 1000;
            return currentTime - finallyTime <= miniTime;
        }
        return true;
    }

    @Override
    public List<OrderRefund> getProcessOrderRefundByOrderId(Long orderId) {
        return orderRefundMapper.getProcessOrderRefundByOrderId(orderId);
    }

    /**
     * 生成退款单
     *
     * @param orderRefund 退款对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void applyRefund(OrderRefund orderRefund) {
        // 生成退款单
        save(orderRefund);
        // 更新订单状态
        Order order = new Order();
        order.setOrderId(orderRefund.getOrderId());
        order.setRefundStatus(RefundStatusEnum.APPLY.value());
        orderService.update(order);

        // 更新订单项状态
        if (Objects.equals(RefundType.ALL.value(), orderRefund.getRefundType())) {
            orderItemService.updateRefundStatusByOrderId(order.getOrderId(), RefundStatusEnum.APPLY.value());
            logger.info("整单退款，更新订单项状态为申请退款，订单id：{}", order.getOrderId());
        } else {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderItemId(orderRefund.getOrderItemId());
            orderItem.setRefundStatus(RefundStatusEnum.APPLY.value());
            orderItem.setFinalRefundId(orderRefund.getRefundId());
            orderItemService.update(orderItem);
            logger.info("部分退款，更新订单项状态为申请退款，订单项id：{}", orderItem.getOrderItemId());
        }
        //如果是赠品，需要处理关联赠品订单项
        List<OrderItemVO> giveawayOrderItems = orderItemService.getOrderItemByGiveawayOrderItemId(orderRefund.getUserId(), orderRefund.getOrderItemId());
        if (giveawayOrderItems.size() != 0) {
            logger.info("赠品退款，关联赠品订单项,更新订单项状态为申请退款，订单项id：{}", orderRefund.getOrderItemId());
            List<OrderItem> list = new ArrayList<>(Constant.INITIAL_CAPACITY);
            for (OrderItemVO orderItemVO : giveawayOrderItems) {
                OrderItem orderItems = BeanUtil.map(orderItemVO, OrderItem.class);
                orderItems.setRefundStatus(RefundStatusEnum.APPLY.value());
                list.add(orderItems);
            }
            orderItemService.updateBatch(list);
        }

        // TODO -y 改为mysql查询
        // 消息推送-申请退款
        SendNotifyBO notifyBO = getSendNotifyBO(orderRefund.getOrderId());
        notifyBO.setPrice(PriceUtil.toDecimalPrice(orderRefund.getRefundAmount()).toString());
        notifyBO.setSendType(SendTypeEnum.LAUNCH_REFUND.getValue());
        notifyBO.setBizId(orderRefund.getOrderId());
        notifyBO.setRemark(orderRefund.getBuyerDesc());
        notifyBO.setRejectMessage(BuyerReasonType.instance(orderRefund.getBuyerReason()).getCn());
        SendStatus sendBizStatus = sendNotifyToShopTemplate.syncSend(RocketMqConstant.SEND_NOTIFY_TO_SHOP_TOPIC, new GenericMessage<>(notifyBO)).getSendStatus();
    }

    private SendNotifyBO getSendNotifyBO(Long orderId) {
        List<SendNotifyBO> sendNotifyList = orderService.listSimpleSendNotifyBO(Collections.singletonList(orderId));
        if (CollUtil.isEmpty(sendNotifyList)) {
            return new SendNotifyBO();
        }
        return sendNotifyList.get(0);
    }


    /**
     * 买家提交物流信息
     *
     * @param orderRefund     退款单对象
     * @param orderRefundAddr 退款物流单对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitExpress(OrderRefund orderRefund, OrderRefundAddr orderRefundAddr) {
        orderRefundAddrService.update(orderRefundAddr);

        // 更新退款单信息
        if (!Objects.equals(ReturnProcessStatusEnum.CONSIGNMENT.value(), orderRefund.getReturnMoneySts())) {
            orderRefund.setReturnMoneySts(ReturnProcessStatusEnum.CONSIGNMENT.value());
            logger.info("买家提交物流信息，更新退款单状态为买家已发货，退款单id：{}", orderRefund.getRefundId());
        }
        orderRefund.setDeliveryTime(new Date());
        orderRefund.setUpdateTime(new Date());
        update(orderRefund);

        // 消息推送-用户已退货
        SendNotifyBO notifyBO = getSendNotifyBO(orderRefund.getOrderId());
        notifyBO.setPrice(PriceUtil.toDecimalPrice(orderRefund.getRefundAmount()).toString());
        //供应商处理的退款，给供应商发送用户退货提醒
        // 供应商处理状态， -1.商家自行处理 0.待供应商处理 1.供应商已同意 2.供应商已拒绝
        if (!Objects.equals(orderRefund.getSupplierHandleStatus(), -1)) {
            notifyBO.setShopId(null);
            notifyBO.setSupplierId(orderRefund.getSupplierId());
            notifyBO.setSendType(SendTypeEnum.RETURN_REFUND_TO_SUPPLIER.getValue());
        } else {
            notifyBO.setSendType(SendTypeEnum.RETURN_REFUND.getValue());
        }

        notifyBO.setBizId(orderRefund.getOrderId());
        notifyBO.setRemark(orderRefund.getBuyerDesc());
        notifyBO.setRejectMessage(BuyerReasonType.instance(orderRefund.getBuyerReason()).getCn());
        SendStatus sendBizStatus = sendNotifyToShopTemplate.syncSend(RocketMqConstant.SEND_NOTIFY_TO_SHOP_TOPIC, new GenericMessage<>(notifyBO)).getSendStatus();

        //notifyTemplateService.sendNotifyByUserRefundDelivery(order, SendType.RETURN_REFUND);
    }

    @Override
    public Integer countByReturnMoneyStsAndOrderId(Integer returnMoneySts, Integer returnMoneySts2, Long orderId) {
        return orderRefundMapper.countByReturnMoneyStsAndOrderId(returnMoneySts, returnMoneySts2, orderId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void agreeReturns(OrderRefundDTO orderRefundParam, OrderRefundVO orderRefundVO, Integer sysType) {
        if (Objects.isNull(orderRefundParam.getShopRefundAddrId())) {
            throw new LuckException("请设置退货物流信息");
        }
        // 同意退款退货操作
        // 设置退货物流信息
        if (Objects.equals(sysType, SysTypeEnum.SUPPLIER.value())) {
            ServerResponseEntity<SupplierApiRefundAddrVO> refundAddrResponse = supplierRefundAddrFeignClient.getSupplierRefundAddrByRefundAddrId(orderRefundParam.getShopRefundAddrId());
            if (!refundAddrResponse.isSuccess() || refundAddrResponse.getData() == null) {
                throw new LuckException("请设置退货物流信息");
            }
            SupplierApiRefundAddrVO refundAddr = refundAddrResponse.getData();
            OrderRefundAddr orderRefundAddr = new OrderRefundAddr();
            orderRefundAddr.setUserId(orderRefundVO.getUserId());
            orderRefundAddr.setShopId(orderRefundVO.getShopId());
            orderRefundAddr.setRefundId(orderRefundVO.getRefundId());
            orderRefundAddr.setConsigneeName(refundAddr.getConsignee());
            orderRefundAddr.setConsigneeMobile(refundAddr.getMobile());
            orderRefundAddr.setConsigneePostCode(refundAddr.getPostCode());
            String addr = refundAddr.getProvince() + refundAddr.getCity() + refundAddr.getArea() + refundAddr.getAddr();
            orderRefundAddr.setConsigneeAddr(addr);
            orderRefundAddrService.save(orderRefundAddr);
        } else {
            ServerResponseEntity<ShopRefundAddrVO> refundAddrResponse = shopRefundAddrFeignClient.getShopRefundAddrByRefundAddrId(orderRefundParam.getShopRefundAddrId());
            if (!refundAddrResponse.isSuccess() || refundAddrResponse.getData() == null) {
                throw new LuckException("请设置退货物流信息");
            }
            ShopRefundAddrVO refundAddr = refundAddrResponse.getData();
            OrderRefundAddr orderRefundAddr = new OrderRefundAddr();
            orderRefundAddr.setShopId(orderRefundVO.getShopId());
            orderRefundAddr.setRefundId(orderRefundVO.getRefundId());
            orderRefundAddr.setUserId(orderRefundVO.getUserId());
            orderRefundAddr.setConsigneeMobile(refundAddr.getMobile());
            orderRefundAddr.setConsigneeName(refundAddr.getConsignee());
            orderRefundAddr.setConsigneePostCode(refundAddr.getPostCode());
            String addr = refundAddr.getProvince() + refundAddr.getCity() + refundAddr.getArea() + refundAddr.getAddr();
            orderRefundAddr.setConsigneeAddr(addr);
            orderRefundAddrService.save(orderRefundAddr);
        }


        int agreeStats = orderRefundMapper.agreeReturns(orderRefundParam.getSellerMsg(), orderRefundVO.getRefundId());
        if (agreeStats == 0) {
            throw new LuckException("订单退款状态已发生改变，请勿重复操作");
        }
        // TODO 消息推送--同意退款
        List<SendNotifyBO> notifyBOList = orderService.listSendNotifyByOrderIds(Collections.singletonList(orderRefundVO.getOrderId()));
        SendNotifyBO sendNotifyBO = notifyBOList.get(0);
        sendNotifyBO.setSendType(SendTypeEnum.AGREE_REFUND.getValue());
        sendNotifyBO.setPrice(PriceUtil.toDecimalPrice(orderRefundVO.getRefundAmount()).toString());
        SendStatus sendBizStatus = sendNotifyToUserTemplate.syncSend(RocketMqConstant.SEND_NOTIFY_TO_USER_TOPIC, new GenericMessage<>(notifyBOList)).getSendStatus();
    }

    @Override
    public Boolean getIsLastRefund(Long refundId, Long shopId) {
        OrderRefundVO orderRefundVo = getDetailByRefundId(refundId);
        if (Objects.isNull(orderRefundVo)) {
            //退款单不存在
            logger.error("退款单不存在");
            throw new LuckException("退款单不存在");
        }
        if (Objects.equals(orderRefundVo.getRefundType(), RefundType.ALL.value())) {
            //整单退款
            logger.info("整单退款");
            return false;
        }
        if (Objects.equals(orderRefundVo.getApplyType(), RefundApplyType.REFUND_AND_RETURNS.value())) {
            //退货退款
            logger.info("退货退款");
            return false;
        }
        Order order = orderService.getOrderByOrderIdAndUserId(orderRefundVo.getOrderId(), orderRefundVo.getUserId());
        if (!Objects.equals(order.getStatus(), OrderStatus.PAYED.value())) {
            //非待发货
            logger.info("非待发货");
            return false;
        }
        // 如果存在分销订单，则计算分销总金额
        List<OrderItem> orderItemList = orderItemService.listOrderItemsByOrderIds(order.getOrderId());
        // 获取所有的订单项总数
        int orderItemCount = orderItemList.size();
        //退款成功总数
        // 获取所有正在进行中的退款订单
        int refundCount = countSuccessItemNum(order.getOrderId());
        return Objects.equals(refundCount, orderItemCount - 1);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void refundSuccess(RefundNotifyBO refundNotifyBO) {
        Long refundId = refundNotifyBO.getRefundId();
        OrderRefundVO orderRefundVO = orderRefundMapper.getByRefundId(refundId);
        // 已经进行过退款了
        if (Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.SUCCESS.value())) {
            return;
        }

        OrderRefund orderRefund = new OrderRefund();
        orderRefund.setRefundId(refundId);
        orderRefund.setRefundTime(new Date());
        if (Objects.equals(orderRefundVO.getSupplierHandleStatus(), SupplierHandleStatus.TRANSFER_SUPPLIER.value())) {
            orderRefund.setSupplierHandleStatus(SupplierHandleStatus.SUPPLIER_AGREE.value());
        }
        if (Objects.equals(orderRefundVO.getPlatformInterventionStatus(), PlatformInterventionStatus.AGREE.value())) {
            orderRefund.setPlatformInterventionStatus(PlatformInterventionStatus.SUCCESS.value());
            orderRefund.setInterventionFinishTime(new Date());
        }else {
            orderRefund.setReturnMoneySts(ReturnProcessStatusEnum.SUCCESS.value());
        }
        // 更新退款状态
        orderRefundMapper.update(orderRefund);
        // 更新结算单状态
        int updateStatus = orderRefundSettlementMapper.updateToSuccessByRefundId(refundId);
        if (updateStatus < 1) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }

        Order dbOrder = orderService.getByOrderId(refundNotifyBO.getOrderId());
        OrderItemVO dbOrderItem = orderItemService.getByOrderItemId(orderRefundVO.getOrderItemId());
        Order order = new Order();

        // 处理订单退款更新
        this.handleOrderRefund(refundNotifyBO, orderRefundVO, dbOrder, order,dbOrderItem);

        // 还原库存和商品销量
        this.reductionStock(orderRefundVO, dbOrder, dbOrderItem);

        boolean canRefundFlag = Objects.equals(dbOrder.getStatus(), OrderStatus.PAYED.value())
                || Objects.equals(dbOrder.getStatus(), OrderStatus.CONSIGNMENT.value())
                || Objects.equals(dbOrder.getStatus(), OrderStatus.SUCCESS.value());
        // 退款订单关闭，还原优惠券以及订单结算
        if (canRefundFlag && Objects.equals(order.getStatus(), OrderStatus.CLOSE.value())) {
            // 订单在已支付，已发货，确认收货的情况下，退款导致订单关闭
            // 需要判断下是否要进行结算给商家的操作，这个结算的计算是退款完成后结算的，所以不要随便改变顺序
            handlePartialRefund(dbOrder, orderRefundVO);
        }
        refundNotifyBO.setCanRefund(canRefundFlag);
        refundNotifyBO.setOrderStatus(order.getStatus());
        refundNotifyBO.setDbOrderStatus(dbOrder.getStatus());
        refundNotifyBO.setUserId(dbOrder.getUserId());
        refundNotifyBO.setOrderScore(dbOrder.getOrderScore());
        // 通知还原优惠券&&还原成长值&&退还积分&&添加余额退款记录
        SendStatus sendStatus = orderRefundSuccessServiceTemplate.syncSend(RocketMqConstant.ORDER_REFUND_SUCCESS_SERVICE_TOPIC, new GenericMessage<>(refundNotifyBO)).getSendStatus();
        if (!Objects.equals(sendStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }

        OrderRefundVO orderRefundDb = orderRefundMapper.getByRefundId(orderRefund.getRefundId());
        OrderSettlement orderSettlement = orderSettlementService.getByOrderId(refundNotifyBO.getOrderId());
        OrderRefundVO orderRefundVo = new OrderRefundVO();
        orderRefundVo.setRefundId(refundNotifyBO.getRefundId());
        orderRefundVo.setRefundAmount(orderRefundDb.getRefundAmount());
        orderRefundVo.setOrderId(order.getOrderId());
        orderRefundVo.setPayId(orderSettlement.getPayId());
        orderRefundVo.setPayType(orderSettlement.getPayType());
        orderRefundVo.setRefundType(RefundType.ALL.value());
        orderRefundVo.setPlatformRefundAmount(orderRefundDb.getPlatformRefundAmount());
        orderRefundVo.setShopId(orderRefundDb.getShopId());
        orderRefundVo.setPlatformRefundCommission(orderRefundDb.getPlatformRefundCommission());
        orderRefundVo.setPurPlatformRefundCommission(orderRefundDb.getPurPlatformRefundCommission());
        orderRefundVo.setPurchaseRefundAmount(orderRefundDb.getPurchaseRefundAmount());
        orderRefundVo.setWaitPurchase(dbOrder.getWaitPurchase());
        if(Objects.equals(dbOrder.getStatus(),OrderStatus.PAYED.value()) || Objects.equals(dbOrder.getStatus(),OrderStatus.WAIT_GROUP.value())) {
            orderRefundVo.setFreightAmount(dbOrder.getFreightAmount());
        }
        orderRefundVo.setUnSuccessGroupOrder(1);

        SendStatus sendStockStatus = orderRefundTemplate.syncSend(RocketMqConstant.ORDER_REFUND_TOPIC, new GenericMessage<>(orderRefundVo)).getSendStatus();
        if (!Objects.equals(sendStockStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    private void handleIntervention(OrderRefundVO orderRefundVO) {
        if(Objects.nonNull(orderRefundVO.getApplyInterventionTime())){
            orderRefundVO.setInterventionEndTime(DateUtil.offsetHour(orderRefundVO.getApplyInterventionTime(),72));
            orderRefundVO.setPlatformProcessingEndTime(DateUtil.offsetDay(orderRefundVO.getApplyInterventionTime(), 7));
        }
        List<OrderRefundInterventionVO> orderRefundInterventionList = orderRefundInterventionMapper.listByRefundId(orderRefundVO.getRefundId());
        // 处理一下名称？还是直接在保存时存入名称？还是处理名称比较好
        Map<Integer, List<OrderRefundInterventionVO>> refundInterventionMap = orderRefundInterventionList.stream().collect(Collectors.groupingBy(OrderRefundInterventionVO::getSysType));
        String userNickName = "";
        if(CollectionUtil.isNotEmpty(refundInterventionMap.get(SysTypeEnum.ORDINARY.value()))) {
            ServerResponseEntity<UserApiVO> userData = userFeignClient.getUserData(refundInterventionMap.get(SysTypeEnum.ORDINARY.value()).get(0).getBizId());
            if (!userData.isSuccess()) {
                throw new LuckException(userData.getMsg());
            }
            userNickName = Objects.isNull(userData.getData()) ? "用户已注销" : userData.getData().getNickName();
        }
        String shopName = "";
        if(CollectionUtil.isNotEmpty(refundInterventionMap.get(SysTypeEnum.MULTISHOP.value()))) {
            ServerResponseEntity<EsShopDetailBO> shopResp = shopDetailFeignClient.getShopByShopId(refundInterventionMap.get(SysTypeEnum.MULTISHOP.value()).get(0).getBizId());
            if (!shopResp.isSuccess()) {
                throw new LuckException(shopResp.getMsg());
            }
            shopName = Objects.isNull(shopResp.getData()) ? "" : shopResp.getData().getShopName();
        }
        String supplierName = "";
        if(CollectionUtil.isNotEmpty(refundInterventionMap.get(SysTypeEnum.SUPPLIER.value()))) {
            ServerResponseEntity<SupplierDetailBO> suppierResp = supplierDetailFeignClient.getSupplierBySupplierId(refundInterventionMap.get(SysTypeEnum.SUPPLIER.value()).get(0).getBizId());
            if (!suppierResp.isSuccess()) {
                throw new LuckException(suppierResp.getMsg());
            }
            supplierName = Objects.isNull(suppierResp.getData()) ? "" : suppierResp.getData().getSupplierShopName();
        }
        for (OrderRefundInterventionVO  orderRefundIntervention : orderRefundInterventionList) {
            switch (orderRefundIntervention.getSysType()){
                case 0:
                    orderRefundIntervention.setBizName(userNickName);
                    break;
                case 1:
                    orderRefundIntervention.setBizName(shopName);
                    break;
                case 3:
                    orderRefundIntervention.setBizName(supplierName);
                    break;
                default:
                    break;
            }
        }
        orderRefundVO.setOrderRefundInterventionList(orderRefundInterventionList);
    }


    /**
     * 处理订单退款更新
     *
     * @param refundNotifyBO 退款通知
     * @param orderRefundVO  订单退款信息
     * @param dbOrder        订单信息
     * @param order          订单更新数据
     * @param dbOrderItem
     */
    private void handleOrderRefund(RefundNotifyBO refundNotifyBO, OrderRefundVO orderRefundVO, Order dbOrder, Order order, OrderItemVO dbOrderItem) {
        order.setOrderId(refundNotifyBO.getOrderId());
        if (Objects.equals(orderRefundVO.getRefundType(), RefundType.ALL.value())) {
            order.setStatus(OrderStatus.CLOSE.value());
        } else {
            // 查看是否已经达到了所有的订单商品数量，如是则订单关闭
            // 已退款单
            Integer refundSuccessRefundCount = orderRefundMapper.countRefundSuccessRefundCountByOrderId(refundNotifyBO.getOrderId());
            Integer itemNum = orderItemService.sumNumByOrderId(refundNotifyBO.getOrderId());
            // 整个订单完成退款的时候
            if (refundSuccessRefundCount >= itemNum) {
                order.setStatus(OrderStatus.CLOSE.value());
            } else {
                order.setRefundStatus(RefundStatusEnum.PARTIAL_SUCCESS.value());
            }

            // 判断一下如果是虚拟订单且不是无需核销，其他的订单项都是已经核销成功的情况下，那么订单也是关闭的
            int unVerifyNum = orderVirtualInfoService.countWriteOffByOrderId(refundNotifyBO.getOrderId());
            if (itemNum == (unVerifyNum + refundSuccessRefundCount)) {
                order.setStatus(OrderStatus.CLOSE.value());
            }

            // 退款成功后，订单没有关闭，且订单为待发货，减少订单待发货商品数量
            if (!Objects.equals(order.getStatus(), OrderStatus.CLOSE.value()) && Objects.equals(dbOrder.getStatus(), OrderStatus.PAYED.value())) {
                Long orderItemId = orderRefundVO.getOrderItemId();
                // 减少订单待发货商品数量
                orderItemService.reduceUnDeliveryNumByOrderItemId(orderItemId, orderRefundVO.getRefundCount());
                //
                int unDeliveryNum = orderItemService.countUnDeliveryNumByOrderId(refundNotifyBO.getOrderId());
                if (Objects.equals(unDeliveryNum, 0)) {
                    // 如果订单为快递发货情况，查询所有的订单项发货情况，如果有个是快递发货则是快递发货，否则全是无需快递则订单也为无需快递方式。
                    if (Objects.equals(dbOrder.getDeliveryType(), DeliveryType.DELIVERY.value())) {
                        List<OrderItemVO> orderItemList = orderItemService.listOrderItemAndLangByOrderId(refundNotifyBO.getOrderId());
                        int deliveryType = DeliveryType.NOT_DELIVERY.value();
                        for (OrderItemVO orderItemVO : orderItemList) {
                            if (Objects.nonNull(orderItemVO.getDeliveryType()) && Objects.equals(orderItemVO.getDeliveryType(), DeliveryType.DELIVERY.value())) {
                                deliveryType = DeliveryType.DELIVERY.value();
                                break;
                            }
                        }
                        order.setDeliveryType(deliveryType);
                    }
                    order.setStatus(OrderStatus.CONSIGNMENT.value());
                    order.setDeliveryTime(new Date());
                }
                // 如果是待采购状态，退款成功后，订单的采购金额要重新计算
                if(Objects.equals(dbOrder.getWaitPurchase(),PurchaseOrderWaitStatus.WAIT_PURCHASE.value())){
                    // 当前订单项需要补充采购的金额 = 订单实际支付金额 + 平台优惠金额 - 平台佣金 - 分销佣金 - 采购金额
                    long purchaseAmount = dbOrderItem.getActualTotal() + dbOrderItem.getPlatformShareReduce()
                            - dbOrderItem.getDistributionAmount() - dbOrderItem.getPlatformCommission() - dbOrderItem.getItemPurchaseAmount();
                    // 如果大于0则表示这个item不需要补采购金额，否则需要补采购金额
                    purchaseAmount = purchaseAmount > 0 ? 0 : Math.abs(purchaseAmount);
                    order.setPurchaseSpreadAmount(dbOrder.getPurchaseSpreadAmount() - Math.abs(purchaseAmount));
                }
            }
        }
        if (Objects.equals(order.getStatus(), OrderStatus.CLOSE.value())) {
            order.setCancelTime(new Date());
            order.setUpdateTime(new Date());
            order.setCloseType(OrderCloseType.REFUND.value());
            order.setRefundStatus(RefundStatusEnum.SUCCEED.value());
        }
        // 更新订单项状态
        if (Objects.equals(orderRefundVO.getRefundType(), RefundType.ALL.value())) {
            orderItemService.updateRefundStatusByOrderId(order.getOrderId(), RefundStatusEnum.SUCCEED.value());
        } else {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderItemId(orderRefundVO.getOrderItemId());
            // 因为我们商城目前设计为一个订单项只能进行一次退款，无法进行多次退款
            if (dbOrderItem.getCount() > orderRefundVO.getRefundCount()) {
                orderItem.setRefundStatus(RefundStatusEnum.PARTIAL_SUCCESS.value());
            } else {
                orderItem.setRefundStatus(RefundStatusEnum.SUCCEED.value());
            }
            orderItemService.update(orderItem);
        }
        orderService.update(order);
    }

    /**
     * 处理下部分退款完成，订单关闭的时候未结算变成已结算的金额处理，退款超时定时任务。
     *
     * @param order         订单信息
     * @param orderRefundVO
     */
    private void handlePartialRefund(Order order, OrderRefundVO orderRefundVO) {
//        // 待采购订单退款不需要结算
//        if (Objects.equals(order.getWaitPurchase(), PurchaseOrderWaitStatus.WAIT_PURCHASE.value())) {
//            return;
//        }
        // 1.获取到部分退款并且订单关闭后，需要结算给商家、平台的钱
        // 获取所有正在进行中的退款订单
        OrderChangeShopWalletAmountBO orderChangeShopWalletAmountBO = getPartialRefundOrderChangeShopWalletAmountBO(order, orderRefundVO);
        // 商家要结算的钱 -  实际金额 - 退款金额
        long partialRefundAmount = order.getActualTotal() - orderChangeShopWalletAmountBO.getRefundAmount();

        // 已发货的订单，如果有平台优惠的运费金额，结算时要把钱给到商家
        if (!Objects.equals(order.getStatus(), OrderStatus.PAYED.value())) {
            partialRefundAmount = partialRefundAmount + orderChangeShopWalletAmountBO.getPlatformFreeFreightAmount();
        }


        // 如果商家和供应商需要结算的钱都为0，则不需要进行结算了
        if (partialRefundAmount > 0) {
            // 2.发送消息给商家，将需要结算的钱进行结算
            SendStatus sendStatus = orderRefundSuccessSettlementTemplate.syncSend(RocketMqConstant.ORDER_REFUND_SUCCESS_SETTLEMENT_TOPIC, new GenericMessage<>(orderChangeShopWalletAmountBO)).getSendStatus();
            if (!Objects.equals(sendStatus, SendStatus.SEND_OK)) {
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
            // 因为商家结算这里也有结算供应商，所以直接return
            return;
        }


        // 非供应商订单到这一步已经结束了
        if (Objects.equals(orderChangeShopWalletAmountBO.getSupplierId(), 0L)) {
            return;
        }

        // 供应商要结算的钱
        long supplierAmount = orderChangeShopWalletAmountBO.getChangePurchaseAmount() + orderChangeShopWalletAmountBO.getFreightAmount()
                - orderChangeShopWalletAmountBO.getChangePurchasePlatformCommission();

        if (supplierAmount > 0) {
            // 供应商 添加结算金额
            SendStatus sendSupplierStatus = refundSuccessNotifySupplierTemplate.syncSend(RocketMqConstant.ORDER_REFUND_SUCCESS_SETTLEMENT_SUPPLIER_TOPIC, new GenericMessage<>(orderChangeShopWalletAmountBO)).getSendStatus();
            if (!Objects.equals(sendSupplierStatus, SendStatus.SEND_OK)) {
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
        }
    }

    private OrderChangeShopWalletAmountBO getPartialRefundOrderChangeShopWalletAmountBO(Order order, OrderRefundVO orderRefundVO) {
        List<OrderRefund> orderRefunds = getProcessOrderRefundByOrderId(order.getOrderId());
        long alreadyRefundAmount = 0L;
        long changePlatformCommission = 0L;
        long platformRefundAllowanceAmount = 0L;
        long changePurchasePlatformCommission = 0L;
        long changePurchaseRefundAmount = 0L;
        long refundPurchaseRefundAmount = 0L;
        long refundPurchasePlatformCommission = 0L;
        long supplierFreightAmount = 0L;
        List<OrderItem> orderItemList = orderItemService.listOrderItemsByOrderId(order.getOrderId());
        long purchaseAmount = orderItemList.stream().mapToLong(OrderItem::getItemPurchaseAmount).sum();
        long purchasePlatformCommission = orderItemList.stream().mapToLong(OrderItem::getPurchasePlatformCommission).sum();
        for (OrderRefund orderRefund : orderRefunds) {
            alreadyRefundAmount += orderRefund.getRefundAmount();
            changePlatformCommission += orderRefund.getPlatformRefundCommission();
            platformRefundAllowanceAmount += orderRefund.getPlatformRefundAmount();

            refundPurchaseRefundAmount += orderRefund.getPurchaseRefundAmount();
            refundPurchasePlatformCommission += orderRefund.getPurPlatformRefundCommission();
            // 需要判断下是采购前的退款，还是采购后的
            // 采购前的自行处理退款，不需要结算给供应商，采购后的自行处理退款需要结算给供应商
            // 如果是退款平台介入先判断退款平台介入,如果平台处理方式为共同承担的情况下,供应商才需要退款减少金额
            boolean checkPlatformRefundType = Objects.nonNull(orderRefund.getInterventionRefundType()) && Objects.equals(orderRefund.getInterventionRefundType(), RefundInterventionType.COMMON.value());
            if(!Objects.equals(orderRefund.getPlatformInterventionStatus(),-1) && checkPlatformRefundType){
                changePurchaseRefundAmount += orderRefund.getPurchaseRefundAmount();
                changePurchasePlatformCommission += orderRefund.getPurPlatformRefundCommission();
            }
            // 没有平台介入,那么退款供应商有处理过就共同退款,此时供应商才需要退款减少金额
            if (Objects.equals(orderRefund.getPlatformInterventionStatus(),-1) && !Objects.equals(orderRefund.getSupplierHandleStatus(), SupplierHandleStatus.NORMAL.value())) {
                changePurchaseRefundAmount += orderRefund.getPurchaseRefundAmount();
                changePurchasePlatformCommission += orderRefund.getPurPlatformRefundCommission();
            }
            if (Objects.equals(RefundType.ALL.value(), orderRefund.getRefundType())) {
                break;
            }
        }

        // 待发货的订单结算时，平台优惠金额要加上运费优惠的金额（待发货退款是要退运费的，所以这时要把平台优惠的运费也算上，下面计算改变金额时才不会重复计算运费的金额了）
        if (Objects.equals(order.getStatus(), OrderStatus.PAYED.value())) {
            platformRefundAllowanceAmount = platformRefundAllowanceAmount + order.getPlatformFreeFreightAmount();
        }

        OrderChangeShopWalletAmountBO orderChangeShopWalletAmountBO = getOrderChangeShopWalletAmountBO(order, orderRefunds,orderRefundVO, alreadyRefundAmount, changePlatformCommission, platformRefundAllowanceAmount, changePurchasePlatformCommission, changePurchaseRefundAmount, refundPurchaseRefundAmount, refundPurchasePlatformCommission, supplierFreightAmount, purchaseAmount, purchasePlatformCommission);
        // 商家要结算的钱
        long partialRefundAmount = order.getActualTotal() - alreadyRefundAmount;
        // 供应商要结算的钱
        long supplierAmount = orderChangeShopWalletAmountBO.getChangePurchaseAmount() + orderChangeShopWalletAmountBO.getFreightAmount()
                - orderChangeShopWalletAmountBO.getChangePurchasePlatformCommission();
        // 如果是通联支付，先进行通联结算，再回调进行商家结算
        boolean settlementAllinpay = partialRefundAmount > 0 || orderChangeShopWalletAmountBO.getPlatformAllowanceAmount() > 0 || supplierAmount > 0;
        if (Objects.equals(orderChangeShopWalletAmountBO.getPaySysType(), PaySysType.ALLINPAY.value()) && settlementAllinpay) {
            // 1.发送消息给通联，进行通联结算
            // 开启消息
            SendStatus sendStatus = orderSettlementShopByAllinpayTemplate.syncSend(RocketMqConstant.ORDER_SETTLED_SHOP_BY_ALLINPAY_TOPIC, new GenericMessage<>(Collections.singletonList(orderChangeShopWalletAmountBO))).getSendStatus();
            if (!Objects.equals(sendStatus, SendStatus.SEND_OK)) {
                // 消息发不出去就抛异常
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
            return orderChangeShopWalletAmountBO;
        }
        // 如果是待采购订单,退款结算时,计算一下佣金
        if(Objects.equals(order.getWaitPurchase(),1)){
            Map<Long, OrderRefund> orderRefundMap = orderRefunds.stream().collect(Collectors.toMap(OrderRefund::getOrderItemId, orderRefund -> orderRefund));
            OrderRefund orderRefund = null;
            if(orderRefundMap.containsKey(0L)) {
                orderRefund = orderRefundMap.get(0L);
            }
            List<OrderItem> orderItems = orderItemService.listOrderItemsByOrderId(order.getOrderId());
            Long settlementAmount = orderChangeShopWalletAmountBO.getActualTotal() - orderChangeShopWalletAmountBO.getRefundAmount();
            Long platformCommission = 0L;
            for (OrderItem orderItem : orderItems) {
                // 商品佣金 = (订单项实付金额 - 订单项应退金额(订单项实付金额 * 订单退款金额 / 订单实际金额)) * 佣金比例
                Long itemSettlementAmount = orderItem.getActualTotal();
                if(Objects.nonNull(orderRefund)){
                    itemSettlementAmount = orderItem.getActualTotal() - PriceUtil.divideByBankerRounding(orderItem.getActualTotal() * orderRefund.getRefundAmount(),order.getActualTotal());
                }else if(orderRefundMap.containsKey(orderItem.getOrderItemId())){
                    OrderRefund itemOrderRefund = orderRefundMap.get(orderItem.getOrderItemId());
                    itemSettlementAmount = orderItem.getActualTotal() - itemOrderRefund.getRefundAmount();
                }
                long itemPlatformCommission = PriceUtil.divideByBankerRounding((long)(itemSettlementAmount * orderItem.getRate()),100);
                platformCommission += itemPlatformCommission;
            }
            orderChangeShopWalletAmountBO.setPlatformCommission(platformCommission);
        }
        return orderChangeShopWalletAmountBO;
    }

    private static OrderChangeShopWalletAmountBO getOrderChangeShopWalletAmountBO(Order order, List<OrderRefund> orderRefunds, OrderRefundVO orderRefundVO, long alreadyRefundAmount, long changePlatformCommission, long platformRefundAllowanceAmount, long changePurchasePlatformCommission, long changePurchaseRefundAmount, long refundPurchaseRefundAmount, long refundPurchasePlatformCommission, long supplierFreightAmount, long purchaseAmount, long purchasePlatformCommission) {
        OrderChangeShopWalletAmountBO orderChangeShopWalletAmountBO = new OrderChangeShopWalletAmountBO();
        orderChangeShopWalletAmountBO.setOrderStatus(order.getStatus());
        orderChangeShopWalletAmountBO.setRefundId(orderRefundVO.getRefundId());
        orderChangeShopWalletAmountBO.setActualTotal(order.getActualTotal());
        orderChangeShopWalletAmountBO.setRefundAmount(alreadyRefundAmount);
        orderChangeShopWalletAmountBO.setPlatformFreeFreightAmount(order.getPlatformFreeFreightAmount());
        orderChangeShopWalletAmountBO.setPlatformAllowanceAmount(order.getPlatformAmount() - platformRefundAllowanceAmount);
        // 如果是待发货状态，运费要退给用户，此时供应商是不能加上运费
        if (Objects.equals(order.getStatus(), OrderStatus.PAYED.value()) && !Objects.equals(order.getSupplierId(), 0L)) {
            orderChangeShopWalletAmountBO.setFreightAmount(0L);

            // 如果是退款平台介入先判断退款平台介入,如果平台处理方式为商家承担的情况下,供应商可以收入一笔运费
            boolean checkPlatformRefundType = Objects.nonNull(orderRefundVO.getInterventionRefundType()) && Objects.equals(orderRefundVO.getInterventionRefundType(), RefundInterventionType.SHOP.value());
            if(!Objects.equals(orderRefundVO.getPlatformInterventionStatus(),-1) && checkPlatformRefundType){
                supplierFreightAmount = order.getFreightAmount() - Math.abs(order.getFreeFreightAmount());
            }
            // 没有平台介入,如果是待发货状态且为商家自行处理，则还是需要加上运费，供应商可以收入一笔运费
            if (Objects.equals(orderRefundVO.getPlatformInterventionStatus(),-1) && Objects.equals(orderRefundVO.getSupplierHandleStatus(), SupplierHandleStatus.NORMAL.value())) {
                supplierFreightAmount = order.getFreightAmount() - Math.abs(order.getFreeFreightAmount());
            }

            // 供应商发货订单的待采购订单-单项退款，如果有会员包邮，平台补贴金额中就会包含运费补贴的金额
            // 然而运费金额不需要从商家结算金额中扣除，因为平台补贴的运费金额虽然经过商家，但是最终给的是供应商，也就是说商家待结算金额中没有包含平台补贴的运费
            // 但这一步还不能直接从平台补贴金额中扣除，否则会导致结算记录中的平台补贴金额不正确（按目前逻辑，平台补贴金额是包含运费补贴金额的）
            // 因此添加一个供应商运费补贴金额，在下一步计算变化金额时再减去补贴的运费即可
            if (Objects.equals(order.getWaitPurchase(), 1) && order.getPlatformFreeFreightAmount() > 0) {
                orderChangeShopWalletAmountBO.setSupplierFreightAmount(order.getPlatformFreeFreightAmount());
            }
            refundPurchaseRefundAmount = purchaseAmount - refundPurchaseRefundAmount - orderChangeShopWalletAmountBO.getFreightAmount();
        } else {
            orderChangeShopWalletAmountBO.setFreightAmount(order.getFreightAmount() - Math.abs(order.getFreeFreightAmount()));
            refundPurchaseRefundAmount = purchaseAmount - refundPurchaseRefundAmount + orderChangeShopWalletAmountBO.getFreightAmount();
        }
        orderChangeShopWalletAmountBO.setOrderId(order.getOrderId());
        orderChangeShopWalletAmountBO.setPaySysType(order.getPaySysType());
        orderChangeShopWalletAmountBO.setShopId(order.getShopId());
        orderChangeShopWalletAmountBO.setPlatformCommission(order.getPlatformCommission());
        orderChangeShopWalletAmountBO.setChangePlatformCommission(changePlatformCommission);
        orderChangeShopWalletAmountBO.setDistributionAmount(order.getDistributionAmount());
        // 供应商金额
        orderChangeShopWalletAmountBO.setSupplierId(order.getSupplierId());
        orderChangeShopWalletAmountBO.setWaitPurchase(order.getWaitPurchase());
        // 商家自行处理金额 + 运费
        orderChangeShopWalletAmountBO.setRefundPurchaseAmount(refundPurchaseRefundAmount);
        orderChangeShopWalletAmountBO.setChangePurchaseAmount(purchaseAmount + supplierFreightAmount - changePurchaseRefundAmount);
        orderChangeShopWalletAmountBO.setChangePurchasePlatformCommission(purchasePlatformCommission - changePurchasePlatformCommission);
        orderChangeShopWalletAmountBO.setRefundPurchasePlatformCommission(purchasePlatformCommission - refundPurchasePlatformCommission);
        return orderChangeShopWalletAmountBO;
    }

    private void reductionStock(OrderRefundVO orderRefundVO, Order dbOrder, OrderItemVO dbOrderItem) {
        boolean shouldReturnStock = Objects.equals(dbOrder.getStatus(), OrderStatus.PAYED.value()) || Objects.equals(dbOrder.getStatus(), OrderStatus.WAIT_GROUP.value()) || (dbOrder.getOrderMold() != null && dbOrder.getOrderMold() == 1);
        if (!shouldReturnStock) {
            return;
        }
        // 是否为秒杀订单
        boolean isSecKillOrder = Objects.equals(dbOrder.getOrderType(), OrderType.SECKILL.value());
        // 订单待发货或待成团订单超时，结果就被取消了以及虚拟商品订单，还原库存
        List<RefundReductionStockBO> refundReductionStocks;
        List<OrderItemVO> orderItems = orderItemService.listOrderItemAndLangByOrderId(orderRefundVO.getOrderId());
        // 整单退款
        if (Objects.equals(orderRefundVO.getRefundType(), RefundType.ALL.value())) {
            // 组装退款数据列表
            refundReductionStocks = this.loadRefundReductionStockList(orderItems, orderRefundVO, dbOrder);
        }
        // 单项退款
        else {
            // 单个退单时，获取商品是否有赠品订单项，如果有，一并退还
            List<Long> orderItemIds = new ArrayList<>();
            orderItemIds.add(dbOrderItem.getOrderItemId());
            Object result = RedisUtil.get(OrderCacheNames.REFUND_GIVEAWAY_ORDER_ITEM + dbOrderItem.getOrderItemId());
            if(Objects.nonNull(result)){
                List<Long> giveawayOrderItemList = JSONArray.parseArray(result.toString(), Long.class);
                orderItemIds.addAll(giveawayOrderItemList);
            }
            List<OrderItemVO> orderItemList = orderItemService.listOrderItemAndLangByOrderItemIds(orderItemIds);
            List<OrderItemVO> childComboOrderItems = orderItems.stream().filter(orderItemVO -> Objects.equals(orderItemVO.getActivityType(), OrderActivityType.COMBO_PROD.value()) && Objects.equals(orderItemVO.getActivityId(), dbOrderItem.getOrderItemId())).toList();
            if(CollectionUtil.isNotEmpty(childComboOrderItems)) {
                orderItemList.addAll(childComboOrderItems);
            }
            // 组装退款数据列表
            refundReductionStocks = this.loadRefundReductionStockList(orderItemList, orderRefundVO, dbOrder);
        }
        if (CollUtil.isEmpty(refundReductionStocks)) {
            return;
        }


        // 通知还原库存
        SendStatus sendStatus;
        // 秒杀订单统一走秒杀库存，跟秒杀活动是否关闭没有关系
        if (isSecKillOrder) {
            Long activityId = refundReductionStocks.get(0).getActivityId();
            SecKillRefundDTO secKillRefundDTO = new SecKillRefundDTO(activityId, refundReductionStocks,dbOrder.getUserId());
            sendStatus = seckillOrderRefundMqTemplate.syncSend(RocketMqConstant.SECKILL_ORDER_REFUND_TOPIC, new GenericMessage<>(secKillRefundDTO))
                    .getSendStatus();
        } else {
            // 获取商品入库id
            Long id = segmentManager.getSegmentId(DistributedIdKey.tmerclub_STOCK_BILL_LOG);
            sendStatus = orderRefundSuccessStockTemplate.syncSend(RocketMqConstant.ORDER_REFUND_SUCCESS_STOCK_TOPIC, new GenericMessage<>(new RefundStockOperateBO(refundReductionStocks, id)))
                    .getSendStatus();
        }
        if (!Objects.equals(sendStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    private List<RefundReductionStockBO> loadRefundReductionStockList(List<OrderItemVO> orderItemList, OrderRefundVO orderRefundVO, Order dbOrder) {
        if (CollUtil.isEmpty(orderItemList)) {
            return Collections.emptyList();
        }
        boolean supplierDelivery = !Objects.equals(dbOrder.getOrderType(), OrderType.SECKILL.value()) && Objects.equals(dbOrder.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value());
        // 过滤掉组合商品的主商品
        orderItemList = orderItemList.stream().filter(orderItemVO -> !Objects.equals(orderItemVO.getSpuMold(),SpuMold.COMBO.value())).toList();
        List<RefundReductionStockBO> refundReductionStocks = orderItemList.stream().map(orderItem -> {
            RefundReductionStockBO refundReductionStockBO = new RefundReductionStockBO();
            refundReductionStockBO.setOrderId(orderRefundVO.getOrderId());
            refundReductionStockBO.setShopId(orderRefundVO.getShopId());
            refundReductionStockBO.setActivityId(orderItem.getActivityId());
            refundReductionStockBO.setSpuName(orderItem.getSpuName());
            refundReductionStockBO.setSkuName(orderItem.getSkuName());
            refundReductionStockBO.setSkuId(orderItem.getSkuId());
            refundReductionStockBO.setSupplierId(dbOrder.getSupplierId());
            refundReductionStockBO.setStockPointId(orderItem.getStockPointId());
            // 如果是整单退款或者是组合的子商品,修改数量为全部
            if (Objects.equals(orderRefundVO.getRefundType(), RefundType.ALL.value()) || Objects.equals(orderItem.getActivityType(),OrderActivityType.COMBO_PROD.value())) {
                refundReductionStockBO.setCount(orderItem.getCount());
            } else {
                // 单项退款可以修改退款数量，所以用实际的退款数量
                refundReductionStockBO.setCount(orderRefundVO.getRefundCount());
            }
            refundReductionStockBO.setPrice(orderItem.getPrice());
            refundReductionStockBO.setPartyCode(orderItem.getPartyCode());
            refundReductionStockBO.setPic(orderItem.getPic());
            if (supplierDelivery) {
                refundReductionStockBO.setSupplierProd(1);
                refundReductionStockBO.setSkuId(orderItem.getSupplierSkuId());
                refundReductionStockBO.setSpuId(orderItem.getSupplierSpuId());
            } else {
                refundReductionStockBO.setSkuId(orderItem.getSkuId());
                refundReductionStockBO.setSpuId(orderItem.getSpuId());
            }
            return refundReductionStockBO;
        }).collect(Collectors.toList());
        return refundReductionStocks;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelRefund(OrderRefundVO orderRefundVO) {


        // 更新退款状态为已取消
        OrderRefund orderRefund = new OrderRefund();
        orderRefund.setReturnMoneySts(ReturnProcessStatusEnum.FAIL.value());
        orderRefund.setCloseType(RefundCloseType.CANCEL.value());
        orderRefund.setCloseTime(new Date());
        orderRefund.setRefundId(orderRefundVO.getRefundId());
        orderRefund.setUserId(orderRefundVO.getUserId());
        update(orderRefund);

        closeOrderAndOrderItemRefundStatus(orderRefundVO);
    }

    /**
     * 关闭订单和订单项的退款状态
     *
     * @param orderRefundVo
     */
    private void closeOrderAndOrderItemRefundStatus(OrderRefundVO orderRefundVo) {
        Integer orderRefundSuccessCount = orderRefundMapper.countReturnProcessingItemByOrderId(orderRefundVo.getOrderId());

        // 更新订单
        // 如果有订单项退款成功，则订单状态为部分退款成功，否则为退款失败
        if (Objects.equals(orderRefundSuccessCount, 0)) {
            Order order = new Order();
            order.setOrderId(orderRefundVo.getOrderId());
            order.setRefundStatus(RefundStatusEnum.DISAGREE.value());
            orderService.update(order);
        }
        // 更新订单项状态
        if (Objects.equals(orderRefundVo.getRefundType(), RefundType.ALL.value())) {
            orderItemService.updateRefundStatusByOrderId(orderRefundVo.getOrderId(), RefundStatusEnum.DISAGREE.value());
        } else {
            // 拒绝退款
            OrderItem orderItem = new OrderItem();
            orderItem.setRefundStatus(RefundStatusEnum.DISAGREE.value());
            orderItem.setOrderItemId(orderRefundVo.getOrderItemId());
            orderItemService.update(orderItem);
        }

        //如果是赠品，需要处理关联赠品订单项
        List<OrderItemVO> giveawayOrderItems = orderItemService.getOrderItemByGiveawayOrderItemId(orderRefundVo.getUserId(), orderRefundVo.getOrderItemId());
        if (giveawayOrderItems.size() != 0) {
            List<OrderItem> list = new ArrayList<>(Constant.INITIAL_CAPACITY);
            for (OrderItemVO orderItemVO : giveawayOrderItems) {
                OrderItem orderItems = BeanUtil.map(orderItemVO, OrderItem.class);
                orderItems.setRefundStatus(RefundStatusEnum.DISAGREE.value());
                list.add(orderItems);
            }
            orderItemService.updateBatch(list);
        }


    }

    /**
     * 不同意退款
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void disagreeRefund(OrderRefundDTO orderRefundParam, OrderRefundVO orderRefundVO) {
        int agreeStats = orderRefundMapper.disagreeRefund(orderRefundParam.getSellerMsg(), orderRefundParam.getRejectMessage(), orderRefundVO.getRefundId(),
                orderRefundVO.getReturnMoneySts(), orderRefundParam.getIsReceived(), orderRefundVO.getSupplierHandleStatus(), orderRefundParam.getImgUrls());
        if (agreeStats == 0) {
            throw new LuckException("订单退款状态已发生改变，请勿重复操作");
        }
        closeOrderAndOrderItemRefundStatus(orderRefundVO);

        // 消息推送--拒绝退款
        List<SendNotifyBO> notifyBOList = orderService.listSimpleSendNotifyBO(Collections.singletonList(orderRefundVO.getOrderId()));
        SendNotifyBO sendNotifyBO = notifyBOList.get(0);
        sendNotifyBO.setSendType(SendTypeEnum.REFUSE_REFUND.getValue());
        sendNotifyBO.setRejectMessage(orderRefundParam.getRejectMessage());
        sendNotifyBO.setMobile(orderRefundVO.getBuyerMobile());
        sendNotifyBO.setPrice(PriceUtil.toDecimalPrice(orderRefundVO.getRefundAmount()).toString());
        SendStatus sendBizStatus = sendNotifyToUserTemplate.syncSend(RocketMqConstant.SEND_NOTIFY_TO_USER_TOPIC, new GenericMessage<>(notifyBOList)).getSendStatus();
        if (!Objects.equals(sendBizStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void disagreeIntervention(OrderRefundInterventionDTO orderRefundParam, OrderRefundVO orderRefundVO) {
        int agreeStats = orderRefundMapper.disagreeIntervention(orderRefundParam.getPlatformMessage(),
                orderRefundVO.getRefundId(), orderRefundVO.getPlatformInterventionStatus());
        if (agreeStats == 0) {
            throw new LuckException("订单退款状态已发生改变，请勿重复操作");
        }
        closeOrderAndOrderItemRefundStatus(orderRefundVO);
    }

    @Override
    public ServerResponseEntity<Void> agreeRefund(OrderRefundDTO orderRefundParam, OrderRefundVO orderRefundVo) {
        setOrderRefundInfo(orderRefundVo);
        // 执行退款，真正意义上的退款，需要确保
        // 发送事务消息
        TransactionSendResult transactionSendResult = orderRefundTemplate.sendMessageInTransaction(RocketMqConstant.ORDER_REFUND_TOPIC, new GenericMessage<>(orderRefundVo), orderRefundParam);

        if (!Objects.equals(transactionSendResult.getLocalTransactionState(), LocalTransactionState.COMMIT_MESSAGE)) {
            logger.error("退款事务消息发送失败，事务状态：{}", transactionSendResult.getLocalTransactionState());
            return ServerResponseEntity.fail(ResponseEnum.EXCEPTION);
        }
        return ServerResponseEntity.success();
    }

    private void setOrderRefundInfo(OrderRefundVO orderRefundVo) {
        OrderSettlement orderSettlement = orderSettlementService.getByOrderId(orderRefundVo.getOrderId());
        orderRefundVo.setPayId(orderSettlement.getPayId());
        orderRefundVo.setPayType(orderSettlement.getPayType());

        // -----最后一件运费计算-----------
        long freightAmount = 0L;
        orderRefundVo.setFreightAmount(0L);
        // 获取订单信息
        Order order = orderService.getOrderByOrderIdAndUserId(orderRefundVo.getOrderId(), orderRefundVo.getUserId());
        if (Objects.equals(order.getStatus(), OrderStatus.PAYED.value())) {
            // 如果存在分销订单，则计算分销总金额
            List<OrderItem> orderItemList = orderItemService.listOrderItemsByOrderIds(order.getOrderId());
            // 获取所有的订单项总数
            int orderItemCount = orderItemList.size();
            //退款成功总数
            // 获取所有正在进行中的退款订单
            int refundCount = countSuccessItemNum(order.getOrderId());
            //最后一单
            if (Objects.equals(refundCount, orderItemCount - 1)) {
                if (order.getFreightAmount() > 0.0 && order.getPlatformFreeFreightAmount() >= 0.0) {
                    freightAmount = order.getFreightAmount() - order.getPlatformFreeFreightAmount();
                    logger.info("最后一单运费计算：freightAmount={},platformFreeFreightAmount={}", freightAmount, order.getPlatformFreeFreightAmount());
                }
                // 单项退款，且平台减免运费---平台减免的运费要从商家钱包退还给平台，所以将运费添加到平台优惠金额中
                if (Objects.equals(orderRefundVo.getRefundType(), RefundType.SINGLE.value()) && order.getPlatformFreeFreightAmount() > 0.0) {
                    orderRefundVo.setPlatformRefundAmount(orderRefundVo.getPlatformRefundAmount() + order.getPlatformFreeFreightAmount());
                    logger.info("单项退款，且平台减免运费,平台减免的运费要从商家钱包退还给平台，所以将运费添加到平台优惠金额中：platformRefundAmount={}", orderRefundVo.getPlatformRefundAmount());
                }
            }
            // 供应商发货的订单，放进去实际的支付运费金额，用于后续的供应商金额退款
            if (Objects.equals(order.getSupplierDeliveryType(), 1) && !Objects.equals(order.getSupplierId(), 0L)) {
                orderRefundVo.setFreightAmount(freightAmount + Math.abs(order.getFreeFreightAmount()));
                logger.info("供应商发货的订单，放进去实际的支付运费金额，用于后续的供应商金额退款：freightAmount={}", orderRefundVo.getFreightAmount());
            }
        }
        // 如果是定金预售，需要注意下是两笔退款
        if (Objects.equals(order.getPreSaleType(), PreSaleType.DEPOSIT.value())) {
            orderRefundVo.setPayIds(orderSettlement.getPayIds());
            logger.info("定金预售，需要注意下是两笔退款：payIds={}", orderSettlement.getPayIds());
        }
        // 只有单个退款才需要加上运费
        if (Objects.equals(orderRefundVo.getRefundType(), RefundType.SINGLE.value())) {
            orderRefundVo.setRefundAmount(orderRefundVo.getRefundAmount() + freightAmount);
            logger.info("单个退款需要加上运费：refundAmount={}", orderRefundVo.getRefundAmount());
        }
        // 如果是通联支付，且为采购完成的，则需要在进行采购金额的退款,这里直接用后续的金额计算
        if (Objects.equals(order.getPaySysType(), PaySysType.ALLINPAY.value()) && Objects.nonNull(order.getPurchaseSpreadAmount()) && Objects.equals(order.getWaitPurchase(), PurchaseOrderWaitStatus.PURCHASED.value())) {
            Long distributionAmount;
            logger.info("通联支付，且为采购完成的，则需要在进行采购金额的退款,这里直接用后续的金额计算：purchaseSpreadAmount={}", order.getPurchaseSpreadAmount());
            if (Objects.equals(orderRefundVo.getRefundType(), RefundType.ALL.value())) {
                distributionAmount = order.getDistributionAmount();
                logger.info("整单退款，分销金额为：distributionAmount={}", distributionAmount);
            } else {
                OrderItemVO item = orderItemService.getByOrderItemId(orderRefundVo.getOrderItemId());
                distributionAmount = item.getDistributionAmount() + item.getDistributionParentAmount();
                logger.info("单项退款，分销金额为：distributionAmount={}", distributionAmount);
            }

            // 商家改变金额 = 退款金额 + 平台补贴改变量 - 平台佣金改变量 -分销金额 - 供应商金额改变量 - 运费
            // 43 + 0 - 0 - 0 - 99.5 =
            long shopRealRefundAmount = orderRefundVo.getRefundAmount() + orderRefundVo.getPlatformRefundAmount()
                    - orderRefundVo.getPlatformRefundCommission() - distributionAmount
                    - orderRefundVo.getPurchaseRefundAmount() - orderRefundVo.getFreightAmount();

            // 供应商发货订单，未发货单项退款运费处理：供应商订单的运费最终是给供应商的，商家不会得到运费的钱，按目前的业务供应商发货订单的运费可以有以下两种理解
            // 情况一：用户支付运费，运费先给到商家，然后商家将运费给供应商。按业务来说是这样的，因为用户是跟商家购买的商品，商家再到供应商去请求发货
            // 情况二：平台会员包邮，用户需要支付的运费由平台出了，所以平台需要补贴运费给商家，商家再把平台补贴的运费给供应商
            // 因为供应商发货订单的运费，最终都是给到供应商，商家只是做一个中转，所以在退款的时候，商家不需要去扣除运费的金额
            // 但情况二的平台补贴金额中包含了供应商商品运费，因此在商家的计算要扣除运费的金额，避免商家又扣了一次运费造成亏损
            if (Objects.nonNull(orderRefundVo.getSupplierFreightAmount()) && !Objects.equals(orderRefundVo.getShopId(), 0L)) {
                shopRealRefundAmount = shopRealRefundAmount - orderRefundVo.getSupplierFreightAmount();
                logger.info("供应商发货订单，未发货单项退款运费处理：shopRealRefundAmount={}", shopRealRefundAmount);
            }
            orderRefundVo.setAllinpayRefundPurchaseAmount(shopRealRefundAmount);
        }
    }


    /**
     * 移交供应商
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transferRefundOrderToSupplier(OrderRefundDTO orderRefundParam, OrderRefundVO orderRefundVo) {
        int agreeStats = orderRefundMapper.transferRefundOrderToSupplier(orderRefundVo.getSupplierHandleStatus(), orderRefundParam.getSupplierHandleStatus(),
                orderRefundVo.getRefundId(), orderRefundVo.getReturnMoneySts());
        // 退款移交供应商处理，需发送退款提醒给供应商
        SendNotifyBO notifyBO = getSendNotifyBO(orderRefundVo.getOrderId());
        notifyBO.setShopId(null);
        notifyBO.setSupplierId(orderRefundVo.getSupplierId());
        notifyBO.setPrice(PriceUtil.toDecimalPrice(orderRefundVo.getRefundAmount()).toString());
        notifyBO.setSendType(SendTypeEnum.LAUNCH_REFUND_TO_SUPPLIER.getValue());
        notifyBO.setBizId(orderRefundVo.getOrderId());
        notifyBO.setRemark(orderRefundVo.getBuyerDesc());
        notifyBO.setRejectMessage(BuyerReasonType.instance(orderRefundVo.getBuyerReason()).getCn());
        SendStatus sendBizStatus = sendNotifyToShopTemplate.syncSend(RocketMqConstant.SEND_NOTIFY_TO_SHOP_TOPIC, new GenericMessage<>(notifyBO)).getSendStatus();
        if (!Objects.equals(sendBizStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
        if (agreeStats == 0) {
            throw new LuckException("订单退款状态已发生改变，请勿重复操作");
        }
        // 若商家有进行备注，保存备注信息
        if (!ObjectUtils.isEmpty(orderRefundParam.getSellerMsg())) {
            OrderRefund orderRefund = new OrderRefund();
            orderRefund.setRefundId(orderRefundVo.getRefundId());
            orderRefund.setShopSellerMsg(orderRefundParam.getSellerMsg());
            orderRefundMapper.update(orderRefund);
        }
    }

    /**
     * 同意退款操作（生成结算记录）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int agreeRefund(OrderRefundVO orderRefundVO, OrderRefundDTO orderRefundParam) {
        Date nowDate = new Date();
        // 订单正在进行退款结算,之前已经同意过了，不需要再操作了
        if (orderRefundSettlementMapper.countByRefundId(orderRefundVO.getRefundId()) > 0) {
            return 0;
        }

        long freightAmount = checkLastRefund(orderRefundVO);
        // 生成退款结算记录
        OrderRefundSettlement orderRefundSettlement = new OrderRefundSettlement();
        orderRefundSettlement.setOrderId(orderRefundVO.getOrderId());
        orderRefundSettlement.setPayId(orderRefundVO.getPayId());
        orderRefundSettlement.setRefundId(orderRefundVO.getRefundId());
        orderRefundSettlement.setPayType(orderRefundVO.getPayType());
        orderRefundSettlement.setRefundAmount(orderRefundVO.getRefundAmount() + freightAmount);
        orderRefundSettlement.setOrderTotalAmount(orderRefundVO.getActualTotal());
        orderRefundSettlement.setUserId(orderRefundVO.getUserId());
        orderRefundSettlement.setRefundStatus(1);
        orderRefundSettlement.setCreateTime(nowDate);
        orderRefundSettlement.setUpdateTime(nowDate);
        orderRefundSettlementMapper.save(orderRefundSettlement);

        // 获取退款单信息
        OrderRefundVO orderRefundDb = orderRefundMapper.getByRefundId(orderRefundVO.getRefundId());
        // 进入这里会有两种情况 1.商家/供应商同意退款 2.平台统一用户退款
        int updateStatus = 0;
        if (Objects.equals(orderRefundVO.getPlatformInterventionStatus(),-1)) {
            // 商家同意退款
            // 如果有商家自行处理，则加上关联商家自行处理的支付id用以记录
            updateStatus = orderRefundMapper.agreeRefund(orderRefundParam.getSellerMsg(), orderRefundVO.getRefundId(), orderRefundVO.getReturnMoneySts(), orderRefundParam.getIsReceived(),
                    orderRefundDb.getApplyType(), orderRefundVO.getRefundAmount(), orderRefundVO.getPurchaseRefundAmount());
        } else {
            // 平台同意退款
            updateStatus = orderRefundMapper.platformAgreeRefund(orderRefundVO);
        }

        if (updateStatus == 0) {
            return 0;
        }
        return 1;
    }


    private long checkLastRefund(OrderRefundVO orderRefundDto) {
        if (Objects.equals(orderRefundDto.getRefundType(), RefundType.ALL.value())) {
            return 0L;
        }
        // 获取订单信息
        Order order = orderService.getOrderByOrderIdAndUserId(orderRefundDto.getOrderId(), orderRefundDto.getUserId());
        if (!Objects.equals(order.getStatus(), OrderStatus.PAYED.value())) {
            return 0L;
        }
        //所有订单项总数

        // 如果存在分销订单，则计算分销总金额
        List<OrderItem> orderItemList = orderItemService.listOrderItemsByOrderId(order.getOrderId());
        // 获取所有的订单项总数
        int orderItemCount = orderItemList.size();
        //退款成功总数
        // 获取所有正在进行中的退款订单
        int refundCount = countSuccessItemNum(order.getOrderId());
        if (Objects.equals(refundCount, orderItemCount - 1) && order.getFreightAmount() > 0.0) {
            //最后一单
            if (order.getPlatformFreeFreightAmount() == 0.0) {
                return order.getFreightAmount() - order.getPlatformFreeFreightAmount();
            }
        }
        return 0L;
    }

    @Override
    public Integer getRefundStatus(Long refundId) {
        return orderRefundMapper.getRefundStatus(refundId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createGroupUnSuccessRefundInfo(RefundNotifyBO refundNotifyBO) {
        Order dbOrder = orderService.getByOrderId(refundNotifyBO.getOrderId());
        List<OrderItem> orderItemList = orderItemService.listOrderItemsByOrderId(refundNotifyBO.getOrderId());
        // 生成退款单信息
        OrderRefund orderRefund = new OrderRefund();
        orderRefund.setRefundId(refundNotifyBO.getRefundId());
        orderRefund.setShopId(dbOrder.getShopId());
        orderRefund.setOrderId(refundNotifyBO.getOrderId());
        orderRefund.setRefundType(RefundType.ALL.value());
        orderRefund.setRefundAmount(refundNotifyBO.getRefundAmount());
        orderRefund.setApplyType(1);
        orderRefund.setIsReceived(0);
        orderRefund.setPlatformRefundAmount(dbOrder.getPlatformAmount());
        orderRefund.setBuyerReason(BuyerReasonType.GROUP_FAILED.value());
        orderRefund.setBuyerDesc("拼团失败：系统自动退款");
        orderRefund.setReturnMoneySts(ReturnProcessStatusEnum.APPLY.value());
        orderRefund.setSellerMsg("拼团失败：系统自动退款");
        orderRefund.setHandelTime(new Date());
        orderRefund.setUpdateTime(new Date());
        orderRefund.setUserId(dbOrder.getUserId());
        orderRefund.setOrderItemId(0L);
        orderRefund.setRefundCount(dbOrder.getAllCount());
        orderRefund.setPlatformRefundCommission(dbOrder.getPlatformCommission());
        orderRefund.setSupplierId(dbOrder.getSupplierId());
        orderRefund.setPaySysType(dbOrder.getPaySysType());
        orderRefund.setPurchaseRefundAmount(orderItemList.stream().mapToLong(OrderItem::getItemPurchaseAmount).sum());
        orderRefund.setPurPlatformRefundCommission(orderItemList.stream().mapToLong(OrderItem::getPurchasePlatformCommission).sum());
        orderRefundMapper.save(orderRefund);

        OrderRefundSettlement orderRefundSettlement = new OrderRefundSettlement();
        orderRefundSettlement.setOrderId(refundNotifyBO.getOrderId());
        orderRefundSettlement.setPayId(refundNotifyBO.getPayId());
        orderRefundSettlement.setRefundId(refundNotifyBO.getRefundId());
        orderRefundSettlement.setRefundAmount(refundNotifyBO.getRefundAmount());
        orderRefundSettlement.setOrderTotalAmount(refundNotifyBO.getRefundAmount());
        orderRefundSettlement.setRefundStatus(1);
        orderRefundSettlement.setUserId(dbOrder.getUserId());
        orderRefundSettlement.setPayType(dbOrder.getPayType());
        orderRefundSettlementMapper.save(orderRefundSettlement);

        refundSuccess(refundNotifyBO);
    }

    @Override
    public List<OrderRefundVO> getProcessingOrderRefundByOrderId(Long orderId) {
        return orderRefundMapper.getProcessingOrderRefundByOrderId(orderId);
    }

    @Override
    public List<OrderRefundVO> listOrderRefundByOrderId(Long orderId) {
        return orderRefundMapper.listOrderRefundByOrderId(orderId);
    }

    @Override
    public Integer getSupplierHandleStatusByOrderId(Long orderId) {
        return orderRefundMapper.getSupplierHandleStatusByOrderId(orderId);
    }

    @Override
    public List<OrderRefundProdEffectRespVO> getProdRefundEffectByDateAndProdIds(List<Long> spuIds, Date startTime, Date endTime) {
        return mongoOrderRefundManager.getProdRefundEffectByDateAndProdIds(spuIds, startTime, endTime);
    }

    @Override
    public List<com.tmerclub.cloud.api.order.vo.OrderRefundVO> getOrderRefundByOrderIdAndRefundStatus(Long orderId, Integer returnMoneySts) {
        return orderRefundMapper.getOrderRefundByOrderIdAndRefundStatus(orderId, returnMoneySts);
    }

    @Override
    public List<OrderRefundSimpleVO> listOrderIdsByRefundIds(List<Long> refundIds) {
        if (CollUtil.isEmpty(refundIds)) {
            return new ArrayList<>(0);
        }
        return orderRefundMapper.listOrderIdsByRefundIds(refundIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelWhenTimeOut(OrderRefundVO orderRefundDb) {
        List<Integer> returnMoneyStsList = ReturnProcessStatusEnum.closeStatus();
        long createTime = DateUtil.offsetDay(new Date(), -Constant.MAX_REFUND_APPLY_TIME).getTime();
        Date now = new Date();
        OrderRefund orderRefund = new OrderRefund();
        Order order = new Order();
        order.setOrderId(orderRefundDb.getOrderId());
        order.setUpdateTime(now);
        orderRefund.setRefundId(orderRefundDb.getRefundId());
        orderRefund.setUpdateTime(now);
        //create_time <![CDATA[ < ]]> #{date} AND return_money_sts in(1,2,3,4) AND
        // 创建时间在15天内或处理退款状态不符合条件的不进行取消退款处理
        if (orderRefundDb.getCreateTime().getTime() > createTime || !returnMoneyStsList.contains(orderRefundDb.getReturnMoneySts())) {
            // 更新退款的更新时间，同步es、mongo中的退款数据
            orderRefundMapper.update(orderRefund);
            orderService.update(order);
            return;
        }
        orderRefund.setReturnMoneySts(ReturnProcessStatusEnum.FAIL.value());
        orderRefund.setSellerMsg("申请退款超时");
        orderRefund.setCloseTime(now);
        orderRefund.setCloseType(RefundCloseType.TIME_OUT.value());
        orderRefund.setHandelTime(now);
        // 批量修改订单退款状态
        // 查询退款成功的订单商品数量
        Integer orderRefundSuccessCount = orderRefundMapper.countRefundSuccessRefundCountByOrderId(orderRefundDb.getOrderId());
        // 更新订单,如果有订单项退款成功，则订单状态为部分退款成功，否则为退款失败
        if (orderRefundSuccessCount > 0) {
            order.setRefundStatus(RefundStatusEnum.PARTIAL_SUCCESS.value());
        } else {
            order.setRefundStatus(RefundStatusEnum.DISAGREE.value());
        }

        // 更新订单项状态
        if (Objects.equals(orderRefundDb.getRefundType(), RefundType.ALL.value())) {
            orderItemService.updateRefundStatusByOrderId(orderRefundDb.getOrderId(), RefundStatusEnum.DISAGREE.value());
        } else {
            // 退款失败
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderItemId(orderRefundDb.getOrderItemId());
            orderItem.setRefundStatus(RefundStatusEnum.DISAGREE.value());
            orderItemService.update(orderItem);
        }
        orderRefundMapper.update(orderRefund);
        orderService.update(order);
    }

    @Override
    public com.tmerclub.cloud.api.order.vo.OrderRefundVO getOrderRefundByRefundId(Long refundId) {
        OrderRefundVO orderRefundVO = getByRefundId(refundId);
        Order order = orderService.getByOrderId(orderRefundVO.getOrderId());
        orderRefundVO.setPaySysType(order.getPaySysType());
        return BeanUtil.map(orderRefundVO, com.tmerclub.cloud.api.order.vo.OrderRefundVO.class);
    }

    @Override
    public int countSuccessItemNum(Long orderId) {
        return orderRefundMapper.countSuccessItemNum(orderId);
    }

    @Override
    public EsOrderRefundBO saveMongoAndGetEsOrderRefundInfo(Long refundId) {
        MongoOrderRefundBO mongoOrderRefundBO = orderRefundMapper.mongoAndEsOrderRefundInfo(refundId);
        if (Objects.isNull(mongoOrderRefundBO)) {
            return null;
        }
        MongoOrderRefundBO mongoOrder = orderRefundMapper.mongoEsOrder(mongoOrderRefundBO.getOrderId());
        mongoOrderRefundBO.setShopName(mongoOrder.getShopName());
        mongoOrderRefundBO.setOrderType(mongoOrder.getOrderType());
        mongoOrderRefundBO.setFreightAmount(mongoOrder.getFreightAmount());
        mongoOrderRefundBO.setOrderStatus(mongoOrder.getOrderStatus());
        mongoOrderRefundBO.setWaitPurchase(mongoOrder.getWaitPurchase());
        mongoOrderRefundBO.setPayType(mongoOrder.getPayType());
        mongoOrderRefundBO.setPayId(mongoOrder.getPayId());
        // 处理包含赠品还有组合商品的退款订单
        List<Long> giveawayList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        if (Objects.nonNull(mongoOrderRefundBO.getReturnGiveawayIds())) {
            String[] split = mongoOrderRefundBO.getReturnGiveawayIds().split(StrUtil.COMMA);
            giveawayList = Arrays.stream(split).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
        }
        List<MongoOrderRefundItemBO> mongoOrderRefundItems = orderRefundMapper.mongoAndEsOrderRefundItems(mongoOrderRefundBO.getOrderId(), mongoOrderRefundBO.getOrderItemId(), giveawayList);
        List<MongoOrderRefundItemBO> allItems = orderRefundMapper.mongoAndEsOrderRefundItems(mongoOrderRefundBO.getOrderId(), null, null);
        Map<Long, List<MongoOrderRefundItemBO>> itemMap = allItems.stream().filter(orderItem -> Objects.equals(orderItem.getActivityType(), OrderActivityType.COMBO_PROD.value())).collect(Collectors.groupingBy(MongoOrderRefundItemBO::getActivityId));
        // 获取订单数据
        if (Objects.equals(mongoOrderRefundBO.getRefundType(), RefundType.SINGLE.value())) {
            mongoOrderRefundItems.get(0).setRefundAmount(mongoOrderRefundBO.getRefundAmount());
            if(MapUtil.isNotEmpty(itemMap) && itemMap.containsKey(mongoOrderRefundItems.get(0).getOrderItemId())){
                mongoOrderRefundItems.addAll(itemMap.get(mongoOrderRefundItems.get(0).getOrderItemId()));
            }
        }

        mongoOrderRefundBO.setOrderItems(mongoOrderRefundItems);

        // 单项商品退款,要把订单项中的商品数量换成退款的商品数量
        for (MongoOrderRefundItemBO mongoOrderRefundItem : mongoOrderRefundItems) {
            // 单项退款处理订单项
            if (Objects.equals(mongoOrderRefundBO.getRefundType(), RefundType.SINGLE.value())) {
                if (Objects.equals(mongoOrderRefundItem.getOrderItemId(), mongoOrderRefundBO.getOrderItemId())) {
                    mongoOrderRefundItem.setCount(mongoOrderRefundBO.getRefundCount());
                    mongoOrderRefundBO.setRefundScore(mongoOrderRefundItem.getRefundScore());
                }
            }
            if (Objects.equals(mongoOrderRefundBO.getRefundType(), RefundType.SINGLE.value())) {
                mongoOrderRefundItem.setRefundAmount(mongoOrderRefundBO.getRefundAmount());
            } else {
                mongoOrderRefundItem.setRefundAmount(mongoOrderRefundItem.getActualTotal());
            }
            for (OrderItemLangVO orderItemLangVO : mongoOrderRefundItem.getOrderItemLangList()) {
                if (Objects.equals(orderItemLangVO.getLang(), LanguageEnum.LANGUAGE_EN.getLang())) {
                    mongoOrderRefundItem.setSkuNameEn(orderItemLangVO.getSkuName());
                    mongoOrderRefundItem.setSpuNameEn(orderItemLangVO.getSpuName());
                    mongoOrderRefundItem.setSupplierSkuNameEn(orderItemLangVO.getSupplierSkuName());
                    mongoOrderRefundItem.setSupplierSpuNameEn(orderItemLangVO.getSupplierSpuName());
                } else {
                    mongoOrderRefundItem.setSkuNameZh(orderItemLangVO.getSkuName());
                    mongoOrderRefundItem.setSpuNameZh(orderItemLangVO.getSpuName());
                    mongoOrderRefundItem.setSupplierSkuNameZh(orderItemLangVO.getSupplierSkuName());
                    mongoOrderRefundItem.setSupplierSpuNameZh(orderItemLangVO.getSupplierSpuName());
                }
            }
        }
        mongoOrderRefundManager.save(mongoOrderRefundBO);
        return BeanUtil.map(mongoOrderRefundBO, EsOrderRefundBO.class);
    }

    @Override
    public PageVO<OrderRefundVO> userOrderRefundPage(PageDTO pageDTO, OrderRefundSearchDTO orderRefundSearchDTO) {
        Long userId = AuthUserContext.get().getUserId();
        orderRefundSearchDTO.setUserId(userId);
        PageVO<OrderRefundVO> pageVO = PageUtil.doPage(pageDTO, () -> orderRefundMapper.listUserOrderRefund(orderRefundSearchDTO));
        if (CollUtil.isEmpty(pageVO.getList())) {
            return pageVO;
        }
        List<Long> orderIds = pageVO.getList().stream().map(OrderRefundVO::getOrderId).collect(Collectors.toList());
        List<OrderItemVO> orderItemList = orderItemService.listOrderItemsByUserIdAndOrderIds(userId, orderIds);
        Map<Long, List<OrderItemVO>> orderItemMap = orderItemList.stream().collect(Collectors.groupingBy(OrderItemVO::getOrderId));
        List<Long> shopIds = pageVO.getList().stream().map(OrderRefundVO::getShopId).collect(Collectors.toList());
        List<ShopDetailVO> shops = shopDetailFeignClient.listByShopIds(shopIds).getData();
        Map<Long, String> shopNameMap = shops.stream().collect(Collectors.toMap(ShopDetailVO::getShopId, ShopDetailVO::getShopName));
        for (OrderRefundVO orderRefundVO : pageVO.getList()) {
            if(Objects.nonNull(orderRefundVO.getApplyInterventionTime())) {
                orderRefundVO.setInterventionEndTime(DateUtil.offsetHour(orderRefundVO.getApplyInterventionTime(), 72));
                orderRefundVO.setPlatformProcessingEndTime(DateUtil.offsetDay(orderRefundVO.getApplyInterventionTime(), 7));
            }
            List<OrderItemVO> orderItems = orderItemMap.get(orderRefundVO.getOrderId());
            String shopName = shopNameMap.get(orderRefundVO.getShopId());
            if (CollUtil.isEmpty(orderItems) || Objects.isNull(shopName)) {
                continue;
            }
            orderRefundVO.setShopName(shopName);
            List<RefundOrderItemVO> refundOrderItems = BeanUtil.mapAsList(orderItems, RefundOrderItemVO.class);
            orderRefundVO.setOrderItems(refundOrderItems);
            // 整单退款不需要处理赠品和退款数量
            if (Objects.equals(orderRefundVO.getRefundType(), RefundType.ALL.value())) {
                giveawayRefundOrderItem(orderRefundVO);
                continue;
            }

            // 获取赠品id列表
            List<Long> giveawayList;
            if (StrUtil.isNotBlank(orderRefundVO.getReturnGiveawayIds())) {
                String[] split = orderRefundVO.getReturnGiveawayIds().split(",");
                giveawayList = Arrays.stream(split).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
            } else {
                giveawayList = new ArrayList<>(0);
            }

            // 单项退款处理订单项
            Iterator<RefundOrderItemVO> iterator = refundOrderItems.iterator();
            while (iterator.hasNext()) {
                RefundOrderItemVO refundOrderItem = iterator.next();
                // 移除不是退款或退款项赠品的订单项
                if (!Objects.equals(refundOrderItem.getOrderItemId(), orderRefundVO.getOrderItemId()) && !giveawayList.contains(refundOrderItem.getOrderItemId())) {
                    iterator.remove();
                    continue;
                }
                // 单项商品退款,要把订单项中的商品数量换成退款的商品数量
                if (Objects.equals(refundOrderItem.getOrderItemId(), orderRefundVO.getOrderItemId())) {
                    refundOrderItem.setCount(orderRefundVO.getRefundCount());
                    refundOrderItem.setRefundScore(orderRefundVO.getRefundScore());
                }
            }
            giveawayRefundOrderItem(orderRefundVO);
        }
        return pageVO;
    }

    /**
     * 处理赠品退款订单项
     * @param orderRefundVO
     */
    private void giveawayRefundOrderItem(OrderRefundVO orderRefundVO) {
        Map<Long, List<RefundOrderItemVO>> map = orderRefundVO.getOrderItems().stream()
                .filter(s -> Objects.equals(s.getActivityType(), OrderActivityType.GIVEAWAY.value()))
                .collect(Collectors.groupingBy(RefundOrderItemVO::getActivityId));
        Map<Long, List<RefundOrderItemVO>> comboMap = orderRefundVO.getOrderItems().stream()
                .filter(s -> Objects.equals(s.getActivityType(), OrderActivityType.COMBO_PROD.value()))
                .collect(Collectors.groupingBy(RefundOrderItemVO::getActivityId));
        // 如果没有赠品，就不需要处理
        if (MapUtil.isEmpty(map) && MapUtil.isEmpty(comboMap)) {
            return;
        }
        // 将赠品放到对应的主订单项中
        Iterator<RefundOrderItemVO> iterator = orderRefundVO.getOrderItems().iterator();
        while (iterator.hasNext()) {
            RefundOrderItemVO refundOrderItemVO = iterator.next();
            // 移除赠品的订单项，进入下一个循环
            if (Objects.equals(refundOrderItemVO.getActivityType(), OrderActivityType.GIVEAWAY.value()) || Objects.equals(refundOrderItemVO.getActivityType(), OrderActivityType.COMBO_PROD.value())) {
                iterator.remove();
                continue;
            }
            // 主订单项插入赠品订单项
            if (map.containsKey(refundOrderItemVO.getOrderItemId())) {
                refundOrderItemVO.setGiveawayList(map.get(refundOrderItemVO.getOrderItemId()));
            }
            // 主订单项插入赠品订单项
            if (comboMap.containsKey(refundOrderItemVO.getOrderItemId())) {
                refundOrderItemVO.setComboList(comboMap.get(refundOrderItemVO.getOrderItemId()));
            }
        }
    }

    @Override
    public AccountOrderDetailVO getAccountOrderDetail(Date startTime, Date endTime, String shopName, Long shopId) {
        return mongoOrderRefundManager.getAccountRefundOrderDetail(startTime, endTime, shopName, shopId);
    }

    @Override
    public PageShopAccountOrderVO listShopAccountDetail(Date startTime, Date endTime, String shopName, Integer pageSize, Integer pageNum) {
        return mongoOrderRefundManager.listShopRefundAccountDetail(startTime, endTime, shopName, pageSize, pageNum);
    }

    @Override
    public PageShopAccountOrderVO listOrderRefundInfo(Date startTime, Date endTime, Long shopId, String shopName, Integer pageSize, Integer pageNum) {
        if (Objects.isNull(pageNum) && Objects.isNull(pageSize)) {
            return mongoOrderRefundManager.listOrderRefundInfo(startTime, endTime, shopName);
        }
        return mongoOrderRefundManager.pageOrderRefundInfo(startTime, endTime, shopId, pageSize, pageNum);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void refundRequest(Long refundId) {
        // 获取退款信息
        OrderRefundVO orderRefundVO = getDetailByRefundId(refundId);
        if (Objects.isNull(orderRefundVO)) {
            logger.error("退款订单{}不存在", refundId);
        }
        if (!Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.PROCESSING.value())) {
            logger.error("退款订单{}不在商家处理状态，发放退款失败", refundId);
        }
        // 如果有移交供应商时间就属于供应商退款，额外处理
        if (Objects.nonNull(orderRefundVO.getSupplierTime()) && Objects.equals(orderRefundVO.getSupplierHandleStatus(), SupplierHandleStatus.SUPPLIER_AGREE.value())) {
            logger.info("退款订单{}由供应商处理，设置供应商相关数值", refundId);
            OrderSettlement orderSettlement = orderSettlementService.getByOrderId(orderRefundVO.getOrderId());
            setSupplierOrderRefundInfo(orderRefundVO, orderSettlement);
        } else {
            setOrderRefundInfo(orderRefundVO);
        }
        PayRefundBO payRefundBO = new PayRefundBO();
        payRefundBO.setRefundId(orderRefundVO.getRefundId());
        payRefundBO.setRefundAmount(orderRefundVO.getRefundAmount());
        payRefundBO.setAllinpayRefundPurchaseAmount(orderRefundVO.getAllinpayRefundPurchaseAmount());
        payRefundBO.setOrderId(orderRefundVO.getOrderId());
        payRefundBO.setPayId(orderRefundVO.getPayId());
        payRefundBO.setPayIds(orderRefundVO.getPayIds());
        payRefundBO.setShopId(orderRefundVO.getShopId());
        SendStatus sendStatus = orderRefundPaymentTemplate.syncSend(RocketMqConstant.ORDER_REFUND_PAYMENT_TOPIC, new GenericMessage<>(payRefundBO)).getSendStatus();
        if (!Objects.equals(sendStatus, SendStatus.SEND_OK)) {
            // 消息发不出去就抛异常，因为定时任务回调会有多次，几乎不可能每次都无法发送出去，发的出去无所谓因为接口是幂等的
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    @Override
    public void setSupplierOrderRefundInfo(OrderRefundVO orderRefundVo, OrderSettlement orderSettlement) {
        orderRefundVo.setPayId(orderSettlement.getPayId());
        orderRefundVo.setPayType(orderSettlement.getPayType());
        orderRefundVo.setFreightAmount(0L);
        // 获取订单信息
        Order order = orderService.getOrderByOrderIdAndUserId(orderRefundVo.getOrderId(), orderRefundVo.getUserId());
        if (Objects.equals(order.getStatus(), OrderStatus.PAYED.value())) {
            // -----最后一件商品的运费计算-----------
            long freightAmount = 0L;
            // 如果存在分销订单，则计算分销总金额
            List<OrderItem> orderItemList = orderItemService.listOrderItemsByOrderId(order.getOrderId());
            // 获取所有的订单项总数
            int orderItemCount = orderItemList.size();
            //退款成功总数
            // 获取所有正在进行中的退款订单
            int refundCount = countSuccessItemNum(order.getOrderId());
            //最后一单
            if (Objects.equals(refundCount, orderItemCount - 1)) {
                if (order.getFreightAmount() > 0.0 && order.getPlatformFreeFreightAmount() >= 0.0) {
                    freightAmount = order.getFreightAmount() - order.getPlatformFreeFreightAmount();
                    logger.info("最后一单退款，freightAmount：{}", freightAmount);
                }
                // 单项退款，且平台减免运费---平台减免的运费要从商家钱包退还给平台，所以将运费添加到平台优惠金额中
                if (Objects.equals(orderRefundVo.getRefundType(), RefundType.SINGLE.value()) && order.getPlatformFreeFreightAmount() > 0.0) {
                    orderRefundVo.setPlatformRefundAmount(orderRefundVo.getPlatformRefundAmount() + order.getPlatformFreeFreightAmount());
                    orderRefundVo.setLastOrder(true);
                    logger.info("单项退款，且平台减免运费，平台减免的运费要从商家钱包退还给平台，所以将运费添加到平台优惠金额中，platformRefundAmount：{}", orderRefundVo.getPlatformRefundAmount());
                }
            }
            // 供应商发货的订单，放进去实际的支付运费金额，用于后续的供应商金额退款
            if (Objects.equals(order.getSupplierDeliveryType(), 1) && !Objects.equals(order.getSupplierId(), 0L)) {
                orderRefundVo.setFreightAmount(freightAmount + Math.abs(order.getFreeFreightAmount()));
                logger.info("供应商发货的订单，放进去实际的支付运费金额，用于后续的供应商金额退款，freightAmount：{}", orderRefundVo.getFreightAmount());
            }
            // 只有单个退款才需要加上运费
            if (Objects.equals(orderRefundVo.getRefundType(), RefundType.SINGLE.value())) {
                // 退款金额加上运费
                orderRefundVo.setRefundAmount(orderRefundVo.getRefundAmount() + freightAmount);
                logger.info("单个退款，退款金额加上运费，refundAmount：{}", orderRefundVo.getRefundAmount());
                // 平台减免运费金额的时候，添加供应商发货的订单的运费,商家退款金额需要单独减去上面退款金额中添加的运费
                // 供应商发货的订单单项退款包含的运费为商品原本的运费，不受平台和商家运费减免金额的影响（商家不能修改供应商发货订单的运费，平台减免金额是给商家的，跟供应商没有关系）
                if (Objects.nonNull(order.getPlatformFreeFreightAmount()) && order.getPlatformFreeFreightAmount() > 0.0) {
                    orderRefundVo.setSupplierFreightAmount(order.getFreightAmount());
                    logger.info("平台减免运费金额的时候，添加供应商发货的订单的运费,商家退款金额需要单独减去上面退款金额中添加的运费，supplierFreightAmount：{}", orderRefundVo.getSupplierFreightAmount());
                }
            }
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void applyPlatormIntervertion(OrderRefundInterventionDTO orderRefundParam, OrderRefundVO orderRefundVO) {
        // 更新订单状态
        Order order = new Order();
        order.setOrderId(orderRefundVO.getOrderId());
        order.setRefundStatus(RefundStatusEnum.APPLY.value());
        orderService.update(order);

        // 更新订单项状态
        if (Objects.equals(RefundType.ALL.value(), orderRefundVO.getRefundType())) {
            orderItemService.updateRefundStatusByOrderId(order.getOrderId(), RefundStatusEnum.APPLY.value());
            logger.info("整单退款，更新订单项状态为申请退款，订单id：{}", order.getOrderId());
        } else {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderItemId(orderRefundVO.getOrderItemId());
            orderItem.setRefundStatus(RefundStatusEnum.APPLY.value());
            orderItem.setFinalRefundId(orderRefundVO.getRefundId());
            orderItemService.update(orderItem);
            logger.info("部分退款，更新订单项状态为申请退款，订单项id：{}", orderItem.getOrderItemId());
        }
        //如果是赠品，需要处理关联赠品订单项
        List<OrderItemVO> giveawayOrderItems = orderItemService.getOrderItemByGiveawayOrderItemId(orderRefundVO.getUserId(), orderRefundVO.getOrderItemId());
        if (giveawayOrderItems.size() != 0) {
            logger.info("赠品退款，关联赠品订单项,更新订单项状态为申请退款，订单项id：{}", orderRefundVO.getOrderItemId());
            List<OrderItem> list = new ArrayList<>(Constant.INITIAL_CAPACITY);
            for (OrderItemVO orderItemVO : giveawayOrderItems) {
                OrderItem orderItems = BeanUtil.map(orderItemVO, OrderItem.class);
                orderItems.setRefundStatus(RefundStatusEnum.APPLY.value());
                list.add(orderItems);
            }
            orderItemService.updateBatch(list);
        }
        // 修改退款信息
        OrderRefund orderRefund = new OrderRefund();
        orderRefund.setRefundId(orderRefundParam.getRefundId());
        orderRefund.setPlatformInterventionStatus(PlatformInterventionStatus.APPLY.value());
        orderRefund.setApplyInterventionTime(new Date());
        // 保存用户申请平台介入信息
        orderRefund.setApplyInterventionReason(orderRefundParam.getVoucherDesc());
        orderRefund.setApplyInterventionImgUrls(orderRefundParam.getImgUrls());
        orderRefundMapper.update(orderRefund);
        orderRefundInterventionMapper.deleteById(orderRefundParam.getRefundId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cacelPlatormIntervertion(OrderRefundInterventionDTO orderRefundParam, OrderRefundVO orderRefundVO) {
        // 修改退款信息
        OrderRefund orderRefund = new OrderRefund();
        orderRefund.setRefundId(orderRefundParam.getRefundId());
        orderRefund.setPlatformInterventionStatus(PlatformInterventionStatus.NONE.value());
        orderRefund.setInterventionFinishTime(new Date());
        // 保存用户申请平台介入信息
        orderRefundMapper.update(orderRefund);
        closeOrderAndOrderItemRefundStatus(orderRefundVO);
    }


    @Override
    public List<Long> listOrderRefundByOrderIds(List<Long> orderIds) {
        if (CollUtil.isEmpty(orderIds)) {
            return new ArrayList<>(0);
        }
        return orderRefundMapper.listOrderRefundByOrderIds(orderIds);
    }

    /**
     * 判断退款单类型（1:整单退款,2:单个物品退款）
     * sysType,1.展示赠品信息，0.不展示
     */
    private void getRefundTypeByOrderItem(OrderRefundVO orderRefundVO, Integer sysType) {
        Order order = orderService.getOrderByOrderIdAndUserId(orderRefundVO.getOrderId(), orderRefundVO.getUserId());
        orderRefundVO.setWaitPurchase(order.getWaitPurchase());
        if (Objects.equals(orderRefundVO.getRefundType(), RefundType.ALL.value())) {
            List<RefundOrderItemVO> items = orderRefundVO.getOrderItems();
            List<RefundOrderItemVO> reItems = new ArrayList<>(Constant.INITIAL_CAPACITY);
            orderRefundVO.setRefundScore(items.stream().mapToLong(RefundOrderItemVO::getRefundScore).sum());
            //放入赠品信息
            if (Objects.equals(sysType, 1)) {
                List<Long> itemIds = items.stream().map(RefundOrderItemVO::getOrderItemId).collect(Collectors.toList());
                List<OrderItemVO> giveawayAndComboItems = orderItemService.getOrderItemByGiveawayOrderItemIds(itemIds, order.getUserId(), sysType);
                List<RefundOrderItemVO> itemVOList = BeanUtil.mapAsList(giveawayAndComboItems, RefundOrderItemVO.class);
                Map<Long, List<RefundOrderItemVO>> giveawayAndComboItemMap = itemVOList.stream().collect(Collectors.groupingBy(RefundOrderItemVO::getActivityId));
                for (RefundOrderItemVO orderItem : items) {
                    if (Objects.equals(orderItem.getActivityType(), OrderActivityType.GIVEAWAY.value()) || Objects.equals(orderItem.getActivityType(), OrderActivityType.COMBO_PROD.value())) {
                        continue;
                    }
                    if(giveawayAndComboItemMap.containsKey(orderItem.getOrderItemId())){
                        Map<Integer, List<RefundOrderItemVO>> activityTypeItemMap = giveawayAndComboItemMap.get(orderItem.getOrderItemId()).stream().collect(Collectors.groupingBy(RefundOrderItemVO::getActivityType));
                        // 放入赠品
                        orderItem.setGiveawayList(activityTypeItemMap.get(OrderActivityType.GIVEAWAY.value()));
                        // 放入组合
                        orderItem.setComboList(activityTypeItemMap.get(OrderActivityType.COMBO_PROD.value()));
                    }
                    reItems.add(orderItem);
                }
            }
            orderRefundVO.setOrderItems(reItems);
        } else {
            OrderItemVO item = orderItemService.getByOrderItemId(orderRefundVO.getOrderItemId());
            orderRefundVO.setRefundScore(item.getUseScore());
            orderRefundVO.setFreightAmount(order.getFreightAmount());
            RefundOrderItemVO reItemVo = BeanUtil.map(item, RefundOrderItemVO.class);
            //放入赠品信息
            String returnGiveawayIds = orderRefundVO.getReturnGiveawayIds();
            // 获取当前组合的子商品ids
            List<Long> comboItemIds = orderRefundVO.getOrderItems().stream().filter(refundOrderItemVO -> Objects.equals(refundOrderItemVO.getActivityType(),OrderActivityType.COMBO_PROD.value())
                    && Objects.equals(refundOrderItemVO.getActivityId(),orderRefundVO.getOrderItemId())).map(RefundOrderItemVO::getOrderItemId).toList();
            // 如果组合商品或者赠品都没有则不需要处理了
            boolean flag = StrUtil.isBlank(returnGiveawayIds) && CollectionUtil.isEmpty(comboItemIds);
            if ( flag || Objects.equals(sysType, 0)) {
                return;
            }
            List<Long> itemIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
            if(StrUtil.isNotBlank(returnGiveawayIds)) {
                String[] split = returnGiveawayIds.split(StrUtil.COMMA);
                itemIds = Arrays.stream(split).map(s -> Long.parseLong(s.trim())).toList();
            }
            if (CollUtil.isNotEmpty(comboItemIds)) {
                itemIds.addAll(comboItemIds);
            }

            List<OrderItemVO> giveawayAndComboItems = orderItemService.getOrderItemByGiveawayOrderItemIds(itemIds, item.getUserId(), null);
            List<RefundOrderItemVO> itemVOList = BeanUtil.mapAsList(giveawayAndComboItems, RefundOrderItemVO.class);
            List<RefundOrderItemVO> reItems = new ArrayList<>(0);
            for (RefundOrderItemVO refundOrderItemVO : orderRefundVO.getOrderItems()) {
                if (refundOrderItemVO.getOrderItemId().equals(reItemVo.getOrderItemId())) {
                    Map<Integer, List<RefundOrderItemVO>> activityTypeItemMap = itemVOList.stream().collect(Collectors.groupingBy(RefundOrderItemVO::getActivityType));
                    // 放入赠品
                    refundOrderItemVO.setGiveawayList(activityTypeItemMap.get(OrderActivityType.GIVEAWAY.value()));
                    // 放入组合
                    refundOrderItemVO.setComboList(activityTypeItemMap.get(OrderActivityType.COMBO_PROD.value()));
                    reItems.add(refundOrderItemVO);
                    break;
                }
            }
            orderRefundVO.setOrderItems(reItems);
        }
    }
}
