package com.youchain.businessdata.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.youchain.basicdata.domain.Item;
import com.youchain.basicdata.domain.Point;
import com.youchain.basicdata.domain.Stock;
import com.youchain.basicdata.repository.PointRepository;
import com.youchain.basicdata.service.ItemService;
import com.youchain.basicdata.service.PointService;
import com.youchain.businessdata.domain.*;
import com.youchain.businessdata.inputJson.*;
import com.youchain.businessdata.repository.AgvTaskRepository;
import com.youchain.businessdata.repository.InventoryRepository;
import com.youchain.businessdata.repository.PickDetailRepository;
import com.youchain.businessdata.repository.TaskRepository;
import com.youchain.businessdata.service.*;
import com.youchain.config.thread.ThreadPoolExecutorUtil;
import com.youchain.exception.handler.ApiResult;
import com.youchain.modules.system.domain.Dept;
import com.youchain.modules.system.repository.DeptRepository;
import com.youchain.modules.system.service.DeptService;
import com.youchain.utils.*;
import com.youchain.utils.BaseCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.concurrent.CompletableFuture;

import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.OK;

@Service
@RequiredArgsConstructor
@Slf4j
public class MlsServiceImpl implements MlsService {
    private final OrderService orderService;
    private final ItemService itemService;
    private final DeptService deptService;
    private final DeptRepository deptRepository;
    private final EntityManager entityManager;
    private final PointService pointService;
    private final PointRepository pointRepository;
    private final InventoryService inventoryService;
    private final InventoryRepository inventoryRepository;
    private final PickDetailRepository pickDetailRepository;
    private final AgvTaskRepository agvTaskRepository;
    private final TaskRepository taskRepository;
    private final RedisObjectUtils redisObjectUtils;
    private final BatchCreateOrUpdate batchCreateOrUpdate;

    public static String token="";
    public static Date tokenData=null;
    /**
     * 获取Token
     *
     * @return
     */
    @Override
    public String getToKen() {
        if (token != null && !token.isEmpty() && tokenData != null) {
            Date now = new Date();
            long diff = now.getTime() - tokenData.getTime();
            long minutes = diff / (1000 * 60);
            // 如果token在15分钟内仍然有效，则直接返回
            if (minutes < 15) {
                return token;
            }
        }
        String mlsUser = BaseCode.MLS_UN;
        String mlsPwd = BaseCode.MLS_PW;
        JSONObject jsonObject = new JSONObject(new LinkedHashMap<>());
        Map<String, Object> objMap = new LinkedHashMap<>();
        objMap.put("mlsUser", mlsUser);//快码代码
        objMap.put("mlsPwd", mlsPwd);//快码值
        jsonObject.putAll(objMap);
        String resultJson = HttpPostUtil.sendPostReq(UrlApi.extSignIn, jsonObject.toString());//返回ResponseJson*/
        JSONObject resulObject = JSON.parseObject(resultJson);
        //判断接口是否成功
        if (resulObject == null) {
            throw new RuntimeException("获取toKen接口返回数据为空!");
        }

        String code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
        String msg = resulObject.getString("msg") == null ? "" : resulObject.getString("msg");

        if ("0".equals(code)) {
            tokenData = new Date();
            token = resulObject.getString("data") == null ? "" : resulObject.getString("data");
            return token;
        } else {
            throw new RuntimeException("MLS异常信息:" + msg);
        }
    }

    /**
     * 获取送货单JSON
     *
     * @return
     */
    @Override
    public String getOrderJson(OrderInfo orderInfo) {
        JSONObject jsonObject = new JSONObject(new LinkedHashMap<>());
        Map<String, Object> objMap = new LinkedHashMap<>();
        objMap.put("ifaceCode", orderInfo.getIfaceCode());//获取送货单信息
        objMap.put("sourceSystem", orderInfo.getSourceSystem());//来源系统
        objMap.put("params", orderInfo.getParams());
        jsonObject.putAll(objMap);
        return HttpPostUtil.sendPostReq(UrlApi.publicApi, jsonObject.toString(), this.getToKen());//返回ResponseJson*/
    }

    /**
     * 获取送货单信息
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void getOrderInfo(String resultJson) {
        if (StringUtils.isEmpty(resultJson)) {
            throw new IllegalArgumentException("获取送货单接口失败!");
        }

        JSONObject resulObject = JSON.parseObject(resultJson);
        if (resulObject == null) {
            throw new IllegalArgumentException("获取送货单接口返回数据为空!");
        }

        String code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
        String msg = resulObject.getString("msg") == null ? "" : resulObject.getString("msg");
        //判断接口是否成功
        if (!"0".equals(code)) {
            throw new IllegalArgumentException("获取送货单接口异常信息:" + msg);
        }

        JSONObject dataObject = resulObject.getJSONObject("data");
        if (dataObject == null) {
            throw new IllegalArgumentException("获取送货单接口返回数据为空!");
        }


        JSONArray details = dataObject.getJSONArray("list");
        //判断是否有送货单数据
        if (details == null || details.isEmpty()) {
            throw new IllegalArgumentException("没有获取到送货单数据!");
        }

        List<Order> ordersToCreate = new ArrayList<>();//新增订单集合
        List<Order> ordersToUpdate = new ArrayList<>();//更新订单集合
        //获取所有送货单条码号
        Set<String> barcodeNumbers = details.stream()
                .map(detail -> ((JSONObject) detail).getString("barcodeNumber"))
                .collect(Collectors.toSet());
        //获取已存在的订单
        Map<String, Order> existingOrders = orderService.findByBarcodeNumbers(barcodeNumbers);
        //循环处理每个送货单
        for (int i = 0; i < details.size(); i++) {
            JSONObject detail = details.getJSONObject(i);
            String barcodeNumber = detail.getString("barcodeNumber");
            //判断是否已存在订单
            if (existingOrders.containsKey(barcodeNumber)) {
                Order existingOrder = existingOrders.get(barcodeNumber);
                //更新订单信息
                ordersToUpdate.add(updateOrder(existingOrder, detail));
            } else {
                //新增订单
                ordersToCreate.add(createOrder(detail));
            }
        }

        CompletableFuture.runAsync(() -> {
            //批量新增订单
            if (!ordersToCreate.isEmpty()) {
                batchCreateOrUpdate.batchCreate(ordersToCreate);
            }
        });

        CompletableFuture.runAsync(() -> {
            //批量更新订单
            if (!ordersToUpdate.isEmpty()) {
                batchCreateOrUpdate.batchUpdate(ordersToUpdate);
            }
        });
    }

    /**
     * 创建订单
     *
     * @param detail
     * @return
     */
    private Order createOrder(JSONObject detail) {

        String barcodeNumber = detail.getString("barcodeNumber");//送货单条码号
        String isCreatedLabel = detail.getString("isCreatedLabel");//是否已生成标签N
        String itemCode = detail.getString("itemCode");//物料编码
        String iqcResult = detail.getString("iqcResult");//检验结果(不合格：REJECT，合格：ACCEPT)
        String supplierCode = detail.getString("supplierCode");//供应商编码
        //String dispatchNumber=detail.getString("dispatchNumber");//文档没有该字段
        String receivedLocationName = detail.getString("receivedLocationName");//LMES货位名称
        String receivedInvCode = detail.getString("receivedInvCode");//LMES接收子库编码
        //Integer deliveryNotifyLineId = detail.getInteger("deliveryNotifyLineId");//送货通知单行ID
        String deliveryNumber = detail.getString("deliveryNumber");//送货单号
        String receivedAreaCode = detail.getString("receivedAreaCode");//LMES接收货区编码
        String supplierName = detail.getString("supplierName");//供应商名称
        String isIqcInspected = detail.getString("isIqcInspected");//Y-已检验N-未检验
        Double deliveryQty = detail.getDouble("deliveryQty") == null ? 0 : detail.getDouble("deliveryQty");//计划数量
        //String deliveryType=detail.getString("deliveryType");//文档没有该字段
        String receivedLocationCode = detail.getString("receivedLocationCode");//LMES货位编码
        String mlsUpdateTime = detail.getString("updateTime");//更新时间
        String receivedInvName = detail.getString("receivedInvName");//LMES接收子库名称
        Double receivedQty = detail.getDouble("receivedQty") == null ? 0 : detail.getDouble("receivedQty");//实际接收数量
        //Integer deliveryLineId = detail.getInteger("deliveryLineId");//送货单行ID
        String inInspector = detail.getString("inInspector");//检验员
        Integer deliveryHeaderId = detail.getInteger("deliveryHeaderId");//送货单头ID和003接口关联
        String receivedAreaName = detail.getString("receivedAreaName");//mls接收货区名称
        String deliveryStatus = detail.getString("deliveryStatus");//送货单状态

        //创建
        Order newOrder = new Order(deliveryHeaderId, null, null,
                deliveryNumber, barcodeNumber, deliveryStatus, receivedInvCode, receivedInvName,
                receivedAreaCode, receivedAreaName, receivedLocationCode, receivedLocationName,
                itemCode, deliveryQty, inInspector, receivedQty, isIqcInspected, iqcResult, isCreatedLabel,
                supplierCode, supplierName, mlsUpdateTime == null ? null : DateUtil.parse(mlsUpdateTime).toTimestamp()
        );

        return newOrder;
    }

    /**
     * 更新订单信息
     *
     * @param order
     * @param detail
     */
    private Order updateOrder(Order order, JSONObject detail) {
        order.setReceivedQty(detail.getDouble("receivedQty") == null ? 0 : detail.getDouble("receivedQty"));
        order.setDeliveryStatus(detail.getString("deliveryStatus"));
        order.setIsIqcInspected(detail.getString("isIqcInspected"));
        order.setIqcResult(detail.getString("iqcResult"));
        order.setIsCreatedLabel(detail.getString("isCreatedLabel"));
        order.setItemCode(detail.getString("itemCode"));
        order.setMlsUpdateTime(detail.getString("updateTime") == null ? null : DateUtil.parse(detail.getString("updateTime")).toTimestamp());
        return order;
    }

    /**
     * 获取MO票JSON信息
     *
     * @return
     */
    @Override
    public String getMoJson(MoInfo moInfo) {
        JSONObject jsonObject = new JSONObject(new LinkedHashMap<>());
        Map<String, Object> objMap = new LinkedHashMap<>();
        objMap.put("ifaceCode", moInfo.getIfaceCode());//获取送货单信息
        objMap.put("sourceSystem", moInfo.getSourceSystem());//来源系统
        objMap.put("params", moInfo.getParams());
        jsonObject.putAll(objMap);
        return HttpPostUtil.sendPostReq(UrlApi.publicApi, jsonObject.toString(), this.getToKen());

    }
    // 获取已经存在的MO票
    public Map<String, Mo> findBylabelNos(Set labelNos) {
        String hql = "from Mo where labelNo in (:labelNos) ";
        Query query = entityManager.createQuery(hql);
        query.setParameter("labelNos", labelNos);
        List<Mo> list = query.getResultList();
        Map<String, Mo> map = new HashMap<>();
        for (Mo mo : list) {
            map.put(mo.getLabelNo(), mo);
        }
        return map;
    }
    /**
     * 获取MO票信息
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String getMoInfo(String resultJson) {
        String deliveryHeaderId="";
        if (StringUtils.isEmpty(resultJson)) {
            throw new IllegalArgumentException("MO票接口失败!");
        }

        JSONObject resulObject = JSON.parseObject(resultJson);
        if (resulObject == null) {
            throw new IllegalArgumentException("MO票接口返回数据为空!");
        }
        String code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
        String msg = resulObject.getString("msg") == null ? "" : resulObject.getString("msg");

        if (!"0".equals(code)) {
            throw new IllegalArgumentException("MO票接口异常: " + msg);
        }

        JSONObject dataObject = resulObject.getJSONObject("data");
        if (dataObject == null) {
            throw new IllegalArgumentException("MO票接口返回数据为空!");
        }

        JSONArray details = dataObject.getJSONArray("list");
        //判断是否有MO票数据
        if (details == null || details.isEmpty()) {
            throw new IllegalArgumentException("未获取到MO票数据!");
        }

        List<Mo> mosToCreate = new ArrayList<>();//新增Mo集合
        List<Mo> mosToUpdate = new ArrayList<>();//修改Mo集合

        //获取所有物料编码
        Set<String> itemCodes = details.stream()
                .map(detail -> ((JSONObject) detail).getString("itemCode"))
                .collect(Collectors.toSet());
        //获取已存在的物料
        Map<String, Item> existingItems = itemService.findByItemCodes(itemCodes);

        //获取所有MO票
        Set<String> labelNos = details.stream()
                .map(detail -> ((JSONObject) detail).getString("labelNo"))
                .collect(Collectors.toSet());
        //获取已存在的MO票
        Map<String, Mo> existingMos = findBylabelNos(labelNos);

        //获取仓库
        Dept dept = deptRepository.findByDeptId(7l);
//        Dept dept = redisObjectUtils.getObjectFromCache("dept", () -> deptService.toEntity(deptService.findById(7L)), "系统无此仓库!");

        //循环处理每个MO票
        for (int i = 0; i < details.size(); i++) {
            JSONObject detail = details.getJSONObject(i);
            System.out.println("detail：" + detail);
            deliveryHeaderId = String.valueOf(detail.getInteger("deliveryHeaderId"));
            System.out.println("deliveryHeaderId111：" + deliveryHeaderId);

            //物料编码
            String itemCode = detail.getString("itemCode").trim();
            Item item = null;
            if (existingItems.containsKey(itemCode)) {
                item = existingItems.get(itemCode);
            } else {
                //新增物料
                item = createItem(detail, dept);
                existingItems.put(itemCode, item);
            }

            //MO票
            String labelNo = detail.getString("labelNo");

            //判断是否已存在MO票
            if (existingMos.containsKey(labelNo)) {
                Mo existingMo = existingMos.get(labelNo);
                //更新MO票信息
                mosToUpdate.add(updateMo(existingMo, detail));
            } else {
                //新增MO票
                mosToCreate.add(createMo(detail, item));
            }
        }
        //批量新增Mo票
        if (!mosToCreate.isEmpty()) {
            batchCreateOrUpdate.batchCreate(mosToCreate);
        }
        //批量更新Mo票
        if (!mosToUpdate.isEmpty()) {
            batchCreateOrUpdate.batchUpdate(mosToUpdate);
        }
        System.out.println("deliveryHeaderId777：" + deliveryHeaderId);
        return deliveryHeaderId;
    }

    @Override
    public MoInfo getMoInfo(Date date) {
        MoParams params = new MoParams();
        params.setOrgId(808);
        Set invCodes = new HashSet<>();
        invCodes.add("MA2111");
        params.setInvCodes(invCodes);
        params.setIqcResult("");

        String startTime = DateUtil.format(DateUtil.beginOfDay(date), "yyyy-MM-dd HH:mm:ss");
        params.setStartTime(startTime);
        String endData = DateUtil.format(date, "yyyy-MM-dd");
        params.setEndTime(endData+" 23:59:59");

        params.setPageNo(1);
        params.setPageSize(10000);
        MoInfo moInfo = new MoInfo();
        moInfo.setIfaceCode("MLS-WQ-003");
        moInfo.setSourceSystem("WQ");
        moInfo.setParams(params);

        return moInfo;
    }

    /**
     * 创建订单
     *
     * @param detail
     * @return
     */
    private Item createItem(JSONObject detail, Dept dept) {

        String itemCode = detail.getString("itemCode");//物料编码
        String itemDesc = detail.getString("itemDesc");//物料描述
        String uom = detail.getString("uom");//单位
        String sourceSystem = detail.getString("sourceSystem");//来源系统
        Long itemId = detail.getLong("itemId");//物料id


        //创建
        Item Item = new Item(itemCode, itemDesc, uom, dept, sourceSystem, itemId);
        itemService.create(Item);
        return Item;
    }

    /**
     * 创建Mo票信息
     *
     * @param detail
     */

    private Mo createMo(JSONObject detail, Item item) {
        Integer selfWorkOrderId = detail.getInteger("selfWorkOrderId");//自制件工单id
        String sourceSystem = detail.getString("sourceSystem");//来源系统
        String selfWorkOrderName = detail.getString("selfWorkOrderName");//自制件工单编号
        String labelType = detail.getString("labelType");//标签类型
        String goodsAreaCode = detail.getString("goodsAreaCode");//MLS货区
        String checkResult = detail.getString("checkResult");//检验状态
        String datetimeStockIn = detail.getString("datetimeStockin");//入库时间
        String deleteFlag = detail.getString("deleteFlag");//数据有效性；有效0，无效1
        String createUserCode = detail.getString("createUserCode");//创建人
        String mlsUpdateTime = detail.getString("updateTime");//修改时间
        String labelNo = detail.getString("labelNo");//MO票
        String updateUserCode = detail.getString("updateUserCode");//修改人
        String mlsCreateTime = detail.getString("createTime");//创建时间
        Double qty = detail.getDouble("qty") == null ? 0 : detail.getDouble("qty");//可用数量
        String labelState = detail.getString("labelState");//标签状态
        Integer deliveryHeaderId = detail.getInteger("deliveryHeaderId");//送货单头ID；通过该字段能找到002接口送货单
        String workOrderName = detail.getString("workOrderName");//工单编号
        Integer workOrderId = detail.getInteger("workOrderId");//工单Id
        String goodsLocationCode = detail.getString("goodsLocationCode");//MLS货位
        String invCode = detail.getString("invCode");//MLS子库

        Mo mo = new Mo(labelNo, labelType, labelState, deliveryHeaderId, sourceSystem, qty,
                workOrderId, workOrderName, selfWorkOrderId, selfWorkOrderName, null, item,
                checkResult, Boolean.parseBoolean(deleteFlag), null, null, null, null, invCode, goodsAreaCode, goodsLocationCode,
                datetimeStockIn == null ? null : DateUtil.parse(datetimeStockIn).toTimestamp(),
                mlsCreateTime == null ? null : DateUtil.parse(mlsCreateTime).toTimestamp(),
                mlsUpdateTime == null ? null : DateUtil.parse(mlsUpdateTime).toTimestamp(),
                createUserCode, updateUserCode
        );

        return mo;
    }

    private Mo updateMo(Mo mo, JSONObject detail) {
        mo.setLabelState(detail.getString("labelState"));
        mo.setMlsUpdateTime(detail.getString("updateTime") == null ? null : DateUtil.parse(detail.getString("updateTime")).toTimestamp());
        mo.setUpdateUserCode(detail.getString("updateUserCode"));
        mo.setDeliveryHeaderId(detail.getInteger("deliveryHeaderId"));
        mo.setOrderNo(detail.getString("orderNo"));
        return mo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void getIssueInfo(IssueInfo issueInfo) {
        if (issueInfo == null) {
            throw new IllegalArgumentException("传入的 IssueInfo 对象为空");
        }

        Set<String> workOrderNameSet = issueInfo.getWorkOrderName();
        if (workOrderNameSet == null || workOrderNameSet.isEmpty()) {
            throw new IllegalArgumentException("没有获取到工单号!");
        }

        CompletableFuture<List<Inventory>> inventoryListFuture = CompletableFuture.supplyAsync(() -> {

            List<Inventory> inventoryList = inventoryService.findInvByBillCode(workOrderNameSet);//根据工单号查询库存信息

            return inventoryList;
        });

        if (inventoryListFuture.join().isEmpty()) {
            throw new RuntimeException("无库存信息!");
        }
        List<String> errorMsgList = new ArrayList<>();
        inventoryListFuture.thenAccept((result) -> {
            //目标点
            /*Point endPoint = redisObjectUtils.getObjectFromCache("ckjbk", () -> pointService.findByCode(null, BaseStatus.FREE, null, "出库接驳口", null),
                    "系统无此点位!");*/

            List<Inventory> inventoryToUpdate = new ArrayList<>();
            List<PickDetail> pickDetailToCreate = new ArrayList<>();
            List<AgvTask> agvTaskToCreate = new ArrayList<>();
            List<Task> taskToCreate = new ArrayList<>();
            for (Inventory inv : result) {
                /* 按顺序获取出库接驳点*/
                Point endPoint;
                List<Point> pointList = pointRepository.findByAreaAndStatus("出库接驳口", BaseStatus.FREE);
                if (pointList.size() < 1) {
                    errorMsgList.add(inv.getItemKey().getPropC1() + "标签分配无空闲备货位!");
                    continue;
                    /* 出库接驳口无空闲库位，更新状态重新分配*/
                    /*pointList = pointRepository.findByAreaAndStatus("出库接驳口", BaseStatus.USED);
                    for (Point p : pointList) {
                        p.setStatus(BaseStatus.FREE);
                        pointRepository.save(p);
                    }*/
                }
                if (inv.getBeLock()==true&&BaseCode.PICK_YH_QR.equals("1")){
                    errorMsgList.add(inv.getItemKey().getPropC1() + "库存未验货!");
                    continue;
                }
                if (inv.getQueuedQty()>0){
                    errorMsgList.add(inv.getItemKey().getPropC1() + "库存已被占用!");
                    continue;
                }
                endPoint = pointList.get(0);
                endPoint.setStatus(BaseStatus.USED);
                pointRepository.save(endPoint);

                //根据库存信息生成叫料任务
                Stock stock = inv.getStock();//容器
                Point startPoint = inv.getPoint();//起始点位
                ItemKey itemKey = inv.getItemKey();
                Item item = inv.getItemKey().getItem();

                //更新库存信息
                inventoryToUpdate.add(updateInventory(inv));

                //生成出库明细
                PickDetail pd = createPickDetail(item, inv.getBillCode(), itemKey.getPropC1(), inv.getQuantity(), issueInfo.getTaskNumber());
                pickDetailToCreate.add(pd);

                //生成搬运任务
                AgvTask agvTask = new AgvTask(BizStatus.PICK, stock.getCode(), startPoint.getCode(), endPoint.getCode(), BizStatus.OPEN, "PICKER_MOVE");
                agvTaskToCreate.add(agvTask);

                //生成Task
                Task task = createTask(item, itemKey, pd, inv.getBillCode(), stock, startPoint, endPoint, agvTask, inv);
                taskToCreate.add(task);
            }
            if (!errorMsgList.isEmpty()) {
                throw new RuntimeException(errorMsgList.toString());
            }
            ExecutorService executor = ThreadPoolExecutorUtil.getPoll("getIssueInfo-job");

            // 批量更新库存信息
            CompletableFuture<Void> inventoryFuture = CompletableFuture.runAsync(() -> {
                //批量更新库存信息
                if (!inventoryToUpdate.isEmpty()) {
                    batchCreateOrUpdate.batchUpdate(inventoryToUpdate);
                }

            }, executor);


            CompletableFuture<Void> pickDetailFuture = inventoryFuture.thenRunAsync(() -> {
                //批量生成叫料明细
                if (!pickDetailToCreate.isEmpty()) {
                    batchCreateOrUpdate.batchCreate(pickDetailToCreate);
                }

            }, executor);

            CompletableFuture<Void> agvTaskFuture = pickDetailFuture.thenRunAsync(() -> {
                // 批量生成agv任务
                if (!agvTaskToCreate.isEmpty()) {
                    batchCreateOrUpdate.batchCreate(agvTaskToCreate);
                }

            }, executor);

            CompletableFuture<Void> taskFuture = agvTaskFuture.thenRunAsync(() -> {
                // 批量生成任务
                if (!taskToCreate.isEmpty()) {
                    batchCreateOrUpdate.batchCreate(taskToCreate);

                }

            }, executor);
            taskFuture.join();

            executor.shutdown();
        });
        if (!errorMsgList.isEmpty()) {
            throw new RuntimeException(errorMsgList.toString());
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void getIssueInfo(List<String> itemCodes,Point endPoint) {

        CompletableFuture<List<Inventory>> inventoryListFuture = CompletableFuture.supplyAsync(() -> {

            List<Inventory> inventoryList = inventoryRepository.findInvByItemCodes(itemCodes);//物料号码查询库存信息

            return inventoryList;
        });

        if (inventoryListFuture.join().isEmpty()) {
            throw new RuntimeException("无库存信息!");
        }
        List<String> errorMsgList = new ArrayList<>();
        inventoryListFuture.thenAccept((result) -> {
            List<Inventory> inventoryToUpdate = new ArrayList<>();
            List<PickDetail> pickDetailToCreate = new ArrayList<>();
            List<AgvTask> agvTaskToCreate = new ArrayList<>();
            List<Task> taskToCreate = new ArrayList<>();
            for (Inventory inv : result) {
                if (inv.getBeLock()==true&&BaseCode.PICK_YH_QR.equals("1")){
                    errorMsgList.add(inv.getItemKey().getPropC1() + "库存未验货!");
                    continue;
                }
                if (inv.getQueuedQty()>0){
                    errorMsgList.add(inv.getItemKey().getPropC1() + "库存已被占用!");
                    continue;
                }
                //根据库存信息生成叫料任务
                Stock stock = inv.getStock();//容器
                Point startPoint = inv.getPoint();//起始点位
                ItemKey itemKey = inv.getItemKey();
                Item item = inv.getItemKey().getItem();

                //更新库存信息
                inventoryToUpdate.add(updateInventory(inv));

                //生成出库明细
                PickDetail pd = createPickDetail(item, inv.getBillCode(), itemKey.getPropC1(), inv.getQuantity(), "");
                pickDetailToCreate.add(pd);

                //生成搬运任务
                AgvTask agvTask = new AgvTask(BizStatus.PICK, stock.getCode(), startPoint.getCode(), endPoint.getCode(), BizStatus.OPEN, "PICKER_MOVE");
                agvTaskToCreate.add(agvTask);

                //生成Task
                Task task = createTask(item, itemKey, pd, inv.getBillCode(), stock, startPoint, endPoint, agvTask, inv);
                taskToCreate.add(task);

                break;
            }
            if (!errorMsgList.isEmpty()) {
                throw new RuntimeException(errorMsgList.toString());
            }
            ExecutorService executor = ThreadPoolExecutorUtil.getPoll("getIssueInfo-job");

            // 批量更新库存信息
            CompletableFuture<Void> inventoryFuture = CompletableFuture.runAsync(() -> {
                //批量更新库存信息
                if (!inventoryToUpdate.isEmpty()) {
                    batchCreateOrUpdate.batchUpdate(inventoryToUpdate);
                }

            }, executor);


            CompletableFuture<Void> pickDetailFuture = inventoryFuture.thenRunAsync(() -> {
                //批量生成叫料明细
                if (!pickDetailToCreate.isEmpty()) {
                    batchCreateOrUpdate.batchCreate(pickDetailToCreate);
                }

            }, executor);

            CompletableFuture<Void> agvTaskFuture = pickDetailFuture.thenRunAsync(() -> {
                // 批量生成agv任务
                if (!agvTaskToCreate.isEmpty()) {
                    batchCreateOrUpdate.batchCreate(agvTaskToCreate);
                }

            }, executor);

            CompletableFuture<Void> taskFuture = agvTaskFuture.thenRunAsync(() -> {
                // 批量生成任务
                if (!taskToCreate.isEmpty()) {
                    batchCreateOrUpdate.batchCreate(taskToCreate);

                }

            }, executor);
            taskFuture.join();

            executor.shutdown();
        });
        if (!errorMsgList.isEmpty()) {
            throw new RuntimeException(errorMsgList.toString());
        }
    }
    private void processInventory(Inventory inv, Point endPoint) {
        Stock stock = inv.getStock();
        Point startPoint = inv.getPoint();
        Item item = inv.getItemKey().getItem();

        // 更新库存信息
        Inventory updatedInv = updateInventory(inv);

        // 生成出库明细
        PickDetail pd = new PickDetail();
        pd.setItem(item);
        pd.setPo(inv.getBillCode());
        pd.setPropC1(inv.getItemKey().getPropC1());
        pd.setLineNo(1L);
        pd.setOrderQty(inv.getQuantity());
        pd.setAllocatedQty(inv.getQuantity());
        pd.setStatus(BizStatus.ALLOCATE);
        pd.setDept(item.getDept());

        // 生成搬运任务
        AgvTask agvTask = new AgvTask(BizStatus.PICK, stock.getCode(), startPoint.getCode(), endPoint.getCode(), BizStatus.OPEN, "PICKER_MOVE");

        // 生成Task
        Task task = new Task();
        task.setItem(item);
        task.setItemKey(inv.getItemKey());
        task.setPickDetail(pd);
        task.setBillCode(inv.getBillCode());
        task.setSrcStock(stock);
        task.setDstStock(stock);
        task.setSrcPoint(startPoint);
        task.setDstPoint(endPoint);
        task.setSrcStockCode(stock.getCode());
        task.setSrcPointCode(startPoint.getCode());
        task.setDstPointCode(endPoint.getCode());
        task.setInvStatus(inv.getStatus());
        task.setTaskType(BizStatus.PICK);
        task.setTaskStatus(BizStatus.OPEN);
        task.setPlanQty(inv.getQuantity());
        task.setInvId(inv.getId());
        task.setDept(item.getDept());
        task.setAgvTask(agvTask);

        synchronized (this) {
            // 批量更新库存信息
            batchCreateOrUpdate.batchUpdate(Collections.singletonList(updatedInv));

            // 批量生成叫料明细
            batchCreateOrUpdate.batchCreate(Collections.singletonList(pd));

            // 批量生成agv任务
            batchCreateOrUpdate.batchCreate(Collections.singletonList(agvTask));

            // 批量生成任务
            batchCreateOrUpdate.batchCreate(Collections.singletonList(task));
        }
    }

    /**
     * 更新库存信息
     *
     * @param inventory
     * @return
     */
    public Inventory updateInventory(Inventory inventory) {
        inventory.setQueuedQty(inventory.getQuantity());
        return inventory;
    }

    public PickDetail createPickDetail(Item item, String po, String propC1, Double orderQty, String taskNumber) {
        PickDetail pickDetail = new PickDetail();
        pickDetail.setItem(item);
        pickDetail.setPo(po);
        pickDetail.setPropC1(propC1);
        pickDetail.setLineNo(1L);
        pickDetail.setOrderQty(orderQty);
        pickDetail.setAllocatedQty(orderQty);
        pickDetail.setStatus(BizStatus.ALLOCATE);
        pickDetail.setDept(item.getDept());
        pickDetail.setPropC2(taskNumber);
        return pickDetail;
    }

    public Task createTask(Item item, ItemKey itemKey, PickDetail pd, String taskNumber, Stock stock, Point startPoint, Point endPoint, AgvTask agvTask, Inventory inv) {
        Task task = new Task();
        task.setItem(item);
        task.setItemKey(itemKey);
        task.setPickDetail(pd);
        task.setBillCode(taskNumber);
        task.setSrcStock(stock);
        task.setDstStock(stock);
        task.setSrcPoint(startPoint);
        task.setDstPoint(endPoint);
        task.setSrcStockCode(stock.getCode());
        task.setSrcPointCode(startPoint.getCode());
        task.setDstPointCode(endPoint.getCode());
        task.setInvStatus(inv.getStatus());
        task.setTaskType(BizStatus.PICK);
        task.setTaskStatus(BizStatus.OPEN);
        task.setPlanQty(inv.getQuantity());
        task.setInvId(inv.getId());
        task.setDept(item.getDept());
        task.setAgvTask(agvTask);
        return task;
    }


    /**
     * Mo票回传
     *
     * @param returnMoInfo
     * @return
     */
    @Override
    public String returnMo(ReturnMoInfo returnMoInfo) {
        JSONObject jsonObject = new JSONObject(new LinkedHashMap<>());
        Map<String, Object> objMap = new LinkedHashMap<>();
        objMap.put("ifaceCode", returnMoInfo.getIfaceCode());//获取送货单信息
        objMap.put("sourceSystem", returnMoInfo.getSourceSystem());//来源系统
        objMap.put("params", returnMoInfo.getParams());
        jsonObject.putAll(objMap);
        return HttpPostUtil.sendPostReq(UrlApi.publicApi, jsonObject.toString(), this.getToKen());
    }

    /**
     * 叫料结果回传
     *
     * @param returnIssueInfo
     * @return
     */
    @Override
    public String returnIssue(ReturnIssueInfo returnIssueInfo) {
        JSONObject jsonObject = new JSONObject(new LinkedHashMap<>());
        Map<String, Object> objMap = new LinkedHashMap<>();
        objMap.put("ifaceCode", returnIssueInfo.getIfaceCode());//获取送货单信息
        objMap.put("sourceSystem", returnIssueInfo.getSourceSystem());//来源系统
        objMap.put("params", returnIssueInfo.getParams());
        jsonObject.putAll(objMap);
        return HttpPostUtil.sendPostReq(UrlApi.publicApi, jsonObject.toString(), this.getToKen());
    }

    @Override
    public Task getCreateTasks(Point endPoint,Inventory inv,String reqCode) {
        // 占用库位
        endPoint.setStatus(BaseStatus.USED);
        pointRepository.save(endPoint);
        //根据库存信息生成叫料任务
        Stock stock = inv.getStock();//容器
        Point startPoint = inv.getPoint();//起始点位
        ItemKey itemKey = inv.getItemKey();
        Item item = inv.getItemKey().getItem();
        //生成出库明细
        PickDetail pd = createPickDetail(item, inv.getBillCode(), itemKey.getPropC1(), inv.getQuantity(), reqCode);
        // 生成搬运任务
        AgvTask agvTask = new AgvTask(BizStatus.PICK, stock.getCode(), startPoint.getCode(), endPoint.getCode(), BizStatus.OPEN, "PICKER_MOVE");
        // 生成Task
        Task task = createTask(item, itemKey, pd, inv.getBillCode(), stock, startPoint, endPoint, agvTask, inv);
        // 更新库存信息
        inv.setQueuedQty(inv.getQuantity());
        inventoryRepository.save(inv);
        //批量生成叫料明细
        pickDetailRepository.save(pd);
        // 批量生成agv任务
        agvTaskRepository.save(agvTask);

        // 批量生成任务
        taskRepository.save(task);
        return task;
    }
}
