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

import cn.hutool.core.collection.CollectionUtil;
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.ShopDetailFeignClient;
import com.tmerclub.cloud.api.multishop.vo.ShopDetailVO;
import com.tmerclub.cloud.api.order.constant.OrderStatus;
import com.tmerclub.cloud.api.product.feign.SkuFeignClient;
import com.tmerclub.cloud.api.product.feign.SpuFeignClient;
import com.tmerclub.cloud.api.supplier.feign.SupplierRefundAddrFeignClient;
import com.tmerclub.cloud.api.vo.EsPageVO;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.order.constant.DeliveryType;
import com.tmerclub.cloud.common.order.constant.OrderActivityType;
import com.tmerclub.cloud.common.order.dto.OrderSearchDTO;
import com.tmerclub.cloud.common.order.vo.*;
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.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.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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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 2022/07/11.
 */
@RestController("supplierOrderController")
@RequestMapping("/s/order")
public class OrderController {

    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderExcelService orderExcelService;
    @Autowired
    private OrderAddrService orderAddrService;
    @Autowired
    private DeliveryManager deliveryManager;
    @DubboReference
    private SkuFeignClient skuFeignClient;
    @DubboReference
    private SpuFeignClient spuFeignClient;
    @Autowired
    private OrderItemService orderItemService;
    @DubboReference
    private EsOrderFeignClient esOrderFeignClient;
    @DubboReference
    private ShopDetailFeignClient shopDetailFeignClient;
    @Autowired
    private OrderRefundService orderRefundService;
    @DubboReference
    private SupplierRefundAddrFeignClient supplierRefundAddrFeignClient;

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

    /**
     * 分页获取
     */
    @GetMapping("/page")
    public ServerResponseEntity<EsPageVO<EsSupplierOrderVO>> page(OrderSearchDTO orderSearchDTO) {
        orderSearchDTO.setSupplierId(AuthUserContext.get().getTenantId());
        // 供应商只能看到采购完成且供应商发货的订单
        orderSearchDTO.setWaitPurchase(0);
        orderSearchDTO.setSupplierDeliveryType(1);
        orderSearchDTO.setIsPayed(1);
        EsPageVO<EsOrderVO> orderPage = orderService.orderPage(orderSearchDTO);
        List<EsSupplierOrderVO> esSupplierOrderList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        List<Long> shopIds = orderPage.getList().stream().map(EsOrderVO::getShopId).collect(Collectors.toList());
        ServerResponseEntity<List<ShopDetailVO>> serverResponse = shopDetailFeignClient.listByShopIds(shopIds);
        List<ShopDetailVO> shopDetailList = serverResponse.getData();
        Map<Long, String> shopMobileMap = shopDetailList.stream().collect(Collectors.toMap(ShopDetailVO::getShopId, ShopDetailVO::getContactPhone));
        // 处理下发货完成时能否修改物流
        for (EsOrderVO esOrderVO : orderPage.getList()) {
            // 处理组合列表
            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(comboMap)) {
                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()));
                }
            }
            EsSupplierOrderVO esSupplierOrderVO = BeanUtil.map(esOrderVO, EsSupplierOrderVO.class);
            // 处理一下返回退款信息，是否移交供应商处理
            if (Objects.nonNull(esSupplierOrderVO.getRefundStatus())) {
                Integer supplierHandlerStatus = orderRefundService.getSupplierHandleStatusByOrderId(esSupplierOrderVO.getOrderId());
                esSupplierOrderVO.setSupplierHandleStatus(supplierHandlerStatus);
            }
            esSupplierOrderList.add(esSupplierOrderVO);
            if (!Objects.equals(esSupplierOrderVO.getSupplierId(), 0L) && shopMobileMap.containsKey(esSupplierOrderVO.getSupplierId())) {
                esSupplierOrderVO.setShopMobile(shopMobileMap.get(esSupplierOrderVO.getShopId()));
            }
            esSupplierOrderVO.setMobile(PhoneUtil.hideBetween(esSupplierOrderVO.getMobile()).toString());
            if (!Objects.equals(esSupplierOrderVO.getStatus(), OrderStatus.CONSIGNMENT.value()) ||
                    !Objects.equals(esSupplierOrderVO.getDeliveryType(), DeliveryType.DELIVERY.value())) {
                continue;
            }
            int updateOrViewDeliveryInfo = 0;
            for (EsOrderItemVO orderItem : esSupplierOrderVO.getOrderItems()) {
                if (Objects.nonNull(orderItem.getDeliveryType()) && Objects.equals(orderItem.getDeliveryType(), DeliveryType.DELIVERY.value())) {
                    updateOrViewDeliveryInfo = 1;
                    break;
                }
            }
            esSupplierOrderVO.setUpdateOrViewDeliveryInfo(updateOrViewDeliveryInfo);
        }
        EsPageVO<EsSupplierOrderVO> supplierOrderPage = new EsPageVO<>();
        supplierOrderPage.setTotal(orderPage.getTotal());
        supplierOrderPage.setPages(orderPage.getPages());
        supplierOrderPage.setList(esSupplierOrderList);
        return ServerResponseEntity.success(supplierOrderPage);
    }

    /**
     * 获取信息
     */
    @GetMapping("/orderInfo/{orderId}")
    public ServerResponseEntity<OrderVO> info(@PathVariable("orderId") Long orderId) {
        // 订单和订单项
        Order order = orderService.getOrderAndOrderItemData(orderId, null);

        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());
        }
        // 处理下组合
        List<OrderItemVO> orderItemDbList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 获取组合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.COMBO_PROD.value())) {
                continue;
            }
            // 放入组合子商品项
            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());
        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, null);
        OrderVO orderVO = BeanUtil.map(order, OrderVO.class);
        List<OrderItemVO> orderItems = orderVO.getOrderItems();
        for (OrderItemVO orderItem : orderItems) {
            orderItem.setChangeNum(orderItem.getBeDeliveredNum() == -1 ? orderItem.getCount() : orderItem.getBeDeliveredNum());
        }
        // 用户收货地址
        OrderAddr orderAddr = orderAddrService.getById(order.getOrderAddrId());
        orderVO.setOrderAddr(BeanUtil.map(orderAddr, OrderAddrVO.class));
        return ServerResponseEntity.success(orderVO);
    }

    /**
     * 发货
     */
    @PostMapping("/delivery")
    public ServerResponseEntity<Void> delivery(@Valid @RequestBody DeliveryOrderDTO deliveryOrderParam) {
        Order order = orderService.getOrderAndOrderItemData(deliveryOrderParam.getOrderId(), null);
        if (Objects.isNull(order)) {
            return ServerResponseEntity.fail(ResponseEnum.UNAUTHORIZED);
        }
        // 订单不在支付状态
        if (!Objects.equals(order.getStatus(), OrderStatus.PAYED.value())) {
            return ServerResponseEntity.showFailMsg("订单状态异常");
        }
        List<DeliveryOrderItemDTO> selectOrderItems = deliveryOrderParam.getSelectOrderItems();
        if (CollectionUtil.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();
    }

    @GetMapping("/get_change_amount")
    @Operation(summary = "查询修改订单地址后的运费")
    public ServerResponseEntity<Double> getChangeAmount(OrderChangeAddrDTO param) {
        Order dbOrder = orderService.getOrderAndOrderItemData(param.getOrderId(), null);
        if (dbOrder.getStatus() > OrderStatus.PAYED.value() && !Objects.equals(dbOrder.getStatus(), OrderStatus.WAIT_GROUP.value())) {
            logger.error("订单状态异常，无法更改订单地址");
            throw new LuckException("订单状态异常，无法更改订单地址");
        }
        List<OrderItem> orderItems = orderItemService.listOrderItemsByOrderId(dbOrder.getOrderId());
        List<Long> skuIds = orderItems.stream().map(OrderItem::getSupplierSkuId).collect(Collectors.toList());
        List<Long> spuIds = orderItems.stream().map(OrderItem::getSupplierSpuId).collect(Collectors.toList());
        ServerResponseEntity<List<SkuAddrVO>> responseEntity = skuFeignClient.listSpuDetailByIds(skuIds);
        ServerResponseEntity<List<SpuVO>> response = spuFeignClient.listSpuBySpuIds(spuIds);
        if (!responseEntity.isSuccess() || !response.isSuccess()) {
            logger.error("查询sku或者spu信息失败，skuIds:{}", skuIds, "spuIds:{}", spuIds);
            throw new LuckException(responseEntity.getMsg());
        }
        List<SkuAddrVO> skuList = responseEntity.getData();
        List<SpuVO> spuList = response.getData();
        Map<Long, SkuAddrVO> skuMap = skuList.stream().collect(Collectors.toMap(SkuAddrVO::getSkuId, s -> s));
        Map<Long, SpuVO> spuMap = spuList.stream().collect(Collectors.toMap(SpuVO::getSpuId, s -> s));
        List<ShopCartItemVO> shopCartItems = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (OrderItem orderItem : orderItems) {
            SkuAddrVO sku = skuMap.get(orderItem.getSupplierSkuId());
            SpuVO spuVO = spuMap.get(orderItem.getSupplierSpuId());
            ShopCartItemVO shopCartItem = new ShopCartItemVO();
            shopCartItem.setSkuId(orderItem.getSkuId());
            shopCartItem.setCount(orderItem.getCount());
            shopCartItem.setTotalAmount(orderItem.getSpuTotalAmount());
            shopCartItem.setShopId(orderItem.getShopId());
            shopCartItem.setVolume(sku.getVolume());
            shopCartItem.setWeight(sku.getWeight());
            shopCartItem.setDeliveryTemplateId(spuVO.getDeliveryTemplateId());
            shopCartItem.setDeliveryAmount(spuVO.getDeliveryAmount());
            shopCartItems.add(shopCartItem);
        }
        UserAddrVO userAddrVO = new UserAddrVO();
        userAddrVO.setAreaId(param.getAreaId());
        if (Objects.equals(dbOrder.getDeliveryType(), DeliveryType.SAME_CITY.value())) {
            logger.info("同城配送，用户经纬度：lng:{},lat:{}", param.getLng(), param.getLat());
            userAddrVO.setLng(param.getLng());
            userAddrVO.setLat(param.getLat());
        }
        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.setSupplierId(AuthUserContext.get().getTenantId());
        orderSearchDTO.setStatus(OrderStatus.PAYED.value());
        orderSearchDTO.setSupplierDeliveryType(SupplierDeliveryType.SUPPLIER_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<>(8);
            EasyExcel.read(file.getInputStream(), UnDeliveryOrderExcelVO.class, new OrderExcelListener(orderExcelService, errorMap)).sheet().doRead();
            info = orderExcelService.orderExportError(errorMap);
        } catch (IOException e) {
            logger.error("导入订单失败，失败原因：{}", e.getMessage());
            throw new LuckException(e.getMessage());
        }
        return ServerResponseEntity.success(info);
    }
}
