package com.bonus.canteen.core.order.business;

import cn.hutool.core.collection.CollUtil;
import com.bonus.canteen.core.account.constants.AccTradeTypeEnum;
import com.bonus.canteen.core.account.constants.AccWalletTypeEnum;
import com.bonus.canteen.core.account.domain.AccWalletInfo;
import com.bonus.canteen.core.account.domain.WalletUpdateDTO;
import com.bonus.canteen.core.account.domain.bo.TradeAndWalletInfo;
import com.bonus.canteen.core.account.service.IAccTradeService;
import com.bonus.canteen.core.account.service.IAccWalletInfoService;
import com.bonus.canteen.core.common.utils.MqUtil;
import com.bonus.canteen.core.common.utils.ObjectUtils;
import com.bonus.canteen.core.common.utils.RedisUtil;
import com.bonus.canteen.core.cook.domain.CookRecipeDetail;
import com.bonus.canteen.core.cook.domain.CookRecipeDishes;
import com.bonus.canteen.core.cook.enums.RecipeDetailTypeEnum;
import com.bonus.canteen.core.cook.service.ICookRecipeDetailService;
import com.bonus.canteen.core.cook.service.ICookRecipeDishesService;
import com.bonus.canteen.core.order.constants.OrderDetailStateEnum;
import com.bonus.canteen.core.order.constants.OrderDetailTypeEnum;
import com.bonus.canteen.core.order.constants.OrderRefundStateEnum;
import com.bonus.canteen.core.order.constants.OrderStateEnum;
import com.bonus.canteen.core.order.domain.OrderDetail;
import com.bonus.canteen.core.order.domain.OrderInfo;
import com.bonus.canteen.core.order.domain.OrderPayDTO;
import com.bonus.canteen.core.order.domain.OrderPayResultDTO;
import com.bonus.canteen.core.order.domain.param.OrderPartRefundDetailParam;
import com.bonus.canteen.core.order.domain.param.OrderPartRefundParam;
import com.bonus.canteen.core.order.mapper.OrderInfoMapper;
import com.bonus.canteen.core.order.mq.bo.DeviceRefundOrderBO;
import com.bonus.canteen.core.order.mq.bo.DeviceRefundOrderDetailBO;
import com.bonus.canteen.core.order.service.IOrderDetailService;
import com.bonus.canteen.core.pay.constants.PayChannelEnum;
import com.bonus.canteen.core.pay.constants.PayStateEnum;
import com.bonus.canteen.core.pay.constants.PayTypeEnum;
import com.bonus.canteen.core.user.domain.DeviceMqPersonalUpdateMessageDTO;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.houqin.mq.constant.LeMqConstant;
import com.bonus.common.houqin.utils.JacksonUtil;
import com.bonus.common.security.utils.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Component
public class OrderBusiness {
    private static final Logger log = LoggerFactory.getLogger(OrderBusiness.class);
    private static final String ORDER_REFUND_REDIS_KEY = "sc:order_refund_orderId_%s";

    @Autowired
    private IOrderDetailService orderDetailService;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private ICookRecipeDishesService cookRecipeDishesService;
    @Autowired
    private IAccWalletInfoService accWalletInfoService;
    @Autowired
    private IAccTradeService accTradeService;
    @Autowired
    private ICookRecipeDetailService cookRecipeDetailService;

    @Transactional(rollbackFor = Exception.class)
    public List<OrderInfo> orderPlaceHandler(List<OrderInfo> orderInfoList) {
        if(CollUtil.isEmpty(orderInfoList)) {
            throw new ServiceException("订单明细不能为空");
        }
        orderInfoMapper.batchInsertOrderInfo(orderInfoList);
        if(CollUtil.isNotEmpty(orderInfoList.get(0).getOrderDetailList())) {
            orderInfoList.forEach(orderInfo -> {
                List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
                orderDetailList.forEach(orderDetail -> orderDetail.setOrderId(orderInfo.getOrderId()));
                orderDetailService.batchInsertOrderDetail(orderDetailList);
                reduceMenuDishSupplyNum(orderDetailList, orderInfo.getUserId(), orderInfo.getOrderTime());
            });
        }
        return orderInfoList;
    }

    public void reduceMenuDishSupplyNum(List<OrderDetail> orderDetailList, Long userId, Date orderTime) {
        log.info("订单扣减库存入参：{}", JacksonUtil.writeValueAsString(orderDetailList));
        for(OrderDetail orderDetail : orderDetailList) {
            if(OrderDetailTypeEnum.KEYAMOUNT.getKey().equals(orderDetail.getDetailType())) {
                continue;
            }
            CookRecipeDishes menuRecipeDishes = new CookRecipeDishes();
            ObjectUtils.setAllFieldsToNull(menuRecipeDishes);
            CookRecipeDetail menuRecipeDetail = new CookRecipeDetail();
            menuRecipeDetail.setDetailType(RecipeDetailTypeEnum.DETAIL_DATA.key());
            menuRecipeDetail.setRecipeId(orderDetail.getRecipeId());
            menuRecipeDetail.setApplyDate(orderDetail.getOrderDate());
            menuRecipeDetail.setMealtimeType(orderDetail.getMealtimeType());
            log.info("菜谱详情入参：{}", JacksonUtil.writeValueAsString(menuRecipeDetail));
            List<CookRecipeDetail> cookRecipeDetails = cookRecipeDetailService.selectCookRecipeDetailList(menuRecipeDetail);
            if(CollUtil.isEmpty(cookRecipeDetails) || cookRecipeDetails.size() > 1) {
                throw new ServiceException("菜谱详情异常");
            }
            menuRecipeDishes.setRecipeDetailId(cookRecipeDetails.get(0).getRecipeDetailId());
            menuRecipeDishes.setDishesId(orderDetail.getGoodsId());
            cookRecipeDishesService.reduceMenuRecipeDishesSupplyNum(menuRecipeDishes, menuRecipeDetail,
                    orderDetail.getQuantity(), userId , orderTime);
        }
    }

    public void addMenuDishSupplyNum(List<OrderDetail> orderDetailList) {
        log.info("订单新增库存入参：{}", JacksonUtil.writeValueAsString(orderDetailList));
        for(OrderDetail orderDetail : orderDetailList) {
            if(OrderDetailTypeEnum.KEYAMOUNT.getKey().equals(orderDetail.getDetailType())) {
                continue;
            }
            CookRecipeDishes menuRecipeDishes = new CookRecipeDishes();
            ObjectUtils.setAllFieldsToNull(menuRecipeDishes);
            menuRecipeDishes.setRecipeDetailId(orderDetail.getRecipeDetailId());
            menuRecipeDishes.setDishesId(orderDetail.getGoodsId());
            cookRecipeDishesService.addMenuRecipeDishesSupplyNum(menuRecipeDishes, orderDetail.getQuantity());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateOrderPayFailed(List<OrderInfo> orderInfoList) {
        OrderPayResultDTO orderPayResultDTO = new OrderPayResultDTO();
        orderPayResultDTO.setOrderIdList(orderInfoList.stream().map(OrderInfo::getOrderId).collect(Collectors.toList()));
        orderPayResultDTO.setPayState(PayStateEnum.PAY_FAIL.getKey());
        orderPayResultDTO.setUpdateBy(SecurityUtils.getUsername());
        orderPayResultDTO.setPayTime(LocalDateTime.now());
        orderPayResultDTO.setUpdateTime(LocalDateTime.now());
        orderInfoMapper.updateOrderPayResult(orderPayResultDTO);
    }

    @Transactional(rollbackFor = Exception.class)
    public void orderPay(List<OrderInfo> orderInfoList) {
        OrderPayDTO orderPayDTO = buildOrderPayDTO(orderInfoList);
        try {
            List<AccWalletInfo> walletInfoList = accWalletInfoService.selectAccWalletInfoByUserId(orderPayDTO.getUserId());
            if (CollUtil.isEmpty(walletInfoList)) {
                throw new ServiceException("钱包不存在");
            }

            BigDecimal subsidyWalletBal = getWalletBalance(walletInfoList, AccWalletTypeEnum.SUBSIDY);
            BigDecimal personalWalletBal = getWalletBalance(walletInfoList, AccWalletTypeEnum.WALLET);
            BigDecimal totalWalletBal = subsidyWalletBal.add(personalWalletBal);

            if (totalWalletBal.compareTo(orderPayDTO.getOrderTotalAmount()) < 0) {
                throw new ServiceException("钱包余额不足");
            }
            for(OrderInfo orderInfo : orderInfoList) {
                walletInfoList = accWalletInfoService.selectAccWalletInfoByUserId(orderPayDTO.getUserId());
                subsidyWalletBal = getWalletBalance(walletInfoList, AccWalletTypeEnum.SUBSIDY);
                deductFromWallets(orderInfo, subsidyWalletBal);
            }
        } catch (ServiceException ex) {
            log.error("订单支付异常", ex);
            throw new ServiceException(ex.getMessage());
        } catch (Exception ex) {
            log.error("订单支付异常", ex);
            throw new ServiceException("支付失败");
        }
        List<OrderInfo> deviceOrderInfoList = orderInfoList.stream()
                .filter(orderInfo -> StringUtils.isNotEmpty(orderInfo.getDeviceOrderId()))
                .collect(Collectors.toList());
        List<OrderInfo> reserveOrderInfoList = orderInfoList.stream()
                .filter(orderInfo -> StringUtils.isEmpty(orderInfo.getDeviceOrderId()))
                .collect(Collectors.toList());
        if(CollUtil.isNotEmpty(deviceOrderInfoList)) {
            OrderPayResultDTO orderPayResultDTO = new OrderPayResultDTO();
            orderPayResultDTO.setOrderIdList(deviceOrderInfoList.stream().map(OrderInfo::getOrderId).collect(Collectors.toList()));
            orderPayResultDTO.setPayState(PayStateEnum.PAY_SUCC.getKey());
            orderPayResultDTO.setUpdateBy(SecurityUtils.getUsername());
            orderPayResultDTO.setOrderState(OrderStateEnum.FINISH.getKey());
            orderPayResultDTO.setPayTime(LocalDateTime.now());
            orderPayResultDTO.setUpdateTime(LocalDateTime.now());
            orderInfoMapper.updateOrderPayResult(orderPayResultDTO);
        }
        if(CollUtil.isNotEmpty(reserveOrderInfoList)) {
            OrderPayResultDTO orderPayResultDTO = new OrderPayResultDTO();
            orderPayResultDTO.setOrderIdList(reserveOrderInfoList.stream().map(OrderInfo::getOrderId).collect(Collectors.toList()));
            orderPayResultDTO.setPayState(PayStateEnum.PAY_SUCC.getKey());
            orderPayResultDTO.setUpdateBy(SecurityUtils.getUsername());
            orderPayResultDTO.setOrderState(OrderStateEnum.PLACE.getKey());
            orderPayResultDTO.setPayTime(LocalDateTime.now());
            orderPayResultDTO.setUpdateTime(LocalDateTime.now());
            orderInfoMapper.updateOrderPayResult(orderPayResultDTO);
        }

        try {
            DeviceMqPersonalUpdateMessageDTO bean = new DeviceMqPersonalUpdateMessageDTO().setUpdatePerson(Math.toIntExact(orderInfoList.get(0).getUserId()),"update");
            String jsonString = JacksonUtil.writeValueAsString(bean);
            log.info("账户变动发送mq内容：{}", jsonString);
            MqUtil.pushToTenantAllDevice(bean, LeMqConstant.Topic.DEVICE_UPDATE_PERSONAL_CONFIG_V4);
        } catch (Exception e) {
            log.error("发送MQ消息失败", e);
        }
    }

    private OrderPayDTO buildOrderPayDTO(List<OrderInfo> orderInfoList) {
        OrderPayDTO orderPayDTO = new OrderPayDTO();
        BigDecimal totalAmount = orderInfoList.stream()
                .map(OrderInfo::getRealAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        orderPayDTO.setOrderTotalAmount(totalAmount);
        orderPayDTO.setUserId(orderInfoList.get(0).getUserId());
        orderPayDTO.setOrderInfoList(orderInfoList);
        return orderPayDTO;
    }

    private void deductFromWallets(OrderInfo orderInfo, BigDecimal subsidyWalletBal) {
        Long orderNo = orderInfo.getOrderId();
        String deviceSn = orderInfo.getDeviceSn();
        if (orderInfo.getRealAmount().compareTo(subsidyWalletBal) <= 0) {
            deductWalletBalance(orderInfo.getRealAmount(), orderInfo.getUserId(), AccWalletTypeEnum.SUBSIDY, orderNo, deviceSn);
        } else if (subsidyWalletBal.compareTo(BigDecimal.ZERO) > 0) {
            deductWalletBalance(subsidyWalletBal, orderInfo.getUserId(), AccWalletTypeEnum.SUBSIDY, orderNo, deviceSn);
            BigDecimal remainAmount = orderInfo.getRealAmount().subtract(subsidyWalletBal);
            deductWalletBalance(remainAmount, orderInfo.getUserId(), AccWalletTypeEnum.WALLET, orderNo, deviceSn);
        } else {
            deductWalletBalance(orderInfo.getRealAmount(), orderInfo.getUserId(), AccWalletTypeEnum.WALLET, orderNo, deviceSn);
        }
    }

    private void deductWalletBalance(BigDecimal amount,
                                     Long userId,
                                     AccWalletTypeEnum walletTypeEnum,
                                     Long orderNo,
                                     String deviceSn) {
        WalletUpdateDTO walletUpdateDTO = new WalletUpdateDTO();
        walletUpdateDTO.setAmount(amount);
        walletUpdateDTO.setUserId(userId);
        walletUpdateDTO.setAccWalletTypeEnum(walletTypeEnum);
        walletUpdateDTO.setAccTradeTypeEnum(AccTradeTypeEnum.CONSUME);
        walletUpdateDTO.setPayChannelEnum(PayChannelEnum.ACC);
        walletUpdateDTO.setPayTypeEnum(PayTypeEnum.MEAL_CARD);
        walletUpdateDTO.setOrderNo(orderNo);
        walletUpdateDTO.setDeviceSn(deviceSn);
        walletUpdateDTO.setBatch(true);
        accWalletInfoService.clearAccWalletBalance(walletUpdateDTO);
    }

    private BigDecimal getWalletBalance(List<AccWalletInfo> walletInfoList, AccWalletTypeEnum walletTypeEnum) {
        return walletInfoList.stream()
                .filter(walletInfo -> walletTypeEnum.getKey().equals(walletInfo.getWalletType()))
                .map(AccWalletInfo::getWalletBal)
                .findFirst()
                .orElse(BigDecimal.ZERO);
    }

    @Transactional(rollbackFor = {Exception.class})
    public List<DeviceRefundOrderDetailBO> partRefund(OrderPartRefundParam param, OrderInfo orderInfo) {
        if(Objects.isNull(orderInfo)) {
            throw new ServiceException("订单不存在");
        }
        String refundKey = String.format(ORDER_REFUND_REDIS_KEY, param.getOrderId());
        if (!RedisUtil.setNx(refundKey, 1, 2)) {
            log.info("退单处理中：{}", refundKey);
            throw new ServiceException("退单处理中");
        }
        if(orderInfo.getOrderRefundState().equals(OrderRefundStateEnum.FINISH.getKey())) {
            throw new ServiceException("订单已退");
        }
        if(orderInfo.getOrderState().equals(OrderStateEnum.CANCEL.getKey())) {
            throw new ServiceException("订单已取消");
        }
//        if(orderInfo.getOrderState().equals(OrderStateEnum.FINISH.getKey())) {
//            throw new ServiceException("订单已核销");
//        }
        List<OrderDetail> orderRefundDetailList = new ArrayList<>();
        List<DeviceRefundOrderDetailBO> deviceRefundOrderDetailList = new ArrayList<>();
        if(PayStateEnum.PAY_SUCC.getKey().equals(orderInfo.getPayState())) {
            List<TradeAndWalletInfo> accTradeList = accTradeService.queryTradeAndWallerInfoByOrderNo
                    (String.valueOf(param.getOrderId()), AccTradeTypeEnum.CONSUME);
            if(CollUtil.isEmpty(accTradeList)) {
                throw new ServiceException("订单交易记录不存在");
            }
            BigDecimal refundAmount = BigDecimal.ZERO;

            List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
            for(OrderPartRefundDetailParam detailParam : param.getOrderPartRefundDetailList()) {
                OrderDetail orderDetail = orderDetailList.stream()
                        .filter(detail -> detail.getDetailId()
                                .equals(detailParam.getDetailId())).findFirst().orElse(null);
                if(orderDetail == null) {
                    throw new ServiceException("订单明细不存在");
                }
                if(orderDetail.getQuantity() < detailParam.getQuantity()) {
                    throw new ServiceException("退菜数量不能大于订单数量");
                }
                BigDecimal detailRefundAmount = orderDetail.getFinalPrice().multiply(new BigDecimal(detailParam.getQuantity()));
                refundAmount = refundAmount.add(detailRefundAmount);
                orderDetail.setRefundAmount(detailRefundAmount.add(orderDetail.getRefundAmount()));
                orderDetail.setRefundNum(detailParam.getQuantity() + orderDetail.getRefundNum());
                if(orderDetail.getRefundNum().equals(orderDetail.getQuantity())){
                    orderDetail.setDetailState(OrderDetailStateEnum.REFUNDED.getKey());
                }else {
                    orderDetail.setDetailState(OrderDetailStateEnum.PART_REFUND.getKey());
                }
                orderDetail.setUpdateBy(SecurityUtils.getUsername());
                orderDetailService.updateOrderDetail(orderDetail);
                OrderDetail inventoryOrderDetail = new OrderDetail();
                BeanUtils.copyProperties(orderDetail, inventoryOrderDetail);
                inventoryOrderDetail.setQuantity(detailParam.getQuantity());
                orderRefundDetailList.add(inventoryOrderDetail);
                DeviceRefundOrderDetailBO orderDetailBO = new DeviceRefundOrderDetailBO();
                orderDetailBO.setQuantity(detailParam.getQuantity());
                orderDetailBO.setGoodsId(orderDetail.getGoodsId());
                deviceRefundOrderDetailList.add(orderDetailBO);
            }
            OrderInfo refundOrderInfo = new OrderInfo();
            refundOrderInfo.setOrderId(param.getOrderId());
            refundOrderInfo.setRefundAmount(refundAmount.add(orderInfo.getRefundAmount()));
            if(orderInfo.getRealAmount().equals(refundOrderInfo.getRefundAmount())){
                refundOrderInfo.setOrderRefundState(OrderRefundStateEnum.FINISH.getKey());
                refundOrderInfo.setOrderState(OrderStateEnum.CANCEL.getKey());
            }else {
                refundOrderInfo.setOrderRefundState(OrderRefundStateEnum.PART_SUCC.getKey());
                refundOrderInfo.setOrderState(OrderStateEnum.Part_REFUND.getKey());
            }
            refundOrderInfo.setUpdateBy(SecurityUtils.getUsername());
            refundOrderInfo.setUpdateTime(DateUtils.getNowDate());
            orderInfoMapper.updateOrderInfo(refundOrderInfo);
            log.info("[部分退款]：订单id: {}, 退款金额：{}", param.getOrderId(), refundAmount);
            TradeAndWalletInfo tradeAndWalletInfo = accTradeList.stream()
                    .filter(trade -> PayStateEnum.PAY_SUCC.getKey().equals(trade.getPayState())
                            && AccWalletTypeEnum.WALLET.getKey().equals(trade.getWalletType()))
                    .findFirst().orElse(null);
            TradeAndWalletInfo tradeAndSubsidyInfo = accTradeList.stream()
                    .filter(trade -> PayStateEnum.PAY_SUCC.getKey().equals(trade.getPayState())
                            && AccWalletTypeEnum.SUBSIDY.getKey().equals(trade.getWalletType()))
                    .findFirst().orElse(null);
            if(Objects.nonNull(tradeAndWalletInfo)) {
                log.info("[部分退款]：订单id: {}, 个人钱包支付金额：{}", param.getOrderId(), tradeAndWalletInfo.getActualAmount());
                if(tradeAndWalletInfo.getActualAmount().compareTo(refundAmount) >= 0) {
                    refundToWallet(param, refundAmount, orderInfo, tradeAndWalletInfo);
                }else {
                    refundToWallet(param, tradeAndWalletInfo.getActualAmount(), orderInfo, tradeAndWalletInfo);
                    if(Objects.nonNull(tradeAndSubsidyInfo)) {
                        log.info("[部分退款]：订单id: {}, 补贴钱包支付金额：{}", param.getOrderId(), tradeAndSubsidyInfo.getActualAmount());
                        refundToWallet(param, refundAmount.subtract(tradeAndWalletInfo.getActualAmount())
                                , orderInfo, tradeAndSubsidyInfo);
                    }
                }
            }else if(Objects.nonNull(tradeAndSubsidyInfo)) {
                log.info("[部分退款]：订单id: {}, 纯补贴钱包支付金额：{}", param.getOrderId(), tradeAndSubsidyInfo.getActualAmount());
                refundToWallet(param, refundAmount, orderInfo, tradeAndSubsidyInfo);
            }
        }else {
            throw new ServiceException("订单未支付");
        }
        if (CollUtil.isNotEmpty(orderRefundDetailList)) {
            addMenuDishSupplyNum(orderRefundDetailList);
        }
        return deviceRefundOrderDetailList;
    }

    private void refundToWallet(OrderPartRefundParam param, BigDecimal refundAmount
            , OrderInfo orderInfo, TradeAndWalletInfo tradeAndWalletInfo) {
        WalletUpdateDTO walletUpdateDTO = new WalletUpdateDTO();
        walletUpdateDTO.setAmount(refundAmount);
        walletUpdateDTO.setUserId(orderInfo.getUserId());
        walletUpdateDTO.setAccWalletTypeEnum(AccWalletTypeEnum.getEnum(tradeAndWalletInfo.getWalletType()));
        walletUpdateDTO.setAccTradeTypeEnum(AccTradeTypeEnum.CONSUME_REFUND);
        walletUpdateDTO.setPayChannelEnum(PayChannelEnum.ACC);
        walletUpdateDTO.setPayTypeEnum(PayTypeEnum.MEAL_CARD);
        walletUpdateDTO.setOrderNo(param.getOrderId());
        walletUpdateDTO.setDeviceSn(orderInfo.getDeviceSn());
        walletUpdateDTO.setOperationUser(SecurityUtils.getUsername());
        accWalletInfoService.addAccWalletBalance(walletUpdateDTO);
    }

    @Transactional(rollbackFor = {Exception.class})
    public boolean refund(String operationUser, OrderInfo orderInfo) {
        if(Objects.isNull(orderInfo)) {
            throw new ServiceException("订单不存在");
        }
        String refundKey = String.format(ORDER_REFUND_REDIS_KEY, orderInfo.getOrderId());
        if (!RedisUtil.setNx(refundKey, 1, 2)) {
            log.info("退单处理中：{}", refundKey);
            throw new ServiceException("退单处理中");
        }
        if(orderInfo.getOrderRefundState().equals(OrderRefundStateEnum.FINISH.getKey())) {
            throw new ServiceException("订单已退");
        }
        if(orderInfo.getOrderState().equals(OrderStateEnum.CANCEL.getKey())) {
            throw new ServiceException("订单已取消");
        }
        if(orderInfo.getOrderRefundState().equals(OrderRefundStateEnum.PART_SUCC.getKey())) {
            throw new ServiceException("已部分退单，不能再整单退");
        }
//        if(orderInfo.getOrderState().equals(OrderStateEnum.FINISH.getKey())) {
//            throw new ServiceException("订单已核销");
//        }
        List<OrderDetail> orderDetailList = null;
        boolean isSendMQ = false;
        if(PayStateEnum.PAY_SUCC.getKey().equals(orderInfo.getPayState())) {
            List<TradeAndWalletInfo> accTradeList = accTradeService.queryTradeAndWallerInfoByOrderNo
                    (String.valueOf(orderInfo.getOrderId()), AccTradeTypeEnum.CONSUME);
            if(CollUtil.isEmpty(accTradeList)) {
                throw new ServiceException("订单交易记录不存在");
            }
            BigDecimal refundAmount = BigDecimal.ZERO;
            for(TradeAndWalletInfo accTrade : accTradeList) {
                if(PayStateEnum.PAY_SUCC.getKey().equals(accTrade.getPayState())) {
                    WalletUpdateDTO walletUpdateDTO = new WalletUpdateDTO();
                    walletUpdateDTO.setAmount(accTrade.getActualAmount());
                    walletUpdateDTO.setUserId(orderInfo.getUserId());
                    walletUpdateDTO.setAccWalletTypeEnum(AccWalletTypeEnum.getEnum(accTrade.getWalletType()));
                    walletUpdateDTO.setAccTradeTypeEnum(AccTradeTypeEnum.CONSUME_REFUND);
                    walletUpdateDTO.setPayChannelEnum(PayChannelEnum.ACC);
                    walletUpdateDTO.setPayTypeEnum(PayTypeEnum.MEAL_CARD);
                    walletUpdateDTO.setOrderNo(orderInfo.getOrderId());
                    walletUpdateDTO.setDeviceSn(orderInfo.getDeviceSn());
                    walletUpdateDTO.setOperationUser(operationUser);
                    accWalletInfoService.addAccWalletBalance(walletUpdateDTO);
                    refundAmount = refundAmount.add(accTrade.getActualAmount());
                }
            }
            OrderInfo refundOrderInfo = new OrderInfo();
            refundOrderInfo.setOrderId(orderInfo.getOrderId());
            refundOrderInfo.setRefundAmount(refundAmount);
            refundOrderInfo.setOrderRefundState(OrderRefundStateEnum.FINISH.getKey());
            refundOrderInfo.setOrderState(OrderStateEnum.CANCEL.getKey());
            refundOrderInfo.setUpdateBy(StringUtils.isBlank(operationUser) ? SecurityUtils.getUsername() : operationUser);
            refundOrderInfo.setUpdateTime(DateUtils.getNowDate());
            orderInfoMapper.updateOrderInfo(refundOrderInfo);
            orderDetailList = orderInfo.getOrderDetailList();
            for(OrderDetail orderDetail : orderDetailList) {
                orderDetail.setRefundAmount(orderDetail.getRealAmount());
                orderDetail.setRefundNum(orderDetail.getQuantity());
                orderDetail.setDetailState(OrderDetailStateEnum.REFUNDED.getKey());
                orderDetail.setUpdateBy(StringUtils.isBlank(operationUser) ? SecurityUtils.getUsername() : operationUser);
                orderDetailService.updateOrderDetail(orderDetail);
            }
            isSendMQ = true;
        }else {
            OrderInfo refundOrderInfo = new OrderInfo();
            refundOrderInfo.setOrderId(orderInfo.getOrderId());
            refundOrderInfo.setOrderRefundState(OrderRefundStateEnum.FINISH.getKey());
            refundOrderInfo.setOrderState(OrderStateEnum.CANCEL.getKey());
            refundOrderInfo.setUpdateBy(StringUtils.isBlank(operationUser) ? SecurityUtils.getUsername() : operationUser);
            refundOrderInfo.setUpdateTime(DateUtils.getNowDate());
            orderInfoMapper.updateOrderInfo(refundOrderInfo);
            OrderDetail orderDetailQuery = new OrderDetail();
            orderDetailQuery.setOrderId(orderInfo.getOrderId());
            orderDetailList = orderDetailService.selectOrderDetailList(orderDetailQuery);
        }
        if (orderDetailList != null) {
            addMenuDishSupplyNum(orderDetailList);
        }
        return isSendMQ;
    }
}
