
package com.tmerclub.cloud.order.controller.admin;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.tmerclub.cloud.api.delivery.dto.ChangeOrderAddrDTO;
import com.tmerclub.cloud.api.delivery.dto.DeliveryOrderDTO;
import com.tmerclub.cloud.api.delivery.dto.DeliveryOrderItemDTO;
import com.tmerclub.cloud.api.feign.EsOrderFeignClient;
import com.tmerclub.cloud.api.multishop.feign.ShopRefundAddrFeignClient;
import com.tmerclub.cloud.api.multishop.feign.ShopWalletFeignClient;
import com.tmerclub.cloud.api.order.constant.OrderStatus;
import com.tmerclub.cloud.api.payment.constant.PayEntry;
import com.tmerclub.cloud.api.payment.constant.PaySysType;
import com.tmerclub.cloud.api.payment.dto.PayInfoApiDto;
import com.tmerclub.cloud.api.payment.feign.PaymentFeignClient;
import com.tmerclub.cloud.api.product.feign.ProductFeignClient;
import com.tmerclub.cloud.api.product.feign.SkuFeignClient;
import com.tmerclub.cloud.api.product.feign.SpuFeignClient;
import com.tmerclub.cloud.api.supplier.bo.SupplierDetailBO;
import com.tmerclub.cloud.api.supplier.feign.SupplierDetailFeignClient;
import com.tmerclub.cloud.api.supplier.vo.SupplierApiDetailVO;
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.constant.PayType;
import com.tmerclub.cloud.common.constant.SendTypeEnum;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.leaf.manager.SegmentManager;
import com.tmerclub.cloud.common.order.constant.DeliveryType;
import com.tmerclub.cloud.common.order.constant.OrderActivityType;
import com.tmerclub.cloud.common.order.constant.RefundStatusEnum;
import com.tmerclub.cloud.common.order.dto.OrderSearchDTO;
import com.tmerclub.cloud.common.order.vo.*;
import com.tmerclub.cloud.common.product.constant.PreSaleType;
import com.tmerclub.cloud.common.product.constant.SupplierDeliveryType;
import com.tmerclub.cloud.common.product.vo.SkuAddrVO;
import com.tmerclub.cloud.common.product.vo.SpuVO;
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.delivery.manager.DeliveryManager;
import com.tmerclub.cloud.order.constant.Constant;
import com.tmerclub.cloud.order.dto.OrderAddrDTO;
import com.tmerclub.cloud.order.dto.multishop.OrderAdminDTO;
import com.tmerclub.cloud.order.dto.multishop.OrderChangeAddrDTO;
import com.tmerclub.cloud.order.listener.OrderExcelListener;
import com.tmerclub.cloud.order.model.Order;
import com.tmerclub.cloud.order.model.OrderAddr;
import com.tmerclub.cloud.order.model.OrderItem;
import com.tmerclub.cloud.order.service.*;
import com.tmerclub.cloud.order.service.*;
import com.tmerclub.cloud.order.vo.UnDeliveryOrderExcelVO;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.rocketmq.client.producer.SendStatus;
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.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

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

/**
 * @author tmerclub on 2018/09/15.
 */
@RestController("adminOrderController")
@RequestMapping("/mp/order")
public class OrderController {

    @Autowired
    private OrderService orderService;
    @Autowired
    private SegmentManager segmentManager;
    @Autowired
    private OrderPreSaleInfoService orderPreSaleInfoService;
    @Autowired
    private OrderExcelService orderExcelService;
    @Autowired
    private OrderAddrService orderAddrService;
    @Autowired
    private DeliveryManager deliveryManager;
    @Autowired
    private OrderItemService orderItemService;
    @Autowired
    private OrderSelfStationService orderSelfStationService;
    @Autowired
    private OrderRefundService orderRefundService;
    @DubboReference
    private UserFeignClient userFeignClient;
    @DubboReference
    private ShopWalletFeignClient shopWalletFeignClient;
    @DubboReference
    private ProductFeignClient productFeignClient;
    @DubboReference
    private SupplierDetailFeignClient supplierDetailFeignClient;
    @DubboReference
    private SpuFeignClient spuFeignClient;
    @DubboReference
    private SkuFeignClient skuFeignClient;
    @DubboReference
    private EsOrderFeignClient esOrderFeignClient;
    @DubboReference
    private PaymentFeignClient paymentFeignClient;
    @DubboReference
    private ShopRefundAddrFeignClient shopRefundAddrFeignClient;
    @Autowired
    private RocketMQTemplate sendNotifyToShopTemplate;

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


    /**
     * 分页获取
     */
    @GetMapping("/page")
    public ServerResponseEntity<EsPageVO<EsOrderVO>> page(OrderSearchDTO orderSearchDTO) {
        if (Objects.equals(orderSearchDTO.getStatus(), OrderStatus.PAYED.value())) {
            orderSearchDTO.setWaitPurchase(0);
        }
        orderSearchDTO.setShopId(AuthUserContext.get().getTenantId());
        if (Objects.equals(orderSearchDTO.getStatus(), Constant.WAIT_PURCHASES_STATUS)) {
            orderSearchDTO.setStatus(OrderStatus.PAYED.value());
            orderSearchDTO.setWaitPurchase(1);
        }
        EsPageVO<EsOrderVO> orderPage = orderService.orderPage(orderSearchDTO);
        List<Long> userIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        List<Long> supplierIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (EsOrderVO esOrderVO : orderPage.getList()) {
            userIds.add(esOrderVO.getUserId());
            supplierIds.add(esOrderVO.getSupplierId());
        }
        List<UserApiVO> userList = userFeignClient.getUserByUserIds(userIds).getData();
        Map<Long, String> userMap = userList.stream().collect(Collectors.toMap(UserApiVO::getUserId, UserApiVO::getNickName));
        List<SupplierApiDetailVO> shopDetailList = supplierDetailFeignClient.listBySupplierIds(supplierIds).getData();
        Map<Long, String> supplierMobileMap = shopDetailList.stream().collect(Collectors.toMap(SupplierApiDetailVO::getSupplierId, SupplierApiDetailVO::getContactPhone));
        // 处理下发货完成时能否修改物流
        for (EsOrderVO esOrderVO : orderPage.getList()) {
            if (!Objects.equals(esOrderVO.getSupplierId(), 0L) && supplierMobileMap.containsKey(esOrderVO.getSupplierId())) {
                esOrderVO.setSupplierMobile(supplierMobileMap.get(esOrderVO.getSupplierId()));
            }
            esOrderVO.setUserName(null == userMap.get(esOrderVO.getUserId()) ? "*用户已注销*" : userMap.get(esOrderVO.getUserId()));
            esOrderVO.setIsWriteOff(Objects.isNull(userMap.get(esOrderVO.getUserId())));
            // 处理赠品列表
            Map<Long, List<EsOrderItemVO>> giveawayMap = esOrderVO.getOrderItems().stream().filter(orderItemVO -> Objects.equals(orderItemVO.getActivityType(), OrderActivityType.GIVEAWAY.value()))
                    .collect(Collectors.groupingBy(EsOrderItemVO::getActivityId));
            // 处理组合列表
            Map<Long, List<EsOrderItemVO>> comboMap = esOrderVO.getOrderItems().stream().filter(orderItemVO -> Objects.equals(orderItemVO.getActivityType(), OrderActivityType.COMBO_PROD.value()))
                    .collect(Collectors.groupingBy(EsOrderItemVO::getActivityId));
            if (MapUtil.isNotEmpty(giveawayMap) || MapUtil.isNotEmpty(comboMap)) {
                Iterator<EsOrderItemVO> iterator = esOrderVO.getOrderItems().iterator();
                while (iterator.hasNext()) {
                    EsOrderItemVO orderItem = iterator.next();
                    if (Objects.equals(orderItem.getActivityType(), OrderActivityType.GIVEAWAY.value()) || Objects.equals(orderItem.getActivityType(), OrderActivityType.COMBO_PROD.value())) {
                        iterator.remove();
                    }
                    orderItem.setGiveawayList(giveawayMap.get(orderItem.getOrderItemId()));
                    orderItem.setComboList(comboMap.get(orderItem.getOrderItemId()));
                }
            }

            if (StrUtil.isNotBlank(esOrderVO.getMobile())) {
                esOrderVO.setMobile(PhoneUtil.hideBetween(esOrderVO.getMobile()).toString());
            }
            int updateOrViewDeliveryInfo = 0;
            if (!Objects.equals(esOrderVO.getStatus(), OrderStatus.CONSIGNMENT.value()) ||
                    !Objects.equals(esOrderVO.getDeliveryType(), DeliveryType.DELIVERY.value())) {
                continue;
            }
            for (EsOrderItemVO orderItem : esOrderVO.getOrderItems()) {
                if (Objects.nonNull(orderItem.getDeliveryType()) && Objects.equals(orderItem.getDeliveryType(), DeliveryType.DELIVERY.value())) {
                    updateOrViewDeliveryInfo = 1;
                    break;
                }
            }
            esOrderVO.setUpdateOrViewDeliveryInfo(updateOrViewDeliveryInfo);
        }
        return ServerResponseEntity.success(orderPage);
    }

    /**
     * 获取信息
     */
    @GetMapping("/orderInfo/{orderId}")
    public ServerResponseEntity<OrderVO> info(@PathVariable("orderId") Long orderId) {
        // 订单和订单项
        Order order = orderService.getOrderAndOrderItemData(orderId, AuthUserContext.get().getTenantId());
        logger.info("获取订单和订单项信息：{}", order.toString());
        // 详情用户收货地址
        OrderAddr orderAddr = orderAddrService.getById(order.getOrderAddrId());
        order.setOrderAddr(BeanUtil.map(orderAddr, OrderAddr.class));
        OrderVO orderVO = BeanUtil.map(order, OrderVO.class);
        if (Objects.nonNull(orderVO.getOrderAddr()) && StrUtil.isNotBlank(orderVO.getOrderAddr().getMobile())) {
            orderVO.getOrderAddr().setMobile(PhoneUtil.hideBetween(orderVO.getOrderAddr().getMobile()).toString());
        }
        orderService.getReturnOrderStatus(orderVO);
        // 处理下赠品
        List<OrderItemVO> orderItemDbList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 获取赠品map
        Map<Long, List<OrderItemVO>> giveawayMap = orderVO.getOrderItems().stream().filter(item -> Objects.equals(item.getActivityType(), OrderActivityType.GIVEAWAY.value()))
                .collect(Collectors.groupingBy(OrderItemVO::getActivityId));
        // 获取组合map
        Map<Long, List<OrderItemVO>> comboMap = orderVO.getOrderItems().stream().filter(item -> Objects.equals(item.getActivityType(), OrderActivityType.COMBO_PROD.value()))
                .collect(Collectors.groupingBy(OrderItemVO::getActivityId));
        for (OrderItemVO orderItem : orderVO.getOrderItems()) {
            // 赠品订单项不需要进行处理
            if (Objects.equals(orderItem.getActivityType(), OrderActivityType.GIVEAWAY.value()) || Objects.equals(orderItem.getActivityType(), OrderActivityType.COMBO_PROD.value())) {
                continue;
            }
            // 放入赠品
            if (giveawayMap.containsKey(orderItem.getOrderItemId())) {
                List<OrderItemVO> orderItemVOList = giveawayMap.get(orderItem.getOrderItemId());
                orderItem.setGiveawayList(orderItemVOList);
            }
            // 放入组合子商品项
            if (comboMap.containsKey(orderItem.getOrderItemId())) {
                List<OrderItemVO> orderItemVOList = comboMap.get(orderItem.getOrderItemId());
                orderItem.setComboItemList(orderItemVOList);
            }
            orderItemDbList.add(orderItem);
        }
        orderVO.setOrderItems(orderItemDbList);
        logger.info(orderVO.toString());
        // 补充自提点信息
        if (order.getDeliveryType() != null
                && DeliveryType.STATION.value().equals(order.getDeliveryType())) {
            OrderSelfStationVO stationVO = orderSelfStationService.getStationByOrderId(null, orderId);
            logger.info("获取自提点信息stationVO:{}", stationVO);
            orderVO.setOrderSelfStationVO(stationVO);
        }
        // 补充供应商信息
        Long supplierId = order.getSupplierId();
        if (supplierId == null || supplierId == 0L) {
            List<Long> supplierIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
            List<Long> spuIds = orderItemDbList.stream().map(OrderItemVO::getSpuId).collect(Collectors.toList());
            List<SpuVO> spuVOList = productFeignClient.listSpuBySpuIds(spuIds).getData();
            if (!CollectionUtils.isEmpty(spuVOList)) {
                supplierIds = spuVOList.stream().map(SpuVO::getSupplierId).filter(Objects::nonNull).collect(Collectors.toList());
            }
            if (!CollectionUtils.isEmpty(supplierIds)) {
                // 商品默认的供应商id是-1
                supplierId = supplierIds.get(0);
            }
        }
        if (supplierId != null
                && supplierId != 0L && supplierId != -1L) {
            SupplierDetailBO supplierDetailBO = supplierDetailFeignClient.getSupplierBySupplierId(supplierId).getData();
            logger.info("获取供应商信息supplierDetailBO:{}", supplierDetailBO);
            if (supplierDetailBO != null) {
                orderVO.setSupplierId(supplierDetailBO.getSupplierId());
                orderVO.setSupplierName(supplierDetailBO.getSupplierName());
                orderVO.setSupplierMobile(supplierDetailBO.getContactPhone());
            }
        }
        // 预售订单获取预售信息
        if (Objects.nonNull(order.getPreSaleType()) && !Objects.equals(order.getPreSaleType(), PreSaleType.DISABLE.value())) {
            OrderPreSaleInfoVO orderPreSaleInfo = orderPreSaleInfoService.getByOrderId(order.getOrderId());
            logger.info("获取预售信息orderPreSaleInfo:{}", orderPreSaleInfo);
            orderVO.setPayTime(orderPreSaleInfo.getBalancePayTime());
            orderVO.setOrderPreSaleInfoVO(orderPreSaleInfo);
        }
        //套餐优惠金额
        for (OrderItemVO orderItem : orderVO.getOrderItems()) {
            if (Objects.isNull(orderItem.getComboAmount())) {
                continue;
            }
            orderItem.setShareReduce(orderItem.getShareReduce() + orderItem.getComboAmount());
        }
        return ServerResponseEntity.success(orderVO);
    }

    /**
     * 获取订单用户下单地址
     */
    @GetMapping("/order_addr/{orderAddrId}")
    public ServerResponseEntity<OrderAddrVO> getOrderAddr(@PathVariable("orderAddrId") Long orderAddrId) {
        OrderAddr orderAddr = orderAddrService.getById(orderAddrId);
        return ServerResponseEntity.success(BeanUtil.map(orderAddr, OrderAddrVO.class));
    }

    /**
     * 订单项待发货数量查询
     */
    @GetMapping("/order_item_and_address/{orderId}")
    public ServerResponseEntity<OrderVO> getOrderItemAndAddress(@PathVariable("orderId") Long orderId) {
        // 订单和订单项
        Order order = orderService.getOrderAndOrderItemData(orderId, AuthUserContext.get().getTenantId());
        OrderVO orderVO = BeanUtil.map(order, OrderVO.class);
        List<OrderItemVO> orderItems = orderVO.getOrderItems();
        for (OrderItemVO orderItem : orderItems) {
            orderItem.setChangeNum(orderItem.getBeDeliveredNum() != -1 ? orderItem.getBeDeliveredNum() : orderItem.getCount());
        }
        // 用户收货地址
        OrderAddr orderAddr = orderAddrService.getById(order.getOrderAddrId());
        OrderAddrVO orderAddrVO = BeanUtil.map(orderAddr, OrderAddrVO.class);
        orderVO.setOrderAddr(orderAddrVO);
        return ServerResponseEntity.success(orderVO);
    }

    /**
     * 发货
     */
    @PostMapping("/delivery")
    public ServerResponseEntity<Void> delivery(@Valid @RequestBody DeliveryOrderDTO deliveryOrderParam) {
        // TODO 检查发货数量
        Order order = orderService.getOrderAndOrderItemData(deliveryOrderParam.getOrderId(), AuthUserContext.get().getTenantId());
        logger.info("获取订单信息order:{}", order);
        if (Objects.isNull(order)) {
            return ServerResponseEntity.fail(ResponseEnum.UNAUTHORIZED);
        }
        // 订单不在支付状态
        if (!Objects.equals(order.getStatus(), OrderStatus.PAYED.value())) {
            return ServerResponseEntity.showFailMsg("该订单状态异常");
        }
        // 订单不在支付状态
        if (Objects.equals(order.getWaitPurchase(), 1)) {
            return ServerResponseEntity.showFailMsg("该订单状态异常");
        }
        List<DeliveryOrderItemDTO> selectOrderItems = deliveryOrderParam.getSelectOrderItems();
        if (CollUtil.isEmpty(selectOrderItems)) {
            return ServerResponseEntity.showFailMsg("请至少选择一个订单项进行发货操作");
        }
        Map<Long, OrderItem> orderItemMap = order.getOrderItems().stream().collect(Collectors.toMap(OrderItem::getOrderItemId, orderItem -> orderItem));
        for (DeliveryOrderItemDTO selectOrderItem : selectOrderItems) {
            if (!orderItemMap.containsKey(selectOrderItem.getOrderItemId())) {
                throw new LuckException("该订单项不存在");
            }
            OrderItem orderItem = orderItemMap.get(selectOrderItem.getOrderItemId());
            if (orderItem.getBeDeliveredNum() < selectOrderItem.getChangeNum()) {
                throw new LuckException("订单项可发货数量不足,请刷新后重试");
            }
        }
        orderService.delivery(deliveryOrderParam);
        esOrderFeignClient.updateOrder(deliveryOrderParam.getOrderId());
        return ServerResponseEntity.success();
    }

    /**
     * 采购订单
     */
    @PutMapping("/sourcing_order")
    public ServerResponseEntity<?> sourcingOrder(@Valid @RequestBody OrderAdminDTO orderDTO) {
        Long tenantId = AuthUserContext.get().getTenantId();
        Order order = orderService.getOrderAndOrderItemData(orderDTO.getOrderId(), tenantId);
        if (Objects.isNull(order)) {
            return ServerResponseEntity.fail(ResponseEnum.UNAUTHORIZED);
        }
        // 订单不在支付状态
        if (!Objects.equals(order.getStatus(), OrderStatus.PAYED.value())) {
            return ServerResponseEntity.showFailMsg("订单状态异常");
        }
        boolean hasRefund = !Objects.isNull(order.getRefundStatus())
                && !Objects.equals(order.getRefundStatus(), RefundStatusEnum.DISAGREE.value())
                && !Objects.equals(order.getRefundStatus(), RefundStatusEnum.PARTIAL_SUCCESS.value());
        // 订单退款中，不能进行采购操作
        if (hasRefund) {
            return ServerResponseEntity.showFailMsg("订单退款中，不能进行采购操作");
        }
        // 检查商家结算金额是否足够
        ServerResponseEntity<Long> amountResp = shopWalletFeignClient.getSettlementAmountByShopId(order.getShopId(), order.getPaySysType());
        if (!amountResp.isSuccess()) {
            logger.info("获取商家结算金额失败，msg:{}", amountResp.getMsg());
            throw new LuckException(amountResp.getMsg());
        }
        if (amountResp.getData() < order.getPurchaseSpreadAmount()) {
            return ServerResponseEntity.showFailMsg("商家余额不足，请充值！");
        }
        // 发送用户支付消息给供应商
        this.sendPurchaseMsg(order);
        // 如果订单是通联支付的，执行商家余额扣除，让商家跳转到通联输入支付密码等校验
        if (Objects.equals(order.getPaySysType(), PaySysType.ALLINPAY.value())) {
            logger.info("订单是通联支付的，执行商家余额扣除，让商家跳转到通联输入支付密码等校验");
            return allinPayBalancePay(order, tenantId, orderDTO.getReturnUrl());
        }
        // 执行金额扣除
        orderService.sourcingOrder(order);
        return ServerResponseEntity.success();
    }

    private ServerResponseEntity<?> allinPayBalancePay(Order order, Long tenantId, String returnUrl) {
        PayInfoApiDto orderPayInfoVO = new PayInfoApiDto();
        orderPayInfoVO.setBody("商家余额支付订单");
        orderPayInfoVO.setPayAmount(order.getPurchaseSpreadAmount());
        orderPayInfoVO.setPayType(PayType.BALANCE.value());
        orderPayInfoVO.setOrderIds(order.getOrderId().toString());
        orderPayInfoVO.setReturnUrl(returnUrl);
        orderPayInfoVO.setPayEntry(PayEntry.SHOP_BALANCE_PAY_PURCHASE.value());
        orderPayInfoVO.setUserId(order.getUserId().toString());
        orderPayInfoVO.setBizUserId(order.getSupplierId().toString());
        orderPayInfoVO.setShopId(tenantId.toString());
        return paymentFeignClient.doAllinPayShopBalance(orderPayInfoVO);
    }

    /**
     * 修改订单金额
     */
    @PutMapping("/change_amount")
    public ServerResponseEntity<Void> changeAmount(@RequestBody OrderAdminDTO orderAdminDTO) {
        Long minFreightAmount = 0L;
        if (Objects.isNull(orderAdminDTO.getFreightAmount())) {
            orderAdminDTO.setFreightAmount(minFreightAmount);
        } else if (orderAdminDTO.getFreightAmount() < minFreightAmount) {
            throw new LuckException("运费不能小于零");
        }
        Order dbOrder = orderService.getOrderAndOrderItemData(orderAdminDTO.getOrderId(), AuthUserContext.get().getTenantId());
        if (Objects.equals(dbOrder.getPreSaleType(), PreSaleType.DEPOSIT.value())) {
            logger.info("修改预售订单金额");
            orderService.changeAmountByPreSale(orderAdminDTO, dbOrder);
        } else {
            logger.info("修改普通订单金额");
            orderService.changeAmount(orderAdminDTO, dbOrder);
        }
        esOrderFeignClient.updateOrder(orderAdminDTO.getOrderId());
        return ServerResponseEntity.success();
    }

    @GetMapping("/get_change_amount")
    @Operation(summary = "查询修改订单地址后的运费")
    public ServerResponseEntity<Double> getChangeAmount(OrderChangeAddrDTO param) {
        Order dbOrder = orderService.getOrderAndOrderItemData(param.getOrderId(), AuthUserContext.get().getTenantId());
        if (dbOrder.getStatus() > OrderStatus.PAYED.value() && !Objects.equals(dbOrder.getStatus(), OrderStatus.WAIT_GROUP.value())) {
            throw new LuckException("该订单状态异常，无法更改订单地址");
        }
        List<OrderItem> orderItems = orderItemService.listOrderItemsByOrderId(dbOrder.getOrderId());
        if (CollectionUtils.isEmpty(orderItems)) {
            throw new LuckException("数据异常，订单商品信息未找到");
        }
        Set<Long> spuIds = new HashSet<>(Constant.INITIAL_CAPACITY);
        List<Long> skuIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        orderItems.forEach(item -> {
            spuIds.add(item.getSpuId());
            skuIds.add(item.getSkuId());
        });
        // 查询spu
        ServerResponseEntity<List<SpuVO>> spuResp = spuFeignClient.listSpuBySpuIds(new ArrayList<>(spuIds));
        if (!spuResp.isSuccess()) {
            throw new LuckException(spuResp.getMsg());
        }
        List<SpuVO> spuVOList = spuResp.getData();
        Map<Long, SpuVO> spuMap = spuVOList.stream().collect(Collectors.toMap(SpuVO::getSpuId, spu -> spu));
        // 查询sku
        ServerResponseEntity<List<SkuAddrVO>> responseEntity = skuFeignClient.listSpuDetailByIds(skuIds);
        if (!responseEntity.isSuccess()) {
            throw new LuckException(responseEntity.getMsg());
        }
        List<SkuAddrVO> skuList = responseEntity.getData();
        Map<Long, SkuAddrVO> skuMap = skuList.stream().collect(Collectors.toMap(SkuAddrVO::getSkuId, s -> s));
        // 构建shopCartItemVO类
        List<ShopCartItemVO> shopCartItems = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (OrderItem orderItem : dbOrder.getOrderItems()) {
            //如果是赠品或者子组合商品则不需要处理运费
            if (Objects.equals(orderItem.getActivityType(), OrderActivityType.GIVEAWAY.value()) || Objects.equals(orderItem.getActivityType(), OrderActivityType.COMBO_PROD.value())) {
                continue;
            }
            SpuVO spu = spuMap.get(orderItem.getSpuId());
            SkuAddrVO sku = skuMap.get(orderItem.getSkuId());
            ShopCartItemVO shopCartItem = new ShopCartItemVO();
            shopCartItem.setSkuId(orderItem.getSkuId());
            shopCartItem.setSpuId(orderItem.getSpuId());
            shopCartItem.setCount(orderItem.getCount());
            shopCartItem.setShopId(orderItem.getShopId());
            shopCartItem.setTotalAmount(orderItem.getSpuTotalAmount());
            shopCartItem.setVolume(sku.getVolume());
            shopCartItem.setWeight(sku.getWeight());
            shopCartItem.setDeliveryTemplateId(spu.getDeliveryTemplateId());
            shopCartItem.setDeliveryAmount(spu.getDeliveryAmount());
            shopCartItem.setPreSaleType(spu.getPreSaleType());
            shopCartItems.add(shopCartItem);
        }
        UserAddrVO userAddrVO = new UserAddrVO();
        userAddrVO.setAreaId(param.getAreaId());
        if (Objects.equals(dbOrder.getDeliveryType(), DeliveryType.SAME_CITY.value())) {
            userAddrVO.setLat(param.getLat());
            userAddrVO.setLng(param.getLng());
        }
        ChangeOrderAddrDTO changeOrderAddrDTO = new ChangeOrderAddrDTO(shopCartItems, dbOrder.getFreightAmount(), userAddrVO, dbOrder.getDeliveryType());
        return ServerResponseEntity.success(deliveryManager.getOrderChangeAddrAmount(changeOrderAddrDTO));
    }

    /**
     * 修改用户订单地址
     *
     * @return 是否修改成功
     */
    @PutMapping("/change_user_addr")
    public ServerResponseEntity<Void> changeUserAddr(@RequestBody @Valid OrderAddrDTO orderAddrDTO) {
        Order orderDb = orderService.getByOrderId(orderAddrDTO.getOrderId());
        if (orderDb.getStatus() <= OrderStatus.PAYED.value() || Objects.equals(orderDb.getStatus(), OrderStatus.WAIT_GROUP.value())) {
            logger.info("修改订单地址");
            OrderAddr orderAddr = BeanUtil.map(orderAddrDTO, OrderAddr.class);
            orderAddrService.update(orderAddr);
        } else {
            throw new LuckException("该订单状态异常，无法更改订单地址");
        }
        return ServerResponseEntity.success();
    }

    /**
     * 修改订单备注
     *
     * @param order
     * @return 是否修改成功
     */
    @PutMapping("/change_order_remark")
    public ServerResponseEntity<Void> changeOrderRemark(@RequestBody @Valid Order order) {
        Order orderDb = orderService.getByOrderId(order.getOrderId());
        orderDb.setShopRemarks(order.getShopRemarks());
        orderService.update(orderDb);
        return ServerResponseEntity.success();
    }

    @GetMapping("/un_delivery_sold_excel")
    @Operation(summary = "导出待发货的订单excel")
    public ServerResponseEntity<Void> unDeliveryOrderSoldExcel(HttpServletResponse response, OrderSearchDTO orderSearchDTO) {
        orderSearchDTO.setShopId(AuthUserContext.get().getTenantId());
        orderSearchDTO.setSupplierDeliveryType(SupplierDeliveryType.SHOP_DELIVERY.value());
        orderSearchDTO.setStatus(OrderStatus.PAYED.value());
        // 只查询快递发货的订单
        orderSearchDTO.setDeliveryType(DeliveryType.DELIVERY.value());
        orderExcelService.excelUnDeliveryOrderList(response, orderSearchDTO);
        return ServerResponseEntity.success();
    }

    @PostMapping("/export_order_excel")
    @Operation(summary = "导入订单")
    public ServerResponseEntity<String> exportOrderExcel(@RequestParam("excelFile") MultipartFile file) {
        if (Objects.isNull(file)) {
            throw new LuckException("网络繁忙，请稍后再试");
        }
        String info;
        try {
            Map<Integer, List<String>> errorMap = new HashMap<>(10);
            EasyExcel.read(file.getInputStream(), UnDeliveryOrderExcelVO.class, new OrderExcelListener(orderExcelService, errorMap)).sheet().doRead();
            info = orderExcelService.orderExportError(errorMap);
        } catch (IOException e) {
            throw new LuckException(e.getMessage());
        }
        return ServerResponseEntity.success(info);
    }

    @GetMapping("/get_shop_order_by_userId")
    @Operation(summary = "分页获取某个用户的订单数据", description = "分页获取某个用户的订单数据")
    public ServerResponseEntity<EsPageVO<EsOrderVO>> getShopOrderByUserId(PageDTO pageDTO, String userId) {
        EsPageVO<EsOrderVO> pages = orderService.pageByUserId(pageDTO, userId);
        return ServerResponseEntity.success(pages);
    }

    /**
     * 发送采购消息
     * @param order 订单
     */
    private void sendPurchaseMsg(Order order) {
        // 采购后发送用户支付消息给供应商
        SendNotifyBO notifyBO = new SendNotifyBO();
        notifyBO.setSupplierId(order.getSupplierId());
        notifyBO.setBizId(order.getOrderId());
        notifyBO.setUserId(order.getUserId());
        notifyBO.setSupplierDeliveryType(order.getSupplierDeliveryType());
        notifyBO.setSendType(SendTypeEnum.USER_PAY_SUCCESS_TO_SUPPLIER.getValue());
        notifyBO.setMobile(order.getMobile());
        SendStatus sendStatus = sendNotifyToShopTemplate.syncSend(RocketMqConstant.SEND_NOTIFY_TO_SHOP_TOPIC, new GenericMessage<>(notifyBO)).getSendStatus();
        if (!Objects.equals(sendStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }
}
