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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import com.tmerclub.cloud.api.delivery.vo.DeliveryOrderFeignVO;
import com.tmerclub.cloud.api.feign.EsOrderFeignClient;
import com.tmerclub.cloud.api.multishop.feign.ShopDetailFeignClient;
import com.tmerclub.cloud.api.multishop.vo.ShopDetailVO;
import com.tmerclub.cloud.api.order.constant.OrderDeleteStatus;
import com.tmerclub.cloud.api.order.constant.OrderStatus;
import com.tmerclub.cloud.api.payment.dto.PayInfoApiDto;
import com.tmerclub.cloud.api.payment.feign.PaymentFeignClient;
import com.tmerclub.cloud.api.seckill.feign.SeckillFeignClient;
import com.tmerclub.cloud.api.vo.EsPageVO;
import com.tmerclub.cloud.config.WxConfig;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.constant.PayType;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.order.bo.EsOrderBO;
import com.tmerclub.cloud.common.order.constant.DeliveryType;
import com.tmerclub.cloud.common.order.constant.FlowSystemTypeEnum;
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.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.bo.OrderVirtualInfoLogBO;
import com.tmerclub.cloud.order.constant.RefundType;
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.vo.*;
import com.tmerclub.cloud.order.service.*;
import com.tmerclub.cloud.order.vo.OrderRefundVO;
import com.tmerclub.cloud.order.vo.OrderShopVO;
import com.tmerclub.cloud.order.vo.OrderVirtualInfoLogVO;
import com.tmerclub.cloud.order.vo.OrderWxDeliveryVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.rocketmq.client.producer.LocalTransactionState;
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.web.bind.annotation.*;

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

/**
 * 我的订单
 *
 * @author tmerclub
 */
@RestController
@RequestMapping("/my_order")
@Tag(name = "app-我的订单接口")
public class MyOrderController {

    private final Logger LOGGER = LoggerFactory.getLogger(MyOrderController.class);
    @Autowired
    private WxConfig wxConfig;
    @Autowired
    private OrderService orderService;
    @Autowired
    private DeliveryManager deliveryManager;
    @Autowired
    private OrderAddrService orderAddrService;
    @Autowired
    private OrderItemService orderItemService;
    @Autowired
    private OrderRefundService orderRefundService;
    @Autowired
    private RocketMQTemplate orderReceiptTemplate;
    @Autowired
    private OrderPreSaleInfoService orderPreSaleInfoService;
    @Autowired
    private OrderVirtualInfoService orderVirtualInfoService;
    @DubboReference
    private SeckillFeignClient seckillFeignClient;
    @DubboReference
    private EsOrderFeignClient esOrderFeignClient;
    @DubboReference
    private ShopDetailFeignClient shopDetailFeignClient;
    @DubboReference
    private PaymentFeignClient paymentFeignClient;


    /**
     * 订单详情信息接口
     */
    @GetMapping("/order_detail")
    @Operation(summary = "订单详情信息", description = "根据订单号获取订单详情信息")
    @Parameter(name = "orderId", description = "订单号", required = true)
    public ServerResponseEntity<OrderShopVO> orderDetail(@RequestParam("orderId") Long orderId) {
        Long userId = AuthUserContext.get().getUserId();
        Long stationId = AuthUserContext.get().getTenantId();
        OrderShopVO orderShopDto = new OrderShopVO();
        List<OrderItemVO> orderItems;
        Order order;
        // 查询一下redis有没有数据,因为秒杀订单还存在redis
        ServerResponseEntity<ShopCartOrderMergerVO> seckillOrderByRedisResp = seckillFeignClient.getSeckillOrderByRedis(orderId, userId);
        if (!seckillOrderByRedisResp.isSuccess()) {
            throw new LuckException(seckillOrderByRedisResp.getMsg());
        }
        ShopCartOrderMergerVO shopCartOrderMergerVO = seckillOrderByRedisResp.getData();
        // 查询一下redis有没有数据,因为秒杀订单还存在redis
        if (Objects.nonNull(shopCartOrderMergerVO)) {
            order = orderService.getOrderInfoByShopCartOrderMerger(shopCartOrderMergerVO);
            orderItems = BeanUtil.mapAsList(order.getOrderItems(), OrderItemVO.class);
        } else {
            if (Objects.isNull(stationId)) {
                LOGGER.info("非自提订单，用户id：{}，订单号：{}", userId, orderId);
                order = orderService.getOrderByOrderIdAndUserId(orderId, userId);
            } else {
                LOGGER.info("自提订单，用户id：{}，订单号：{}，站点id：{}", userId, orderId, stationId);
                order = orderService.getOrderByOrderIdAndStationId(orderId, stationId);
            }
            // 不是秒杀订单直接查询数据库
            OrderAddr orderAddr = orderAddrService.getById(order.getOrderAddrId());
            order.setOrderAddr(orderAddr);
            orderItems = orderItemService.listOrderItemAndLangByOrderId(orderId);
        }

        if (Objects.equals(order.getShopId(), Constant.PLATFORM_SHOP_ID)) {
            order.setShopName(Constant.PLATFORM_SHOP_NAME);
        }
        // 套餐优惠加到“促销满减”字段中
        if (Objects.nonNull(order.getShopComboAmount())) {
            order.setDiscountAmount(order.getShopComboAmount() + order.getDiscountAmount());
        }


        List<OrderRefundVO> orderRefunds = orderRefundService.listOrderRefundByOrderId(order.getOrderId());
        orderItems.forEach(orderItemVO -> orderItemVO.setFinalRefundId(null));
        long alreadyRefundAmount = 0L;
        for (OrderRefundVO orderRefund : orderRefunds) {
            alreadyRefundAmount = alreadyRefundAmount + orderRefund.getRefundAmount();
            // 整单退款
            if (Objects.equals(RefundType.ALL.value(), orderRefund.getRefundType())) {
                orderShopDto.setCanRefund(false);
                // 统一的退款单号
                for (OrderItemVO orderItemDto : orderItems) {
                    orderItemDto.setFinalRefundId(orderRefund.getRefundId());
                }
                break;
            }
            // 单项退款，每个单号都不一样
            for (OrderItemVO orderItemDto : orderItems) {
                if (Objects.equals(orderItemDto.getOrderItemId(), orderRefund.getOrderItemId())) {
                    orderItemDto.setFinalRefundId(orderRefund.getRefundId());
                }
            }
        }
        setOrderShopDto(orderShopDto, order,order.getOrderAddr(), orderItems);
        orderShopDto.setCanRefundAmount(order.getActualTotal() - alreadyRefundAmount);
        if (order.getRefundStatus() != null && !Objects.equals(order.getRefundStatus(), RefundStatusEnum.DISAGREE.value())) {
            orderShopDto.setFinalRefundId(orderItems.get(0).getFinalRefundId());
        }
        // 若订单为未支付状态，补充上订单自动取消时间
        if (Objects.equals(orderShopDto.getStatus(), OrderStatus.UNPAY.value())) {
            orderShopDto.setAutoCancelTime(new Date(orderShopDto.getCreateTime().getTime() + RocketMqConstant.CANCEL_TIME_INTERVAL));
        }
        // 处理虚拟订单
        if (Objects.equals(order.getOrderMold(), 1)) {
            LOGGER.info("处理虚拟订单，订单号：{}", order.getOrderId());
            List<OrderItem> orderItemList = BeanUtil.mapAsList(orderItems, OrderItem.class);
            order.setOrderItems(orderItemList);
            orderVirtualInfoService.handlerVirtualProdOrder(order, orderShopDto, stationId);
        }
        return ServerResponseEntity.success(orderShopDto);
    }

    @GetMapping("/order_count")
    @Operation(summary = "计算各个订单数量", description = "根据订单状态计算各个订单数量")
    public ServerResponseEntity<OrderCountVO> orderCount() {
        Long userId = AuthUserContext.get().getUserId();
        OrderCountVO orderCount = orderService.countNumberOfStatus(userId);
        // 计算一下当前用户秒杀订单中可能存在的数量
        ServerResponseEntity<OrderCountVO> countSeckillOrderResp = seckillFeignClient.countRedisSeckillOrder(userId);
        if (!countSeckillOrderResp.isSuccess()) {
            throw new LuckException(countSeckillOrderResp.getMsg());
        }
        if(Objects.nonNull(countSeckillOrderResp.getData())){
            OrderCountVO seckillOrderCount = countSeckillOrderResp.getData();
            orderCount.setUnPay(seckillOrderCount.getUnPay() + orderCount.getUnPay());
            orderCount.setPayed(seckillOrderCount.getPayed() + orderCount.getPayed());
        }
        return ServerResponseEntity.success(orderCount);
    }

    /**
     * 分页获取
     */
    @GetMapping("/search_order")
    @Operation(summary = "订单列表信息查询", description = "根据订单编号或者订单中商品名称搜索")
    public ServerResponseEntity<EsPageVO<EsOrderVO>> searchOrder(OrderSearchDTO orderSearchDTO) {
        Long userId = AuthUserContext.get().getUserId();
        orderSearchDTO.setUserId(userId);
        orderSearchDTO.setDeleteStatus(0);
        EsPageVO<EsOrderVO> esOrderPageVO = orderService.myOrderPage(orderSearchDTO);
        List<EsOrderVO> orderList = esOrderPageVO.getList();
        setShopName(orderList);
        boolean checkDeliveryNum = Objects.equals(orderSearchDTO.getStatus(), OrderStatus.PAYED.value()) || Objects.isNull(orderSearchDTO.getStatus());
        Map<Long, Integer> deliveryCountMap = new HashMap<>(16);
        if (checkDeliveryNum) {
            List<Long> orderIds = orderList.stream().map(EsOrderVO::getOrderId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(orderIds)) {
                List<DeliveryOrderFeignVO> deliveryOrderList = deliveryManager.listDeliveryCountByOrderIds(orderIds);
                deliveryCountMap = deliveryOrderList.stream().collect(Collectors.toMap(DeliveryOrderFeignVO::getOrderId, DeliveryOrderFeignVO::getAllCount));
            }
        }
        // 处理下发货完成时能否查看物流
        for (EsOrderVO esOrderVO : orderList) {
            if (Objects.equals(esOrderVO.getShopId(), Constant.PLATFORM_SHOP_ID)) {
                esOrderVO.setShopName(Constant.PLATFORM_SHOP_NAME);
            }
            int updateOrViewDeliveryInfo = 0;
            if (!Objects.equals(esOrderVO.getDeliveryType(), DeliveryType.DELIVERY.value()) && !Objects.equals(esOrderVO.getDeliveryType(), DeliveryType.ONLINE.value())) {
                esOrderVO.setUpdateOrViewDeliveryInfo(updateOrViewDeliveryInfo);
                continue;
            }
            for (EsOrderItemVO orderItem : esOrderVO.getOrderItems()) {
                boolean isDelivery = Objects.equals(orderItem.getDeliveryType(), DeliveryType.ONLINE.value()) || Objects.equals(orderItem.getDeliveryType(), DeliveryType.DELIVERY.value());
                if (Objects.nonNull(orderItem.getDeliveryType()) && isDelivery) {
                    updateOrViewDeliveryInfo = 1;
                    break;
                }
            }
            if (checkDeliveryNum) {
                if (deliveryCountMap.containsKey(esOrderVO.getOrderId())) {
                    esOrderVO.setDeliveryCount(deliveryCountMap.get(esOrderVO.getOrderId()));
                }
            }
            esOrderVO.setUpdateOrViewDeliveryInfo(updateOrViewDeliveryInfo);
        }


        for (EsOrderVO orderVO : orderList) {
            List<EsOrderItemVO> orderItems = orderVO.getOrderItems();
            Map<Long, List<EsOrderItemVO>> map = orderItems.stream()
                    .filter(order -> Objects.equals(order.getActivityType(), OrderActivityType.GIVEAWAY.value()))
                    .collect(Collectors.groupingBy(EsOrderItemVO::getActivityId));
            Map<Long, List<EsOrderItemVO>> comboMap = orderItems.stream()
                    .filter(order -> Objects.equals(order.getActivityType(), OrderActivityType.COMBO_PROD.value()))
                    .collect(Collectors.groupingBy(EsOrderItemVO::getActivityId));
            // 如果没有赠品，就不需要处理
            if (MapUtil.isEmpty(map) && MapUtil.isEmpty(comboMap)) {
                continue;
            }
            // 将赠品放到对应的主订单项中
            Iterator<EsOrderItemVO> iterator = orderItems.iterator();
            while (iterator.hasNext()) {
                EsOrderItemVO myOrderItemDto = iterator.next();
                // 移除赠品的订单项，进入下一个循环
                if (Objects.equals(myOrderItemDto.getActivityType(), OrderActivityType.GIVEAWAY.value()) || Objects.equals(myOrderItemDto.getActivityType(), OrderActivityType.COMBO_PROD.value())) {
                    iterator.remove();
                    continue;
                }
                // 主订单项插入赠品订单项
                if (map.containsKey(myOrderItemDto.getOrderItemId())) {
                    List<EsOrderItemVO> list = map.get(myOrderItemDto.getOrderItemId());
                    myOrderItemDto.setGiveawayList(list);
                }
                // 主订单项插入组合订单项
                if (comboMap.containsKey(myOrderItemDto.getOrderItemId())) {
                    List<EsOrderItemVO> list = comboMap.get(myOrderItemDto.getOrderItemId());
                    myOrderItemDto.setComboList(list);
                }
            }
        }
        return ServerResponseEntity.success(esOrderPageVO);
    }

    // todo 定时任务将订单项设为不可评论的状态

    /**
     * 订单评价列表接口
     */
    @GetMapping("/search_order_item")
    @Operation(summary = "订单评价列表接口", description = "根据订单评价状态获取订单列表信息")
    public ServerResponseEntity<EsPageVO<EsOrderVO>> searchOrderItem(PageDTO page) {

        OrderSearchDTO orderSearchDTO = new OrderSearchDTO();
        Long userId = AuthUserContext.get().getUserId();
        orderSearchDTO.setUserId(userId);
        orderSearchDTO.setPageNum(page.getPageNum());
        orderSearchDTO.setPageSize(page.getPageSize());
        orderSearchDTO.setStatus(OrderStatus.SUCCESS.value());
        orderSearchDTO.setDeleteStatus(OrderDeleteStatus.NOT_DELETE.value());
        EsPageVO<EsOrderVO> esOrderEsPage = orderService.orderPage(orderSearchDTO);
        for (EsOrderVO esOrderVO : esOrderEsPage.getList()) {
            Map<Long, List<EsOrderItemVO>> comboMap = esOrderVO.getOrderItems().stream()
                    .filter(order -> Objects.equals(order.getActivityType(), OrderActivityType.COMBO_PROD.value()))
                    .collect(Collectors.groupingBy(EsOrderItemVO::getActivityId));
            if (MapUtil.isEmpty(comboMap)) {
                continue;
            }
            Iterator<EsOrderItemVO> iterator = esOrderVO.getOrderItems().iterator();
            while (iterator.hasNext()) {
                EsOrderItemVO orderItem = iterator.next();
                if (Objects.equals(orderItem.getActivityType(), OrderActivityType.COMBO_PROD.value())) {
                    iterator.remove();
                }
                orderItem.setComboList(comboMap.get(orderItem.getOrderItemId()));
            }
            esOrderVO.setIsComm(esOrderVO.getOrderItems().get(0).getIsComm());
        }
        return ServerResponseEntity.success(esOrderEsPage);
    }

    /**
     * 取消订单
     */
    @PutMapping("/cancel/{orderId}")
    @Operation(summary = "根据订单号取消订单", description = "根据订单号取消订单")
    @Parameter(name = "orderId", description = "订单号", required = true)
    public ServerResponseEntity<String> cancel(@PathVariable("orderId") Long orderId) {
        Long userId = AuthUserContext.get().getUserId();
        ServerResponseEntity<ShopCartOrderMergerVO> serverResponseEntity = seckillFeignClient.getSeckillOrderByRedis(orderId, userId);
        if (!serverResponseEntity.isSuccess()) {
            throw new LuckException(serverResponseEntity.getMsg());
        }

        ShopCartOrderMergerVO shopCartOrderMergerVO = serverResponseEntity.getData();
        Integer orderStatus;
        if (Objects.nonNull(shopCartOrderMergerVO)) {
            orderStatus = shopCartOrderMergerVO.getStatus();
        } else {
            Order order = orderService.getOrderByOrderIdAndUserId(orderId, userId);
            orderStatus = order.getStatus();
        }
        boolean isPayed = Objects.nonNull(orderStatus) && !Objects.equals(orderStatus, OrderStatus.UNPAY.value()) && !Objects.equals(orderStatus, OrderStatus.CLOSE.value());
        if (isPayed) {
            // 订单已支付，无法取消订单
            return ServerResponseEntity.showFailMsg("订单已支付，无法取消订单");
        }
        // 如果订单未支付的话，将订单设为取消状态
        orderService.cancelOrderAndGetCancelOrderIds(shopCartOrderMergerVO,Collections.singletonList(orderId));
        return ServerResponseEntity.success();
    }


    /**
     * 确认收货
     */
    @PutMapping("/receipt/{orderId}")
    @Operation(summary = "根据订单号确认收货", description = "根据订单号确认收货")
    public ServerResponseEntity<String> receipt(@PathVariable("orderId") Long orderId) {
        Long userId = AuthUserContext.get().getUserId();
        Order order = orderService.getOrderByOrderIdAndUserId(orderId, userId);

        if (!Objects.equals(order.getStatus(), OrderStatus.CONSIGNMENT.value())) {
            if (Objects.equals(order.getStatus(), OrderStatus.SUCCESS.value())) {
                return ServerResponseEntity.showFailMsg("订单已收货，请刷新页面");
            } else {
                return ServerResponseEntity.showFailMsg("订单状态异常，请刷新后重试");
            }
        }
        if (Objects.equals(order.getRefundStatus(), RefundStatusEnum.APPLY.value())) {
            // 订单退款中，无法确认收货
            return ServerResponseEntity.showFailMsg("订单退款中，无法确认收货");
        }
        List<OrderItem> orderItems = orderItemService.listOrderItemsByOrderId(orderId);
        order.setOrderItems(orderItems);


        //注意：订单的确认收货是需要通知很多个服务的。
        // 在发送普通消息的时候，可能消息已经落地发送了，这边抛了异常，让数据回滚，变为未确认收货的状态，此时用户再点击退货，接着再次点击确认收货，
        // 而接收方确实是收到该消息，订单状态从 确认收货变成了“确认收货”，这两个确认收货的状态有本质的区别，所以应该让订单确确实实变为确认收货状态，再向各个服务推送消息
        // 因此用事务消息会比较好

        // 开启事务消息，通知订单自己，开始往各个服务发送通知了
        TransactionSendResult transactionSendResult = orderReceiptTemplate.sendMessageInTransaction(RocketMqConstant.ORDER_RECEIPT_TOPIC, new GenericMessage<>(orderId), null);

        if (!Objects.equals(transactionSendResult.getLocalTransactionState(), LocalTransactionState.COMMIT_MESSAGE)) {
            return ServerResponseEntity.fail(ResponseEnum.EXCEPTION);
        }
        esOrderFeignClient.updateOrder(orderId);
        return ServerResponseEntity.success();
    }

    /**
     * 删除订单
     */
    @DeleteMapping("/{orderId}")
    @Operation(summary = "根据订单号删除订单", description = "根据订单号删除订单")
    @Parameter(name = "orderId", description = "订单号", required = true)
    public ServerResponseEntity<String> delete(@PathVariable("orderId") Long orderId) {
        Long userId = AuthUserContext.get().getUserId();

        Order order = orderService.getOrderByOrderIdAndUserId(orderId, userId);

        if (!Objects.equals(order.getStatus(), OrderStatus.SUCCESS.value()) && !Objects.equals(order.getStatus(), OrderStatus.CLOSE.value())) {
            // 订单未完成或未关闭，无法删除订单
            return ServerResponseEntity.showFailMsg("订单未完成或未关闭，无法删除订单");
        }

        // 删除订单
        orderService.deleteOrder(order.getOrderId());
        esOrderFeignClient.updateOrder(orderId);
        return ServerResponseEntity.success();
    }

    @GetMapping("/get_order_item/{orderItemId}")
    @Operation(summary = "根据订单项id获取订单项详情", description = "根据订单项id获取订单项详情")
    @Parameter(name = "orderItemId", description = "订单项号", required = true)
    public ServerResponseEntity<OrderItemVO> getOrderItemById(@PathVariable("orderItemId") Long orderItemId) {
        Long userId = AuthUserContext.get().getUserId();
        OrderItemVO orderItemVO = orderItemService.getByOrderItemId(orderItemId);
        if (userId == null || orderItemVO == null || !userId.equals(orderItemVO.getUserId())) {
            return ServerResponseEntity.showFailMsg("订单项错误");
        }
        return ServerResponseEntity.success(orderItemVO);
    }

    @GetMapping("/getOrderStatus")
    @Operation(summary = "根据虚拟订单编号获取订单券码")
    public ServerResponseEntity<OrderShopVO> getOrderStatus(@RequestParam("orderId") Long orderId) {
        EsOrderBO esorder = orderService.getEsOrder(orderId);
        Order order = BeanUtil.map(esorder, Order.class);
        OrderShopVO orderShopVO = new OrderShopVO();
        orderShopVO.setStatus(order.getStatus());
        orderShopVO.setRefundStatus(order.getRefundStatus());
        // 如果是虚拟商品订单，处理下虚拟商品订单相关数据
        if (Objects.equals(order.getOrderMold(), 1)) {
            Long stationId = AuthUserContext.get().getTenantId();
            orderVirtualInfoService.handlerVirtualProdOrder(order, orderShopVO, stationId);
        }
        return ServerResponseEntity.success(orderShopVO);
    }

    @GetMapping("/get_by_order_id")
    @Operation(summary = "根据订单编号获取订单虚拟商品核销记录信息", description = "根据订单编号获取订单虚拟商品核销记录信息")
    @Parameter(name = "orderId", description = "订单编号", required = true)
    public ServerResponseEntity<OrderVirtualInfoLogVO> getByOrderId(@RequestParam("orderId") Long orderId) {
        return ServerResponseEntity.success(orderVirtualInfoService.getByOrderId(orderId));
    }

    @GetMapping("/get_by_write_off_code")
    @Operation(summary = "根据核销码获取订单虚拟商品核销记录信息", description = "根据核销码获取订单虚拟商品核销记录信息")
    @Parameter(name = "writeOffCode", description = "核销码", required = true)
    public ServerResponseEntity<List<OrderVirtualInfoLogBO>> getByWriteOffCode(@RequestParam("writeOffCode") String writeOffCode) {
        return ServerResponseEntity.success(orderVirtualInfoService.getByWriteOffCode(writeOffCode));
    }

    /**
     * 判断是否开启了小程序发货信息管理
     */
    @GetMapping("/check_trade_managed/{orderId}")
    @Operation(summary = "判断是否小程序下单并且开启了小程序发货信息管理", description = "判断是否小程序下单并且开启了小程序发货信息管理")
    public ServerResponseEntity<OrderWxDeliveryVO> checkTradeManaged(@PathVariable("orderId") Long orderId) {
        OrderWxDeliveryVO orderWxDeliveryVO = new OrderWxDeliveryVO();
        List<PayInfoApiDto> payInfoApiDtos = paymentFeignClient.getPayInfoByUserIdAndOrderId(AuthUserContext.get().getUserId(), orderId).getData();
        Boolean payFlag = false;
        PayInfoApiDto payInfoApiDto = new PayInfoApiDto();
        if (CollectionUtil.isNotEmpty(payInfoApiDtos)) {
            for (PayInfoApiDto payInfo : payInfoApiDtos) {
                // 判断是否是小程序购买
                if (Objects.equals(payInfo.getPayType(), PayType.WECHATPAY.value()) &&  Objects.equals(payInfo.getSystemModel(), FlowSystemTypeEnum.APPLETS.value())) {
                    payInfoApiDto = payInfo;
                    payFlag = true;
                    break;
                }
            }
        }
        if (payFlag) {
            // 查询小程序是否已开通发货信息管理服务
            Boolean managed = wxConfig.getTradeManaged();
            if (managed) {
                Integer orderStatus = wxConfig.getOrderStatusByBizPayNo(payInfoApiDto.getBizPayNo());
                if (orderStatus != 0) {
                    orderWxDeliveryVO.setOrderStatus(orderStatus);
                    orderWxDeliveryVO.setBizPayNo(payInfoApiDto.getBizPayNo());
                }
            }
        }
        return ServerResponseEntity.success(orderWxDeliveryVO);
    }


    /**
     * 插入数据
     *
     * @param orderShopDto 插入对象
     * @param order        订单信息
     * @param orderAddr    订单地址
     * @param orderItems   订单项列表
     */
    private void setOrderShopDto(OrderShopVO orderShopDto, Order order, OrderAddr orderAddr, List<OrderItemVO> orderItems) {
        // 处理下发货完成时能否查看物流
        int updateOrViewDeliveryInfo = 0;
        if (!Objects.equals(order.getDeliveryType(), DeliveryType.DELIVERY.value()) && !Objects.equals(order.getDeliveryType(), DeliveryType.ONLINE.value())) {
            orderShopDto.setUpdateOrViewDeliveryInfo(updateOrViewDeliveryInfo);
        }
        for (OrderItemVO orderItem : orderItems) {
            boolean canSee = Objects.equals(orderItem.getDeliveryType(), DeliveryType.DELIVERY.value()) || Objects.equals(orderItem.getDeliveryType(), DeliveryType.ONLINE.value());
            if (Objects.nonNull(orderItem.getDeliveryType()) && canSee) {
                updateOrViewDeliveryInfo = 1;
                break;
            }
        }
        getOrderShop(orderShopDto, order, orderAddr, updateOrViewDeliveryInfo);
        // 处理退款
        handleRefund(orderShopDto, order, orderItems);
        orderShopDto.setOrderItems(orderItems);
        orderShopDto.setTotal(order.getTotal());
        orderShopDto.setTotalNum(order.getAllCount());
        // 预售订单获取预售信息
        if (Objects.nonNull(order.getPreSaleType()) && !Objects.equals(order.getPreSaleType(), PreSaleType.DISABLE.value())) {
            OrderPreSaleInfoVO orderPreSaleInfo = orderPreSaleInfoService.getByOrderId(order.getOrderId());
            if (Objects.isNull(orderPreSaleInfo)) {
                // 秒杀订单还存在缓存中
                orderShopDto.setOrderPreSaleInfoVO(BeanUtil.map(order.getOrderPreSaleInfo(), OrderPreSaleInfoVO.class));
            } else {
                orderShopDto.setPayTime(Objects.equals(orderPreSaleInfo.getPreSaleType(), PreSaleType.DEPOSIT.value()) && Objects.equals(orderPreSaleInfo.getPayStatus(), 2) ? orderPreSaleInfo.getBalancePayTime() : order.getPayTime());
                orderShopDto.setOrderPreSaleInfoVO(orderPreSaleInfo);
            }
        }
        // 处理赠品订单项
        List<OrderItemVO> giveWayItems;
        List<OrderItemVO> comboItems;
        List<OrderItemVO> notGiveWayItems = new ArrayList<>(Constant.INITIAL_CAPACITY);
        Map<Long, List<OrderItemVO>> giveWayItemMap = new HashMap<>(Constant.INITIAL_CAPACITY);
        Map<Long, List<OrderItemVO>> comboItemMap = new HashMap<>(Constant.INITIAL_CAPACITY);
        for (OrderItemVO orderItem : orderItems) {
            if (Objects.equals(orderItem.getActivityType(), OrderActivityType.GIVEAWAY.value())) {
                giveWayItems = giveWayItemMap.getOrDefault(orderItem.getActivityId(), new ArrayList<>());
                giveWayItems.add(orderItem);
                giveWayItemMap.put(orderItem.getActivityId(), giveWayItems);
                continue;
            }else if(Objects.equals(orderItem.getActivityType(), OrderActivityType.COMBO_PROD.value())){
                comboItems = comboItemMap.getOrDefault(orderItem.getActivityId(), new ArrayList<>());
                comboItems.add(orderItem);
                comboItemMap.put(orderItem.getActivityId(), comboItems);
                continue;
            }
            notGiveWayItems.add(orderItem);
        }
        for (OrderItemVO notGiveWayItem : notGiveWayItems) {
            notGiveWayItem.setGiveawayList(giveWayItemMap.get(notGiveWayItem.getOrderItemId()));
            notGiveWayItem.setComboItemList(comboItemMap.get(notGiveWayItem.getOrderItemId()));
        }
        orderShopDto.setOrderItems(notGiveWayItems);
    }

    private void getOrderShop(OrderShopVO orderShopDto, Order order, OrderAddr orderAddr, int updateOrViewDeliveryInfo) {
        orderShopDto.setUpdateOrViewDeliveryInfo(updateOrViewDeliveryInfo);
        orderShopDto.setOrderScore(order.getOrderScore());
        orderShopDto.setShopId(order.getShopId());
        orderShopDto.setDeliveryType(order.getDeliveryType());
        orderShopDto.setShopName(order.getShopName());
        orderShopDto.setActualTotal(order.getActualTotal());
        orderShopDto.setOrderAddr(BeanUtil.map(orderAddr, OrderAddrVO.class));
        orderShopDto.setPayType(order.getPayType());
        orderShopDto.setTransfee(order.getFreightAmount());
        orderShopDto.setReduceAmount(Math.abs(order.getReduceAmount()));
        orderShopDto.setCreateTime(order.getCreateTime());
        orderShopDto.setRemarks(order.getRemarks());
        orderShopDto.setOrderType(order.getOrderType());
        orderShopDto.setStatus(order.getStatus());
        // 返回满减优惠金额，优惠券优惠金额和店铺优惠总额
        orderShopDto.setDiscountMoney(order.getDiscountAmount());
        orderShopDto.setShopCouponMoney(order.getShopCouponAmount());
        // TODO 暂时不需要显示店铺包邮金额
//        orderShopDto.setFreeFreightAmount(order.getFreeFreightAmount());
        long shopAmount = order.getReduceAmount() - order.getPlatformAmount() + order.getShopChangeFreeAmount();
        orderShopDto.setShopAmount(shopAmount);
        //返回平台优惠券，平台等级，平台积分优惠金额和平台免运费金额
        orderShopDto.setPlatformCouponAmount(order.getPlatformCouponAmount());
        orderShopDto.setMemberAmount(order.getMemberAmount());
        orderShopDto.setScoreAmount(order.getScoreAmount());
        orderShopDto.setPlatformFreeFreightAmount(order.getPlatformFreeFreightAmount());
        orderShopDto.setShopChangeFreeAmount(order.getShopChangeFreeAmount());
        // 付款时间
        orderShopDto.setPayTime(order.getPayTime());
        // 发货时间
        orderShopDto.setDeliveryTime(order.getDeliveryTime());
        // 完成时间
        orderShopDto.setFinallyTime(order.getFinallyTime());
        // 取消时间
        orderShopDto.setCancelTime(order.getCancelTime());
        // 更新时间
        orderShopDto.setUpdateTime(order.getUpdateTime());
        //订单发票id
        orderShopDto.setOrderInvoiceId(order.getOrderInvoiceId());
        orderShopDto.setOrderMold(order.getOrderMold());
        orderShopDto.setPreSaleType(order.getPreSaleType());
    }

    private void handleRefund(OrderShopVO orderShopDto, Order order, List<OrderItemVO> orderItems) {
        // 可以退款的状态，并在退款时间内
        if (order.getStatus() > OrderStatus.UNPAY.value() && order.getStatus() < OrderStatus.CLOSE.value() && orderRefundService.checkRefundDate(order)) {
            LOGGER.info("订单{}可以退款", order.getOrderId());
            orderShopDto.setCanRefund(true);
            orderShopDto.setCanAllRefund(true);
            for (OrderItemVO orderItem : orderItems) {
                // 有正在退款中的订单项
                if (orderItem.getRefundStatus() != null && !Objects.equals(orderItem.getRefundStatus(), RefundStatusEnum.DISAGREE.value())) {
                    // 无法整单退款
                    orderShopDto.setCanAllRefund(false);
                }
                // 有正在退款中/退款平台介入的订单项
                if (Objects.nonNull(orderItem.getFinalRefundId())) {
                    // 无法整单退款
                    orderShopDto.setCanAllRefund(false);
                }
                // 如果是虚拟商品订单，处理下虚拟商品订单相关数据
                if (Objects.equals(orderItem.getIsRefund(), 0)) {
                    orderShopDto.setCanAllRefund(false);
                    orderShopDto.setCanRefund(false);
                }
            }
            // 正在进行整单退款
            if (order.getRefundStatus() != null && !Objects.equals(order.getRefundStatus(), RefundStatusEnum.DISAGREE.value())) {
                // 所有订单项都没办法退款
                orderShopDto.setCanAllRefund(false);
            }
        }
        if (Objects.nonNull(order.getRefundStatus()) && !Objects.equals(order.getRefundStatus(), RefundStatusEnum.DISAGREE.value())) {
            List<OrderRefundVO> refundVOList = orderRefundService.listOrderRefundByOrderId(order.getOrderId());
            for (OrderRefundVO orderRefund : refundVOList) {
                //整单退款
                if (orderRefund.getRefundType() == 1) {
                    for (OrderItemVO orderItem : orderItems) {
                        orderItem.setReturnMoneySts(orderRefund.getReturnMoneySts());
                    }
                    break;
                }
                // 单项退款，每个单号都不一样
                for (OrderItemVO orderItem : orderItems) {
                    if (Objects.equals(orderItem.getOrderItemId(), orderRefund.getOrderItemId())) {
                        orderItem.setReturnMoneySts(orderRefund.getReturnMoneySts());
                    }
                }
            }
        }
    }




    private void setShopName(List<EsOrderVO> orderList) {
        // 店铺名称
        if (CollUtil.isNotEmpty(orderList)) {
            List<Long> shopIdList = orderList.stream().map(EsOrderVO::getShopId).collect(Collectors.toList());
            List<ShopDetailVO> shopDetailVOList = shopDetailFeignClient.listByShopIds(shopIdList).getData();
            Map<Long, List<ShopDetailVO>> shopDetailVoMap = shopDetailVOList.stream().collect(Collectors.groupingBy(ShopDetailVO::getShopId));
            for (EsOrderVO esOrderVO : orderList) {
                if (Objects.equals(esOrderVO.getShopId(), Constant.PLATFORM_SHOP_ID)) {
                    esOrderVO.setShopName(Constant.PLATFORM_SHOP_NAME);
                } else if (shopDetailVoMap.containsKey(esOrderVO.getShopId())) {
                    esOrderVO.setShopName(shopDetailVoMap.get(esOrderVO.getShopId()).get(0).getShopName());
                }
            }
        }
    }


}
