/*
 * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.platform.controller;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.enums.DvyType;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.param.*;
import com.yami.shop.bean.vo.OrderCountVo;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.exception.GlobalException;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.common.util.R;
import com.yami.shop.dao.ExportTaskMapper;
import com.yami.shop.security.comment.dao.AppConnectMapper;
import com.yami.shop.security.comment.model.AppConnect;
import com.yami.shop.security.platform.util.SecurityUtils;
import com.yami.shop.service.*;
import com.yami.shop.sys.service.SysUserService;
import com.yami.shop.utils.CullenUtils;
import com.yami.shop.wx.service.impl.WxProviderServiceImpl;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单信息管理实现
 *
 * @author lgh
 * @version 1.0.0
 * @since 2018-09-15
 */
@RestController
@RequestMapping("/platform/order")
@AllArgsConstructor
@Log4j2
public class OrderController {

    private final OrderService orderService;
    private final OrderItemService orderItemService;
    private final UserAddrOrderService userAddrOrderService;
    private final ProductService productService;
    private final SkuService skuService;
    private final UserService userService;
    private final DeliveryService deliveryService;
    private final OrderSettlementService orderSettlementService;
    private final AppConnectMapper appConnectMapper;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private ExportTaskService exportTaskService;

    /**
     * 分页获取
     */
    @GetMapping("/page")
//    @PreAuthorize("@pms.hasPermission('platform:order:page')")
    public R<IPage<Order>> page(OrderParam orderParam, PageParam<Order> page) {
        IPage<Order> orderIPage = orderService.pageOrdersDetialByOrderParam(page, orderParam);
        return R.SUCCESS(orderIPage);
    }

    @GetMapping("/deliverList")
    @ApiOperation("后管端-快递订单列表")
    public R<IPage<Order>> deliverList(BackendOrderParam orderParam, PageParam<Order> page) {
        getBackendOrderParam(orderParam);
        IPage<Order> orderIPage = orderService.deliverList(page, orderParam);
        return R.SUCCESS(orderIPage);
    }

    @GetMapping("/deliverListStatusNum")
    @ApiOperation("后管端-快递订单列表-订单状态数量")
    public R<Map<String, Integer>> deliverListStatusNum(BackendOrderParam orderParam) {
        getBackendOrderParam(orderParam);
        return R.SUCCESS(orderService.deliverListStatusNum(orderParam));
    }

    /**
     * 根据商家获取支付信息
     */
    @GetMapping("/orderPayByShopId")
    @ApiOperation(value = "根据商家id获取支付信息")
    public R<OrderPayParam> orderPayByShopId(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @RequestParam("startTime") Date startTime,
                                             @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @RequestParam("endTime") Date endTime) {
        OrderPayParam actualTotal = orderService.getPayUserCountByshopId(null, startTime, endTime);
        return R.SUCCESS(actualTotal);
    }

    /**
     * 获取订单信息
     */
    @GetMapping("/orderInfo/{orderNumber}")
//    @PreAuthorize("@pms.hasPermission('platform:order:info')")
    public R<Order> info(@PathVariable("orderNumber") String orderNumber) {
        Order order = orderService.getOne(new LambdaUpdateWrapper<Order>().eq(Order::getOrderNumber, orderNumber));
        if (order == null) {
            throw new GlobalException("未找到所在的订单");
        }
        UserAddrOrder userAddrOrder = userAddrOrderService.getById(order.getAddrOrderId());
        order.setUserAddrOrder(userAddrOrder);
        List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
        if (!orderItems.isEmpty()) {
            orderItems.forEach(c -> {
                c.setRefundIngCount(orderItemService.refundIngCount(c.getOrderItemId()));
                c.setRefundSuccessCount(orderItemService.refundSuccessCount(c.getOrderItemId()));
            });
        }
        //操作人
        if (order.getSplitUserId() != null) {
            order.setSplitUserName(sysUserService.getById(order.getSplitUserId()).getUsername());
        }
        order.setOrderItems(orderItems);
        User user = userService.getById(order.getUserId());
        if (user != null) {
            order.setNickName(user.getNickName());
            order.setUserMobile(user.getUserMobile());
        }

        //子订单数据处理
        List<Order> list = orderService.list(new LambdaUpdateWrapper<Order>().eq(Order::getParentOrderNumber, orderNumber)
                .eq(Order::getDeleteStatus, 0));

        if (ObjectUtil.isNotEmpty(list)) {
            for (Order order1 : list) {

                List<OrderItem> orderItems2 = orderItemService.getOrderItemsByOrderNumber(orderNumber);
                if (!orderItems2.isEmpty()) {
                    orderItems2.forEach(c -> {
                        c.setRefundIngCount(orderItemService.refundIngCount(c.getOrderItemId()));
                        c.setRefundSuccessCount(orderItemService.refundSuccessCount(c.getOrderItemId()));
                    });
                }
                order1.setOrderItems(orderItems2);
            }
            order.setSubOrders(list);
        }

        return R.SUCCESS(order);
    }


    /**
     * 已销售订单
     *
     * @param orderParam
     */
    @GetMapping("/soldExcel")
    @PreAuthorize("@pms.hasPermission('platform:order:exportExcel')")
    public void soldExcel(OrderParam orderParam, HttpServletResponse response) {
//        orderParam.setIsPayed(1);
        orderService.soldExcel(orderParam, response);
//
    }

    @ApiOperation("发货")
    @PutMapping("/delivery")
    @Transactional(rollbackFor = Exception.class)
    public R<Void> delivery(@RequestBody DeliveryOrderParam deliveryOrderParam) {
        Order order = orderService.getOne(new LambdaUpdateWrapper<Order>().eq(Order::getOrderNumber, deliveryOrderParam.getOrderNumber()));
        if (!Objects.equals(order.getHbOrderStatus(), OrderStatus.PADYED.value()) && Objects.equals(order.getDvyType(), DvyType.FETCH.value())) {
            throw new GlobalException("订单不处于待入库状态，无法进行入库");
        }

        List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(deliveryOrderParam.getOrderNumber());
        if (!orderItems.isEmpty()) {
            orderItems.forEach(orderItem ->
                    CullenUtils.validateDataThrowException(orderItemService.refundIngCount(orderItem.getOrderItemId()) != 0, "该订单存在售后中商品，请处理后发货..."));
        }

        Order orderParam = new Order();
        if (deliveryOrderParam.getDvyType().equals(2)) {
            orderParam.setOrderId(order.getOrderId());
            orderParam.setDvyType(2);
            orderService.updateById(orderParam);
            return R.SUCCESS();
        }

        orderParam.setOrderId(order.getOrderId());
        if (!Objects.equals(order.getDvyType(), DvyType.FETCH.value()) || !Objects.equals(order.getDvyType(), DvyType.NOT_DELIVERY.value())) {
            orderParam.setDvyId(deliveryOrderParam.getDvyId());
            orderParam.setDvyFlowId(deliveryOrderParam.getDvyFlowId());
        }
        orderParam.setDvyTime(new Date());
        orderParam.setUpdateTime(new Date());
        //orderParam.setHbOrderStatus(OrderStatus.CONSIGNMENT.value());
        orderParam.setUserId(order.getUserId());

        orderService.delivery(orderParam);

        for (OrderItem orderItem : orderItems) {
            productService.removeProductCacheByProdId(orderItem.getProdId());
            skuService.removeSkuCacheBySkuId(orderItem.getSkuId(), orderItem.getProdId());
        }

        OrderSettlement settlement = orderSettlementService.getOne(new LambdaQueryWrapper<OrderSettlement>().eq(OrderSettlement::getOrderNumber, deliveryOrderParam.getOrderNumber()));
        UserAddrOrder userAddrOrder = userAddrOrderService.getById(order.getAddrOrderId());
        AppConnect connect = appConnectMapper.getByUserId(order.getUserId(), 1);
        Delivery delivery = deliveryService.getById(deliveryOrderParam.getDvyId());
        CullenUtils.validateDataThrowException(connect == null, "openid不存在..." + order.getUserId());
        CullenUtils.validateDataThrowException(connect.getBizUserId() == null, "openid不存在..." + order.getUserId());
        WxProviderServiceImpl.uploadShippingInfo(
                deliveryOrderParam.getDvyFlowId(),
                settlement.getBizPayNo(),
                toOrderStr(orderItems),
                userAddrOrder.getMobile(),
                connect.getBizUserId(),
                delivery.getDvyNo(), 1
        );
        return R.SUCCESS();
    }

    /**
     * 配送订单模块
     */
    @GetMapping("/deliveryOrder")
    @ApiOperation("配送订单模块")
    public R<IPage<Order>> deliveryOrder(PageParam<Order> page, OrderStatisticsParam orderParam) {
        orderParam.setDvyType(DvyType.NOT_DELIVERY.value());
        IPage<Order> orderIPage = orderService.deliveryOrder(page, orderParam);
        return R.SUCCESS(orderIPage);
    }

    /**
     * 配送订单模块(数据统计)
     */
    @GetMapping("/selectOrderCount")
    @ApiOperation("配送订单模块(数据统计)")
    public R<OrderCountParam> selectOrderCount(OrderParam orderParam) {
        OrderCountParam orderCount = orderService.selectOrderCount(orderParam);
        return R.SUCCESS(orderCount);
    }

    public static String toOrderStr(List<OrderItem> items) {
        if (items == null || items.isEmpty()) {
            return "";
        }
        return items.stream()
                .map(item -> item.getProdName() + "*" + item.getProdCount())
                .collect(Collectors.joining(" "));
    }

    /**
     * 导出
     *
     * @param orderParam
     */
    @GetMapping("/export")
    @ApiOperation("后管端-快递订单列表导出")
    public R<String> export(BackendOrderParam orderParam) {
        getBackendOrderParam(orderParam);
        Long userId = null;
        try {
            userId = SecurityUtils.getSysUser().getUserId();
        } catch (Exception e) {
            throw new GlobalException("导出获取当前登录用户失败");
        }
        if (ObjectUtil.isEmpty(userId)) {
            throw new GlobalException("导出获取当前登录用户信息失败,请登录");
        }
        ExportTask exportTaskOne = exportTaskService.findByUserIdAndStatusAndType(userId, 0, 1);//查询导出任务为正常订单并且在进行中的数据
        // 异步执行
        if (exportTaskOne != null) {
            return R.FAIL("正常订单有导出任务正在执行中,请中断或者等待完成");
        }

        return orderService.export(orderParam, userId);
    }


    /**
     * 订单订单统计数
     *
     * @param orderParam
     */
    @GetMapping("/orderCount")
    @ApiOperation("后管端-订单列表统计")
    public R<OrderCountVo> orderCount(BackendOrderParam orderParam) {
        getBackendOrderParam(orderParam);
        return R.SUCCESS(orderService.orderCount(orderParam));
    }


    private void getBackendOrderParam(BackendOrderParam orderParam) {
        if (orderParam.getChannelIdList() == null || orderParam.getChannelIdList().isEmpty()) {
            throw new GlobalException("请求参数-所属企业不允许为空");
        }
        if (ObjectUtil.isEmpty(orderParam.getUserAttrType())) {
            orderParam.setUserAttrType("1");//默认查询正常人员属性
        }
        if (orderParam.getChannelIdList().contains(0L)) {
            Long userId = null;
            try {
                userId = SecurityUtils.getSysUser().getUserId();
            } catch (Exception e) {
                throw new GlobalException("获取当前登录用户失败");
            }
            List<Long> channelIdList = sysUserService.findByUserIdListId(userId);
            orderParam.setChannelIdList(channelIdList);
            if (userId != Constant.SUPER_ADMIN_ID && (orderParam.getChannelIdList() == null || orderParam.getChannelIdList().isEmpty())) {
                List<Long> longs = new ArrayList<>();
                longs.add(0L);
                orderParam.setChannelIdList(longs);
            }
        }
    }

    /**
     * 手动拆单处理
     * 订单会处于拆单中
     * 会传订单单号和订单项列表信息
     * 会加上父订单项里面的已拆单数量
     * 生成子订单数据 并且子订单会处于临时保存
     */
    @PostMapping("/manualSplit")
    @ApiOperation("手动拆单处理")
    public R<Order> manualSplitOrder(@RequestBody ManualSplitOrderParam param) {
        Order subOrder = orderService.manualSplitOrder(param);
        return R.SUCCESS(subOrder);
    }

    /**
     * 确定拆单
     * 会改变订单拆单状态为拆单完成
     * 会改变子订单拆单状态为不拆单
     */
    @PostMapping("/confirmSplit")
    @ApiOperation("确定拆单")
    public R<Void> confirmSplitOrder(@RequestBody ConfirmSplitOrderParam param) {
        orderService.confirmSplitOrder(param);
        return R.SUCCESS();
    }

    /**
     * 删除对应的临时子订单
     * 加回对应的父订单项已拆单数量数量
     */
    @DeleteMapping("/deleteTempSubOrder")
    @ApiOperation("删除临时子订单")
    public R<Void> deleteTempSubOrder(@RequestParam String subOrderNumber) {
        orderService.deleteTempSubOrder(subOrderNumber);
        return R.SUCCESS();
    }

}
