package org.wcs.business.stock;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.wcs.constant.enums.business.LocationTypeEnum;
import org.wcs.constant.enums.business.SimpleTaskEnum;
import org.wcs.constant.enums.common.TrueOrFalseEnum;
import org.wcs.constant.enums.database.StockComposeTaskTypeEnum;
import org.wcs.constant.enums.database.StockExecuteEquipmentEnum;
import org.wcs.constant.enums.database.StockSingleTaskStatusEnum;
import org.wcs.constant.enums.database.StockSingleTaskTypeEnum;
import org.wcs.helper.PlcTaskIdHelper;
import org.wcs.mapper.intf.AppConveyLocationService;
import org.wcs.mapper.intf.AppStackerLocationService;
import org.wcs.mapper.intf.AppStackerStandService;
import org.wcs.mapper.intf.AppTrayConveyLocationService;
import org.wcs.model.bo.tuple.Tuple2;
import org.wcs.model.po.app.*;
import org.wcs.model.pojo.task.SimpleTask;
import org.wcs.utils.AppStringUtils;
import org.wcs.utils.AppUUIDUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 【核心】仓库组合任务管理，数据处理，
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class StockComposeTaskManage {

    private final StringRedisTemplate stringRedisTemplate;
    private final AppStackerLocationService stackerLocationService;
    private final AppStackerStandService stackerStandService;
    private final AppTrayConveyLocationService trayConveyLocationService;
    private final AppConveyLocationService conveyLocationService;
    private final PlcTaskIdHelper plcTaskIdHelper;
    private final LocationManage locationManage; // 位置管理

    // 点位暂存区，存放点位信息   <点位， 基础资料>
    Map<String, AppStackerLocation> stackerLocationMap = new ConcurrentHashMap<>();
    Map<String, AppStackerStand> stackerStandMap = new ConcurrentHashMap<>();
    Map<String, AppTrayConveyLocation> trayConveyLocationMap = new ConcurrentHashMap<>();
    Map<String, AppConveyLocation> conveyLocationMap = new ConcurrentHashMap<>();

    String areaLocationRedisKey = "WCS:Location:Area"; // 存储每个区域所包含的位置
    Map<String, List<String>> locationAreaMap = new ConcurrentHashMap<>(); // <位置号，所属的区域列表>
    List<String> areas = new ArrayList<>(); // 存储所有的区域
    List<String> locations = new ArrayList<>(); // 存储所有的点位信息




    /**
     * 初始化
     */
    public void initialize() {
        long deleteDataCount = deleteLocationIdArea(); // 删除Redis中的位置区域信息
        log.info("删除Redis中的位置区域信息：{}", deleteDataCount);
        addStackerLocationIdToRedisList(); // 添加堆垛机位置信息到Redis中
        addStackerStandIdToRedisList(); // 添加堆垛机站台信息到Redis中
        addTrayLocationIdToRedisList(); // 添加托盘位置信息到Redis中
        addConveyLocationToRedisList(); // 添加普通输送信息到Redis中
        summaryLocationArea(); // 汇总位置区域信息
        summaryLocation(); // 汇总位置信息
    }

    /**
     * 将堆垛机位置添加到Redis和系统缓存中，按区域添加
     */
    public void addStackerLocationIdToRedisList() {
        List<AppStackerLocation> appStackerLocations = stackerLocationService.queryStackerLocationAll();
        if(appStackerLocations == null) {
            log.error("堆垛机点位数据库查询失败");
            return; // 数据库查询失败
        }
        // 添加到缓存中
        stackerLocationMap = appStackerLocations.stream().collect(Collectors.toMap(AppStackerLocation::getBusinessLocation, appStackerLocation -> appStackerLocation));
        // 添加到 redis 中
        Map<Integer, List<AppStackerLocation>> machineLocation = appStackerLocations.stream().collect(Collectors.groupingBy(AppStackerLocation::getMachineId));
        machineLocation.forEach((machineId, locations) -> {
            // 拿出locations里面所有的 businessLocationId形成list
            List<String> businessLocationIds = locations.stream().map(AppStackerLocation::getBusinessLocation).toList();
            stringRedisTemplate.opsForList().leftPushAll(areaLocationRedisKey + ":" + machineId, businessLocationIds);
        });

    }

    /**
     * 添加堆垛机站台信息到redis和系统缓存中
     */
    public void addStackerStandIdToRedisList() {
        List<AppStackerStand> stackerStands = stackerStandService.queryAll();
        if(stackerStands == null) {
            log.error("堆垛机站台信息数据库访问异常");
            return; // 堆垛机信息数据库访问异常
        }
        // 添加到缓存中
        stackerStandMap = stackerStands.stream().collect(Collectors.toMap(AppStackerStand::getStandId, stackerStand -> stackerStand));
        // 按堆垛机区域添加
        Map<Integer, List<AppStackerStand>> stackerGroup = stackerStands.stream().collect(Collectors.groupingBy(AppStackerStand::getStackerId));
        stackerGroup.forEach((stackerId, stackerStandList) -> {
            List<String> trayLocationIds = stackerStands.stream().map(AppStackerStand::getStandId).collect(Collectors.toList());
            stringRedisTemplate.opsForList().leftPushAll(areaLocationRedisKey + ":" + stackerId, trayLocationIds);
        });
        // 按区域添加
        Map<String, List<AppStackerStand>> areaGroup = stackerStands.stream().collect(Collectors.groupingBy(AppStackerStand::getAreaId));
        areaGroup.forEach((areaId, stackerStandList) -> {
            List<String> trayLocationIds = stackerStands.stream().map(AppStackerStand::getStandId).collect(Collectors.toList());
            stringRedisTemplate.opsForList().leftPushAll(areaLocationRedisKey + ":" + areaId, trayLocationIds);
        });
    }

    /**
     * 添加托盘位置id到redis和系统缓存中
     */
    public void addTrayLocationIdToRedisList() {
        List<AppTrayConveyLocation> trayConveyLocations = trayConveyLocationService.queryAll();
        if(trayConveyLocations == null) {
            log.error("托盘输送点位数据库加载失败");
            return;
        }
        // 添加到缓存中
        trayConveyLocationMap = trayConveyLocations.stream().collect(Collectors.toMap(AppTrayConveyLocation::getBusinessLocationId, trayConveyLocation -> trayConveyLocation));
        // 添加到redis中
        Map<String, List<AppTrayConveyLocation>> trayConveyLocation = trayConveyLocations.stream().collect(Collectors.groupingBy(AppTrayConveyLocation::getAreaId));
        trayConveyLocation.forEach((areaId, trayConveyLocationList) -> {
            List<String> businessLocationIds = trayConveyLocationList.stream().map(AppTrayConveyLocation::getBusinessLocationId).toList();
            stringRedisTemplate.opsForList().leftPushAll(areaLocationRedisKey + ":" + areaId, businessLocationIds);
        });
    }

    /**
     * 添加普通输送点位到 Redis和系统缓存中
     */
    public void addConveyLocationToRedisList() {
        List<AppConveyLocation> appConveyLocations = conveyLocationService.queryAll();
        if(appConveyLocations == null) {
            log.error("普通输送点位数据库加载失败");
            return;
        }
        // 添加到缓存中
        conveyLocationMap = appConveyLocations.stream().collect(Collectors.toMap(AppConveyLocation::getBusinessLocationId, v -> v));
        // 添加到 Redis 中
        Map<String, List<AppConveyLocation>> conveyLocationList = appConveyLocations.stream().collect(Collectors.groupingBy(AppConveyLocation::getAreaId));
        conveyLocationList.forEach((areaId, conveyLocations) -> {
            List<String> businessLocationIds = conveyLocations.stream().map(AppConveyLocation::getBusinessLocationId).toList();
            stringRedisTemplate.opsForList().leftPushAll(areaLocationRedisKey + ":" + areaId, businessLocationIds);
        });
    }

    /**
     * 删除redis中所有点位
     * @return 删除数量
     */
    public long deleteLocationIdArea() {
        Set<String> keys = stringRedisTemplate.keys(areaLocationRedisKey + ":*");
        return stringRedisTemplate.delete(keys);
    }

    /**
     * 计算汇总哪些点对应的不止一个区域，
     * 这些点就是中转点，单独存到map里面，方便后续处理
     */
    public void summaryLocationArea() {
        Set<String> keys = stringRedisTemplate.keys(areaLocationRedisKey + ":*");
        if(keys.isEmpty()) {
            log.warn("汇总点位区域时 无区域点位");
            return;
        }
        // 获取所有区域
        List<String> areas = new ArrayList<>(); // 所有的区域
        keys.forEach(key -> {
            String[] strings = key.split(":");
            areas.add(strings[strings.length - 1]);
        });
        // 计算区域共同点位
        if(areas.size() == 1) {
            return;
        }
        List<Tuple2<String, List<String>>> areaLocationList = new ArrayList<>();
        /* 将每一个点位列表和其他列表对比，找出相同的，这里找出的结果必然有重复的，下面会重新去重并组合 */
        for (int i = 0; i < areas.size() - 1; i++) {
            String key1 = areaLocationRedisKey + areas.get(i);
            for(int p = i + 1; p < areas.size(); p++) {
                String key2 = areaLocationRedisKey + areas.get(p);
                List<String> area1List = stringRedisTemplate.opsForList().range(key1, 0, -1);
                List<String> area2List = stringRedisTemplate.opsForList().range(key2, 0, -1);
                if(area1List == null || area2List == null) {
                    continue;
                }
                // 查找两个list的相同的项
                List<String> sameLocation = area1List.stream().filter(area2List::contains).toList();
                if(sameLocation.isEmpty()) {
                    continue;
                }
                for(String location : sameLocation) {
                    Tuple2<String, List<String>> tuple2 = new Tuple2<>(location, List.of(areas.get(i), areas.get(p)));
                    areaLocationList.add(tuple2);
                }
            }
        }
        this.areas = areas; // 赋值给全局变量
        // -- 去重并组合
        List<String> distinctLocationList = areaLocationList.stream().map(tuple2 -> tuple2.item1).distinct().toList();
        for (String distinctLocation : distinctLocationList) {
            List<Tuple2<String, List<String>>> areaDataList = areaLocationList.stream().filter(tuple2 -> tuple2.item1.equals(distinctLocation)).toList();
            List<String> locationAreas = areaDataList.stream().map(tuple2 -> tuple2.item2).flatMap(List::stream).distinct().toList();
            locationAreaMap.put(distinctLocation, locationAreas);
        }
    }

    /**
     * 汇总所有点位信息
     */
    public void summaryLocation() {
        if(areas.isEmpty()) {
            return;
        }
        areas.forEach(area -> {
            String key = areaLocationRedisKey + ":" + area;
            List<String> locationList = stringRedisTemplate.opsForList().range(key, 0, -1);
            if(locationList == null || locationList.isEmpty()) {
                return;
            }
            locationList.forEach(location -> {
                if(!locations.contains(location)) {
                    locations.add(location);
                }
            });
        });
    }

    /**
     * 检查某一点位是否存在
     * @param location 位点
     * @return 是否存在
     */
    public boolean checkLocationExist(String location) {
        if(location == null || location.trim().isEmpty()) {
            return false;
        }
        if(locations.isEmpty()) {
            summaryLocation();
        }
        return locations.contains(location);
    }

    /**
     * 检查一个点位的区域，若这个点位在多个区域中，则返回多个
     * @param location 待检查的点位
     * @return 该点位的区域
     */
    private List<String> getLocationArea(String location) {
        if(AppStringUtils.isEmpty(location)) {
            return null;
        }
        List<String> locationAreaList = new ArrayList<>();
        // 检查是否是堆垛机点位
        AppStackerLocation stackerLocation = stackerLocationMap.get(location);
        if(stackerLocation != null) {
            locationAreaList.add(stackerLocation.getMachineId().toString());
        }
        // 检查是否是站台点位
        AppStackerStand standLocation = stackerStandMap.get(location);
        if(standLocation != null) {
            locationAreaList.add(standLocation.getStackerId().toString());
            locationAreaList.add(standLocation.getAreaId());
        }
        // 检查是否是托盘输送点位
        AppTrayConveyLocation trayConveyLocation = trayConveyLocationMap.get(location);
        if(trayConveyLocation != null) {
            locationAreaList.add(trayConveyLocation.getAreaId());
        }
        // 检查是否是普通输送任务
        AppConveyLocation conveyLocation = conveyLocationMap.get(location);
        if(conveyLocation != null) {
            locationAreaList.add(conveyLocation.getAreaId());
        }
        if(locationAreaList.isEmpty()) {
            return null;
        }
        return locationAreaList.stream().distinct().toList();
    }

    /**
     * 获取两个区域的中转点
     * @param originArea 起点区域
     * @param destinationArea 终点区域
     * @return 中转点
     */
    private String getTransferLocation(String originArea, String destinationArea) {
        final String[] transferLocation = {null};
        locationAreaMap.forEach((location, areaList) -> {
            if(transferLocation[0] != null) {
                return;
            }
            if(areaList.contains(originArea) && areaList.contains(destinationArea)) {
                transferLocation[0] = location;
            }
        });
        return transferLocation[0];
    }



    /**
     * 检查一个点位的类型，若这个点位在多个类型中，则返回多个
     * @param location 待检查的点位
     * @return 该点位的类型
     */
    private List<LocationTypeEnum> getLocationType(String location) {
        if(AppStringUtils.isEmpty(location)) {
            return List.of(LocationTypeEnum.UNKNOWN);
        }
        List<LocationTypeEnum> locationTypeList = new ArrayList<>();
        // 检查是否是堆垛机点位
        AppStackerLocation stackerLocation = stackerLocationMap.get(location);
        if(stackerLocation != null) {
            locationTypeList.add(LocationTypeEnum.STACKER);
        }
        // 检查是否是站台点位
        AppStackerStand standLocation = stackerStandMap.get(location);
        if(standLocation != null) {
            locationTypeList.add(LocationTypeEnum.STACKER);
            locationTypeList.add(LocationTypeEnum.CONVEY);
        }
        // 检查是否是托盘输送点位
        AppTrayConveyLocation trayConveyLocation = trayConveyLocationMap.get(location);
        if(trayConveyLocation != null) {
            locationTypeList.add(LocationTypeEnum.TRAY_CONVEY);
        }
        // 检查是否是普通输送任务
        AppConveyLocation conveyLocation = conveyLocationMap.get(location);
        if(conveyLocation != null) {
            locationTypeList.add(LocationTypeEnum.CONVEY);
        }
        if(locationTypeList.isEmpty()) {
            return List.of(LocationTypeEnum.UNKNOWN);
        }
        return locationTypeList.stream().distinct().toList();
    }

    /**
     * 计算任务路径 ---- 目前仅支持一个中转点
     * @param origin 起点
     * @param destination 终点
     * @return 任务路径 <计算结果，路径>，若正常则计算结果为 null,不为 null则返回错误
     */
    public Tuple2<String, List<SimpleTask>> calculateTask(String origin, String destination) {
        if(AppStringUtils.isEmpty(origin) || AppStringUtils.isEmpty(destination)) {
            return new Tuple2<>("起点或者终点为空", null);
        }
        if(areas.isEmpty()) {
            return new Tuple2<>("没有区域信息，请先初始化或者检查基础资料", null);
        }
        /* 校验起点终点是否存在 */
        if(locations.isEmpty()) {
            summaryLocation(); // 获取位置
        }
        if(locations.isEmpty()) {
            return new Tuple2<>("没有位置信息，请先初始化或者检查基础资料", null);
        }
        if(!locations.contains(origin)) {
            return new Tuple2<>("起点不存在", null);
        }
        if(!locations.contains(destination)) {
            return new Tuple2<>("终点不存在", null);
        }
        List<String> originLocationAreas = getLocationArea(origin);
        if(originLocationAreas == null) {
            return new Tuple2<>("起点是不受支持的点位", null);
        }
        List<String> destinationLocationAreas = getLocationArea(destination);
        if(destinationLocationAreas == null) {
            return new Tuple2<>("终点是不受支持的点位", null);
        }
        // 判断起点和终点是否是同一种点位类型
        List<String> sameAreaList = originLocationAreas.stream().filter(destinationLocationAreas::contains).toList();
        if(!sameAreaList.isEmpty()) {
            // 不是空的，说明是同一种类型
            List<LocationTypeEnum> originLocationTypes = getLocationType(origin);
            List<LocationTypeEnum> destinationLocationTypes = getLocationType(destination);
            if(originLocationTypes.contains(LocationTypeEnum.UNKNOWN) || destinationLocationTypes.contains(LocationTypeEnum.UNKNOWN)) {
                return new Tuple2<>("起点和终点属于同一区域，但检索不到点位类型，请检查基础资料", null); // 正常不会发生
            }
            // 查找两个list中相同的项
            List<LocationTypeEnum> sameLocationType = originLocationTypes.stream().filter(destinationLocationTypes::contains).toList();
            if(sameLocationType.isEmpty()) {
                return new Tuple2<>("起点和终点属于同一区域，其点位类型不一致，不允许此设置，请检查区域设置是否合法", null);
            }
            SimpleTask simpleTask = new SimpleTask();
            simpleTask.setTaskType(SimpleTaskEnum.getSimpleTaskEnum(sameLocationType.getFirst()));
            simpleTask.setOrigin(origin);
            simpleTask.setDestination(destination);
            simpleTask.setTaskIndex(1);
            return new Tuple2<>(null, List.of(simpleTask));
        }
        // 不是同一类型的点位，跨区任务   ----- 目前仅支持一个中转点（葛林强：2025年8月13日）
        String transferLocation = null;
        for (String originLocationArea : originLocationAreas) {
            if(transferLocation != null) {
                break;
            }
            for (String destinationLocationArea : destinationLocationAreas) {
                transferLocation = getTransferLocation(originLocationArea, destinationLocationArea);
                if(transferLocation != null) {
                    break;
                }
            }
        }
        if(AppStringUtils.isEmpty(transferLocation)) {
            log.info("无法找到中转位置，目前仅支持一个中专点，起点：{}, 终点：{}，起点区域：{}, 终点区域：{}", origin, destination, String.join(";", originLocationAreas), String.join(";", destinationLocationAreas));
            return new Tuple2<>("无法找到中转位置", null);
        }
        // origin ---> transferLocation ---> destination
        List<SimpleTask> simpleTasks = new ArrayList<>();
        // 起点 ---> 中转
        // 不是空的，说明是同一种类型
        List<LocationTypeEnum> originLocationTypes = getLocationType(origin);
        List<LocationTypeEnum> transferLocationTypes = getLocationType(transferLocation);
        if(originLocationTypes.contains(LocationTypeEnum.UNKNOWN) || transferLocationTypes.contains(LocationTypeEnum.UNKNOWN)) {
            return new Tuple2<>("起点和中转点属于同一区域，但检索不到点位类型，请检查基础资料", null); // 正常不会发生
        }
        // 查找两个list中相同的项
        List<LocationTypeEnum> sameLocationType = originLocationTypes.stream().filter(transferLocationTypes::contains).toList();
        if(sameLocationType.isEmpty()) {
            return new Tuple2<>("起点和中转点属于同一区域，其点位类型不一致，不允许此设置，请检查区域设置是否合法", null);
        }
        SimpleTask simpleTask1 = new SimpleTask();
        simpleTask1.setOrigin(origin);
        simpleTask1.setDestination(transferLocation);
        simpleTask1.setTaskType(SimpleTaskEnum.getSimpleTaskEnum(sameLocationType.getFirst()));
        simpleTask1.setTaskIndex(1);
        simpleTasks.add(simpleTask1);
        // 中转点 ---> 目标点
        // 不是空的，说明是同一种类型
        List<LocationTypeEnum> destinationLocationTypes = getLocationType(destination);
        if(originLocationTypes.contains(LocationTypeEnum.UNKNOWN) || transferLocationTypes.contains(LocationTypeEnum.UNKNOWN)) {
            return new Tuple2<>("终点和中转点属于同一区域，但检索不到点位类型，请检查基础资料", null); // 正常不会发生
        }
        // 查找两个list中相同的项
        List<LocationTypeEnum> sameLocationType2 = destinationLocationTypes.stream().filter(transferLocationTypes::contains).toList();
        if(sameLocationType2.isEmpty()) {
            return new Tuple2<>("终点和中转点属于同一区域，其点位类型不一致，不允许此设置，请检查区域设置是否合法", null);
        }
        SimpleTask simpleTask2 = new SimpleTask();
        simpleTask1.setOrigin(origin);
        simpleTask1.setDestination(transferLocation);
        simpleTask1.setTaskType(SimpleTaskEnum.getSimpleTaskEnum(sameLocationType.getFirst()));
        simpleTask1.setTaskIndex(2);
        simpleTasks.add(simpleTask2);
        return new Tuple2<>(null, simpleTasks);
    }

    /**
     * 创建第一个自动任务的子任务
     * @param composeTask 组合任务
     * @return < 异常信息， 子任务 >
     */
    public Tuple2<String, AppStockSingleTask> createFirstAutoStockSingleTask(AppStockComposeTask composeTask) {
        Tuple2<String, List<SimpleTask>> calculateTaskResult = calculateTask(composeTask.getOrigin(), composeTask.getDestination());
        if(calculateTaskResult.getItem1() != null) {
            return new Tuple2<>(calculateTaskResult.getItem1(), null);
        }
        List<SimpleTask> simpleTaskList = calculateTaskResult.getItem2();
        if(simpleTaskList == null || simpleTaskList.isEmpty()) {
            return new Tuple2<>("任务路径无法计算", null);
        }
        SimpleTask simpleTask = simpleTaskList.getFirst();
        StockSingleTaskTypeEnum simpleTaskType = StockSingleTaskTypeEnum.getBySimpleTaskType(simpleTask.getTaskType());
        if(simpleTaskType == null || simpleTaskType == StockSingleTaskTypeEnum.UNKNOWN) {
            return new Tuple2<>("任务类型无法识别", null);
        }
        Integer newTaskId = plcTaskIdHelper.newTaskId();
        if(newTaskId == null || newTaskId == 0) {
            return new Tuple2<>("数据服务异常", null);
        }
        AppStockSingleTask appStockSingleTask = new AppStockSingleTask();
        appStockSingleTask.setTaskId(AppUUIDUtils.getNewUUID());
        appStockSingleTask.setTaskGroup(composeTask.getTaskGroup());
        appStockSingleTask.setPlcTaskId(newTaskId);
        appStockSingleTask.setUpperTaskId(composeTask.getTaskId());
        appStockSingleTask.setExecuteMachine(0);
        appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.STACKER_AUTO.getCode()); // 暂时赋值，下面会重新具体赋值
        appStockSingleTask.setOrigin(simpleTask.getOrigin());
        appStockSingleTask.setDestination(simpleTask.getDestination());
        appStockSingleTask.setComposeDestination(composeTask.getDestination());
        appStockSingleTask.setTaskStatus(StockSingleTaskStatusEnum.CREATE.getCode());
        appStockSingleTask.setCanCancel(TrueOrFalseEnum.TRUE.getCode());
        appStockSingleTask.setPriority(composeTask.getPriority());
        appStockSingleTask.setVehicleNo(composeTask.getVehicleNo());
        appStockSingleTask.setVehicleNoNumber(AppStringUtils.forceToInt(composeTask.getVehicleNo()));
        appStockSingleTask.setVehicleSize(composeTask.getVehicleSize());
        appStockSingleTask.setWeight(composeTask.getWeight());
        appStockSingleTask.setCreateTime(LocalDateTime.now());
        appStockSingleTask.setUpdateTime(LocalDateTime.now());
        appStockSingleTask.setTaskSource(composeTask.getTaskSource());
        appStockSingleTask.setCreatePerson(composeTask.getCreatePerson());
        // 堆垛机任务
        if(simpleTaskType == StockSingleTaskTypeEnum.STACKER_AUTO) {
            List<LocationTypeEnum> originLocationType = getLocationType(simpleTask.getOrigin());
            List<LocationTypeEnum> destinationLocationType = getLocationType(simpleTask.getDestination());
            if(originLocationType.contains(LocationTypeEnum.UNKNOWN) || destinationLocationType.contains(LocationTypeEnum.UNKNOWN)) {
                return new Tuple2<>("任务起点或目标位置未知", null);
            }
            // 检查其起点和终点是什么类型
            if(originLocationType.contains(LocationTypeEnum.STACKER) && destinationLocationType.contains(LocationTypeEnum.STACKER)) {
                appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.STACKER_MOVE.getCode());
            } else if(originLocationType.contains(LocationTypeEnum.CONVEY) && destinationLocationType.contains(LocationTypeEnum.STACKER)) {
                appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.STACKER_IN.getCode());
            }else if(originLocationType.contains(LocationTypeEnum.STACKER) && destinationLocationType.contains(LocationTypeEnum.CONVEY)) {
                appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.STACKER_OUT.getCode());
            }
            return new Tuple2<>(null, appStockSingleTask);
        } else if (simpleTaskType == StockSingleTaskTypeEnum.CONVEY_MOVE) {
            appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.CONVEY_MOVE.getCode());
            return new Tuple2<>(null, appStockSingleTask);
        } else if (simpleTaskType == StockSingleTaskTypeEnum.AGV) {
            appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.AGV.getCode());
            return new Tuple2<>(null, appStockSingleTask);
        } else if (simpleTaskType == StockSingleTaskTypeEnum.SHUTTLE) {
            appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.SHUTTLE.getCode());
            return new Tuple2<>(null, appStockSingleTask);
        }
        return new Tuple2<>("任务类型异常", null);
    }

    /**
     * 创建下一个自动任务的子任务
     * @param composeTask 组合任务
     * @param lastStockSingleTask 上一个子任务
     * @return < 错误信息， 子任务 >
     */
    public Tuple2<String, AppStockSingleTask> createNextAutoStockSingleTask(AppStockComposeTask composeTask, AppStockSingleTask lastStockSingleTask) {
        Tuple2<String, List<SimpleTask>> calculateTaskResult = calculateTask(lastStockSingleTask.getDestination(), composeTask.getDestination());
        if(calculateTaskResult.getItem1() != null) {
            return new Tuple2<>(calculateTaskResult.getItem1(), null);
        }
        List<SimpleTask> simpleTaskList = calculateTaskResult.getItem2();
        if(simpleTaskList == null || simpleTaskList.isEmpty()) {
            return new Tuple2<>("任务路径无法计算", null);
        }
        SimpleTask simpleTask = simpleTaskList.getFirst();
        StockSingleTaskTypeEnum simpleTaskType = StockSingleTaskTypeEnum.getBySimpleTaskType(simpleTask.getTaskType());
        if(simpleTaskType == null || simpleTaskType == StockSingleTaskTypeEnum.UNKNOWN) {
            return new Tuple2<>("任务类型无法识别", null);
        }
        Integer newTaskId = plcTaskIdHelper.newTaskId();
        if(newTaskId == null || newTaskId == 0) {
            return new Tuple2<>("数据服务异常", null);
        }
        AppStockSingleTask appStockSingleTask = new AppStockSingleTask();
        appStockSingleTask.setTaskId(AppUUIDUtils.getNewUUID());
        appStockSingleTask.setTaskGroup(composeTask.getTaskGroup());
        appStockSingleTask.setPlcTaskId(newTaskId);
        appStockSingleTask.setUpperTaskId(composeTask.getTaskId());
        appStockSingleTask.setExecuteMachine(0);
        appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.STACKER_AUTO.getCode()); // 暂时赋值，下面会重新具体赋值
        appStockSingleTask.setOrigin(simpleTask.getOrigin());
        appStockSingleTask.setDestination(simpleTask.getDestination());
        appStockSingleTask.setComposeDestination(composeTask.getDestination());
        appStockSingleTask.setTaskStatus(StockSingleTaskStatusEnum.CREATE.getCode());
        appStockSingleTask.setCanCancel(TrueOrFalseEnum.TRUE.getCode());
        appStockSingleTask.setPriority(composeTask.getPriority());
        appStockSingleTask.setVehicleNo(composeTask.getVehicleNo());
        appStockSingleTask.setVehicleNoNumber(AppStringUtils.forceToInt(composeTask.getVehicleNo()));
        appStockSingleTask.setVehicleSize(composeTask.getVehicleSize());
        appStockSingleTask.setWeight(composeTask.getWeight());
        appStockSingleTask.setCreateTime(LocalDateTime.now());
        appStockSingleTask.setUpdateTime(LocalDateTime.now());
        appStockSingleTask.setTaskSource(composeTask.getTaskSource());
        appStockSingleTask.setCreatePerson(composeTask.getCreatePerson());
        // 堆垛机任务
        if(simpleTaskType == StockSingleTaskTypeEnum.STACKER_AUTO) {
            List<LocationTypeEnum> originLocationType = getLocationType(simpleTask.getOrigin());
            List<LocationTypeEnum> destinationLocationType = getLocationType(simpleTask.getDestination());
            if(originLocationType.contains(LocationTypeEnum.UNKNOWN) || destinationLocationType.contains(LocationTypeEnum.UNKNOWN)) {
                return new Tuple2<>("任务起点或目标位置未知", null);
            }
            // 检查其起点和终点是什么类型
            if(originLocationType.contains(LocationTypeEnum.STACKER) && destinationLocationType.contains(LocationTypeEnum.STACKER)) {
                appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.STACKER_MOVE.getCode());
            } else if(originLocationType.contains(LocationTypeEnum.CONVEY) && destinationLocationType.contains(LocationTypeEnum.STACKER)) {
                appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.STACKER_IN.getCode());
            }else if(originLocationType.contains(LocationTypeEnum.STACKER) && destinationLocationType.contains(LocationTypeEnum.CONVEY)) {
                appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.STACKER_OUT.getCode());
            }
            return new Tuple2<>(null, appStockSingleTask);
        } else if (simpleTaskType == StockSingleTaskTypeEnum.CONVEY_MOVE) {
            appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.CONVEY_MOVE.getCode());
            return new Tuple2<>(null, appStockSingleTask);
        } else if (simpleTaskType == StockSingleTaskTypeEnum.AGV) {
            appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.AGV.getCode());
            return new Tuple2<>(null, appStockSingleTask);
        } else if (simpleTaskType == StockSingleTaskTypeEnum.SHUTTLE) {
            appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.SHUTTLE.getCode());
            return new Tuple2<>(null, appStockSingleTask);
        }
        return new Tuple2<>("任务类型异常", null);
    }

    /**
     * 创建子任务 --- 如果不是入库任务需要判断起点是不是为空，如果为空则不调用此方法
     * @param composeTask 组合任务
     * @param origin 起点
     * @param destination 目标位置
     * @return 子任务
     */
    public Tuple2<String, AppStockSingleTask> createStockSingleTask(AppStockComposeTask composeTask, String origin, String destination) {
        Integer newTaskId = plcTaskIdHelper.newTaskId(); // 获取PLC任务ID
        if(newTaskId == null || newTaskId == 0) {
            return new Tuple2<>("数据服务异常", null);
        }
        if(composeTask.getTaskType().equals(StockComposeTaskTypeEnum.IN.getCode()) && AppStringUtils.isEmpty(composeTask.getOrigin()) && AppStringUtils.isNotEmpty(destination)) { // 入库任务并且起点是空的默认只生成一个堆垛机入库任务
            AppStockSingleTask appStockSingleTask = new AppStockSingleTask();
            appStockSingleTask.setTaskId(AppUUIDUtils.getNewUUID());
            appStockSingleTask.setTaskGroup(composeTask.getTaskGroup());
            appStockSingleTask.setPlcTaskId(newTaskId);
            appStockSingleTask.setUpperTaskId(composeTask.getTaskId());
            appStockSingleTask.setExecuteMachine(StockExecuteEquipmentEnum.STACKER.getCode());
            appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.STACKER_IN.getCode());
            appStockSingleTask.setOrigin(origin);
            appStockSingleTask.setDestination(destination);
            appStockSingleTask.setComposeDestination(composeTask.getDestination());
            appStockSingleTask.setTaskStatus(StockSingleTaskStatusEnum.CREATE.getCode());
            appStockSingleTask.setCanCancel(TrueOrFalseEnum.TRUE.getCode());
            appStockSingleTask.setPriority(composeTask.getPriority());
            appStockSingleTask.setVehicleNo(composeTask.getVehicleNo());
            appStockSingleTask.setVehicleNoNumber(AppStringUtils.forceToInt(composeTask.getVehicleNo()));
            appStockSingleTask.setVehicleSize(composeTask.getVehicleSize());
            appStockSingleTask.setWeight(composeTask.getWeight());
            appStockSingleTask.setCreateTime(LocalDateTime.now());
            appStockSingleTask.setUpdateTime(LocalDateTime.now());
            appStockSingleTask.setTaskSource(composeTask.getTaskSource());
            appStockSingleTask.setCreatePerson(composeTask.getCreatePerson());
            return new Tuple2<>(null, appStockSingleTask);
        }
        if(composeTask.getTaskType().equals(StockComposeTaskTypeEnum.OUT.getCode()) && AppStringUtils.isEmpty(composeTask.getDestination()) && AppStringUtils.isNotEmpty(origin)) { // 出库任务并且终点是空的默认只生成一个堆垛机出库任务
            AppStockSingleTask appStockSingleTask = new AppStockSingleTask();
            appStockSingleTask.setTaskId(AppUUIDUtils.getNewUUID());
            appStockSingleTask.setTaskGroup(composeTask.getTaskGroup());
            appStockSingleTask.setPlcTaskId(newTaskId);
            appStockSingleTask.setUpperTaskId(composeTask.getTaskId());
            appStockSingleTask.setExecuteMachine(StockExecuteEquipmentEnum.STACKER.getCode());
            appStockSingleTask.setTaskType(StockSingleTaskTypeEnum.STACKER_OUT.getCode());
            appStockSingleTask.setOrigin(origin);
            appStockSingleTask.setDestination(destination);
            appStockSingleTask.setComposeDestination(composeTask.getDestination());
            appStockSingleTask.setTaskStatus(StockSingleTaskStatusEnum.CREATE.getCode());
            appStockSingleTask.setCanCancel(TrueOrFalseEnum.TRUE.getCode());
            appStockSingleTask.setPriority(composeTask.getPriority());
            appStockSingleTask.setVehicleNo(composeTask.getVehicleNo());
            appStockSingleTask.setVehicleNoNumber(AppStringUtils.forceToInt(composeTask.getVehicleNo()));
            appStockSingleTask.setVehicleSize(composeTask.getVehicleSize());
            appStockSingleTask.setWeight(composeTask.getWeight());
            appStockSingleTask.setCreateTime(LocalDateTime.now());
            appStockSingleTask.setUpdateTime(LocalDateTime.now());
            appStockSingleTask.setTaskSource(composeTask.getTaskSource());
            appStockSingleTask.setCreatePerson(composeTask.getCreatePerson());
            return new Tuple2<>(null, appStockSingleTask);
        }
        if(AppStringUtils.isEmpty(destination)) {
            return new Tuple2<>("目标位置不能为空", null);
        }
        // 其他任务，动态计算路径 ---- 注意：此处算的如果是输送线任务是直接到独立任务表，不是到单独的 输送线任务表
        if(AppStringUtils.isEmpty(origin)) {
            return new Tuple2<>("起点位置不能为空", null); // 该判断需在调用本方法之前判断，否则任务会被以异常状态取消
        }
        List<Tuple2<LocationTypeEnum, String>> courseCalculateResult = locationManage.courseCalculate(origin, destination);
        if(courseCalculateResult == null || courseCalculateResult.isEmpty()) {
            return new Tuple2<>("无法计算路径", null);
        }
        if(courseCalculateResult.size() < 2) {
            return new Tuple2<>("计算的路径不正确", null);
        }
        Tuple2<LocationTypeEnum, String> originCourseInfo = courseCalculateResult.getFirst(); // 取第一个路径
        Tuple2<LocationTypeEnum, String> destinationCourseInfo = courseCalculateResult.get(1);
        // 生成任务
        StockExecuteEquipmentEnum executeEquipment = StockExecuteEquipmentEnum.getExecuteEquipment(originCourseInfo.getItem1());
        StockSingleTaskTypeEnum simpleTaskType = StockSingleTaskTypeEnum.getByComposeTaskTypeAndExecuteMachine(StockComposeTaskTypeEnum.getByCode(composeTask.getTaskType()), executeEquipment);

        AppStockSingleTask appStockSingleTask = new AppStockSingleTask();
        appStockSingleTask.setTaskId(AppUUIDUtils.getNewUUID());
        appStockSingleTask.setTaskGroup(composeTask.getTaskGroup());
        appStockSingleTask.setPlcTaskId(newTaskId);
        appStockSingleTask.setUpperTaskId(composeTask.getTaskId());
        appStockSingleTask.setExecuteMachine(executeEquipment.getCode());
        appStockSingleTask.setTaskType(simpleTaskType.getCode());
        appStockSingleTask.setOrigin(originCourseInfo.getItem2());
        appStockSingleTask.setDestination(destinationCourseInfo.getItem2());
        appStockSingleTask.setComposeDestination(composeTask.getDestination());
        appStockSingleTask.setTaskStatus(StockSingleTaskStatusEnum.CREATE.getCode());
        appStockSingleTask.setCanCancel(TrueOrFalseEnum.TRUE.getCode());
        appStockSingleTask.setPriority(composeTask.getPriority());
        appStockSingleTask.setVehicleNo(composeTask.getVehicleNo());
        appStockSingleTask.setVehicleNoNumber(AppStringUtils.forceToInt(composeTask.getVehicleNo()));
        appStockSingleTask.setVehicleSize(composeTask.getVehicleSize());
        appStockSingleTask.setWeight(composeTask.getWeight());
        appStockSingleTask.setCreateTime(LocalDateTime.now());
        appStockSingleTask.setUpdateTime(LocalDateTime.now());
        appStockSingleTask.setTaskSource(composeTask.getTaskSource());
        appStockSingleTask.setCreatePerson(composeTask.getCreatePerson());
        return new Tuple2<>(null, appStockSingleTask);
    }


    /**
     * 创建入库任务
     *
     * @param composeTask 组合任务
     * @return 入库任务结果
     */
    public Tuple2<String, AppStockSingleTask> createStockInSingleTask(AppStockComposeTask composeTask) {
        String origin = composeTask.getOrigin();
        String destination = composeTask.getDestination();
        if(AppStringUtils.isEmpty(origin) && AppStringUtils.isEmpty(destination)) {
            return new Tuple2<>("起点或者终点都为空", null);
        }
        List<String> originLocationAreas = getLocationArea(origin);
        List<String> destinationLocationAreas = getLocationArea(destination);
        if(originLocationAreas == null && destinationLocationAreas == null) {
            return new Tuple2<>("起点和终点均是不受支持的点位", null);
        }
        // 入库任务，以终点为最终目标
        // 判断终点点位类型
        List<LocationTypeEnum> destinationLocationTypes = getLocationType(destination);
        if(destinationLocationTypes.contains(LocationTypeEnum.UNKNOWN)) {
            return new Tuple2<>("终点点位类型未知", null);
        }
        // 这里终点只能有一个点位类型，多个计报错
        if(destinationLocationTypes.size() > 1) {
            return new Tuple2<>("终点点位类型不能为多个，请检查基础资料", null);
        }
        SimpleTaskEnum simpleTaskEnum = SimpleTaskEnum.getSimpleTaskEnum(destinationLocationTypes.getFirst());
        StockSingleTaskTypeEnum simpleTaskType = StockSingleTaskTypeEnum.getBySimpleTaskType(simpleTaskEnum);
        if(simpleTaskEnum.equals(SimpleTaskEnum.STACKER)) {
            simpleTaskType = StockSingleTaskTypeEnum.STACKER_IN;
        }
        Integer newTaskId = plcTaskIdHelper.newTaskId();
        if(newTaskId == null || newTaskId == 0) {
            return new Tuple2<>("数据服务异常", null);
        }
        AppStockSingleTask appStockSingleTask = new AppStockSingleTask();
        appStockSingleTask.setTaskId(AppUUIDUtils.getNewUUID());
        appStockSingleTask.setTaskGroup(composeTask.getTaskGroup());
        appStockSingleTask.setPlcTaskId(newTaskId);
        appStockSingleTask.setUpperTaskId(composeTask.getTaskId());
        appStockSingleTask.setExecuteMachine(StockExecuteEquipmentEnum.STACKER.getCode());
        appStockSingleTask.setTaskType(simpleTaskType.getCode());
        appStockSingleTask.setOrigin(origin);
        appStockSingleTask.setDestination(destination);
        appStockSingleTask.setComposeDestination(composeTask.getDestination());
        appStockSingleTask.setTaskStatus(StockSingleTaskStatusEnum.CREATE.getCode());
        appStockSingleTask.setCanCancel(TrueOrFalseEnum.TRUE.getCode());
        appStockSingleTask.setPriority(composeTask.getPriority());
        appStockSingleTask.setVehicleNo(composeTask.getVehicleNo());
        appStockSingleTask.setVehicleNoNumber(AppStringUtils.forceToInt(composeTask.getVehicleNo()));
        appStockSingleTask.setVehicleSize(composeTask.getVehicleSize());
        appStockSingleTask.setWeight(composeTask.getWeight());
        appStockSingleTask.setCreateTime(LocalDateTime.now());
        appStockSingleTask.setUpdateTime(LocalDateTime.now());
        appStockSingleTask.setTaskSource(composeTask.getTaskSource());
        appStockSingleTask.setCreatePerson(composeTask.getCreatePerson());
        return new Tuple2<>(null, appStockSingleTask);
    }


    /**
     * 创建出库任务
     *
     * @param composeTask 组合任务
     * @return 出库任务结果
     */
    public Tuple2<String, AppStockSingleTask> createStockOutSingleTask(AppStockComposeTask composeTask) {
        String origin = composeTask.getOrigin();
        String destination = composeTask.getDestination();
        if(AppStringUtils.isEmpty(origin) && AppStringUtils.isEmpty(destination)) {
            return new Tuple2<>("起点或者终点都为空", null);
        }
        List<String> originLocationAreas = getLocationArea(origin);
        List<String> destinationLocationAreas = getLocationArea(destination);
        if(originLocationAreas == null && destinationLocationAreas == null) {
            return new Tuple2<>("起点和终点均是不受支持的点位", null);
        }
        // 出库任务，以起点为最终数据
        // 判断起点点位类型
        List<LocationTypeEnum> originLocationTypes = getLocationType(origin);
        if(originLocationTypes.contains(LocationTypeEnum.UNKNOWN)) {
            return new Tuple2<>("起点点位类型未知", null);
        }
        // 这里起点只能有一个点位类型，多个计报错
        if(originLocationTypes.size() > 1) {
            return new Tuple2<>("起点点位类型不能为多个，请检查基础资料", null);
        }
        SimpleTaskEnum simpleTaskEnum = SimpleTaskEnum.getSimpleTaskEnum(originLocationTypes.getFirst());
        StockSingleTaskTypeEnum simpleTaskType = StockSingleTaskTypeEnum.getBySimpleTaskType(simpleTaskEnum);
        if(simpleTaskEnum.equals(SimpleTaskEnum.STACKER)) {
            simpleTaskType = StockSingleTaskTypeEnum.STACKER_OUT;
        }
        Integer newTaskId = plcTaskIdHelper.newTaskId();
        if(newTaskId == null || newTaskId == 0) {
            return new Tuple2<>("数据服务异常", null);
        }
        AppStockSingleTask appStockSingleTask = new AppStockSingleTask();
        appStockSingleTask.setTaskId(AppUUIDUtils.getNewUUID());
        appStockSingleTask.setTaskGroup(composeTask.getTaskGroup());
        appStockSingleTask.setPlcTaskId(newTaskId);
        appStockSingleTask.setUpperTaskId(composeTask.getTaskId());
        appStockSingleTask.setExecuteMachine(StockExecuteEquipmentEnum.STACKER.getCode());
        appStockSingleTask.setTaskType(simpleTaskType.getCode());
        appStockSingleTask.setOrigin(origin);
        appStockSingleTask.setDestination(destination);
        appStockSingleTask.setComposeDestination(composeTask.getDestination());
        appStockSingleTask.setTaskStatus(StockSingleTaskStatusEnum.CREATE.getCode());
        appStockSingleTask.setCanCancel(TrueOrFalseEnum.TRUE.getCode());
        appStockSingleTask.setPriority(composeTask.getPriority());
        appStockSingleTask.setVehicleNo(composeTask.getVehicleNo());
        appStockSingleTask.setVehicleNoNumber(AppStringUtils.forceToInt(composeTask.getVehicleNo()));
        appStockSingleTask.setVehicleSize(composeTask.getVehicleSize());
        appStockSingleTask.setWeight(composeTask.getWeight());
        appStockSingleTask.setCreateTime(LocalDateTime.now());
        appStockSingleTask.setUpdateTime(LocalDateTime.now());
        appStockSingleTask.setTaskSource(composeTask.getTaskSource());
        appStockSingleTask.setCreatePerson(composeTask.getCreatePerson());
        return new Tuple2<>(null, appStockSingleTask);
    }

    /**
     * 创建移库任务
     *
     * @param composeTask 组合任务
     * @return 移库任务结果
     */
    public Tuple2<String, AppStockSingleTask> createStockMoveSingleTask(AppStockComposeTask composeTask) {
        String origin = composeTask.getOrigin();
        String destination = composeTask.getDestination();
        if(AppStringUtils.isEmpty(origin) && AppStringUtils.isEmpty(destination)) {
            return new Tuple2<>("起点或者终点都为空", null);
        }
        // 移库任务
        List<String> originLocationAreas = getLocationArea(origin);
        if(originLocationAreas == null) {
            return new Tuple2<>("起点是不受支持的点位", null);
        }
        List<String> destinationLocationAreas = getLocationArea(destination);
        if(destinationLocationAreas == null) {
            return new Tuple2<>("终点是不受支持的点位", null);
        }
        // 判断起点和终点是否是同一种点位区域
        List<String> sameAreaList = originLocationAreas.stream().filter(destinationLocationAreas::contains).toList();
        if(sameAreaList.isEmpty()) {
            return new Tuple2<>("起点和终点不是同区域点位", null);
        }
        // 不是空的，说明是同一种类型
        List<LocationTypeEnum> originLocationTypes = getLocationType(origin);
        List<LocationTypeEnum> destinationLocationTypes = getLocationType(destination);
        if(originLocationTypes.contains(LocationTypeEnum.UNKNOWN) || destinationLocationTypes.contains(LocationTypeEnum.UNKNOWN)) {
            return new Tuple2<>("起点和终点属于同一区域，但检索不到点位类型，请检查基础资料", null); // 正常不会发生
        }
        // 查找两个list中相同的项
        List<LocationTypeEnum> sameLocationType = originLocationTypes.stream().filter(destinationLocationTypes::contains).toList();
        if(sameLocationType.isEmpty()) {
            return new Tuple2<>("起点和终点属于同一区域，其点位类型不一致，不允许此设置，请检查区域设置是否合法", null);
        }
        SimpleTaskEnum simpleTaskEnum = SimpleTaskEnum.getSimpleTaskEnum(sameLocationType.getFirst());
        StockSingleTaskTypeEnum simpleTaskType = StockSingleTaskTypeEnum.getBySimpleTaskType(simpleTaskEnum);
        if(simpleTaskEnum.equals(SimpleTaskEnum.STACKER)) {
            simpleTaskType = StockSingleTaskTypeEnum.STACKER_MOVE;
        }
        Integer newTaskId = plcTaskIdHelper.newTaskId();
        if(newTaskId == null || newTaskId == 0) {
            return new Tuple2<>("数据服务异常", null);
        }
        AppStockSingleTask appStockSingleTask = new AppStockSingleTask();
        appStockSingleTask.setTaskId(AppUUIDUtils.getNewUUID());
        appStockSingleTask.setTaskGroup(composeTask.getTaskGroup());
        appStockSingleTask.setPlcTaskId(newTaskId);
        appStockSingleTask.setUpperTaskId(composeTask.getTaskId());
        appStockSingleTask.setExecuteMachine(StockExecuteEquipmentEnum.STACKER.getCode());
        appStockSingleTask.setTaskType(simpleTaskType.getCode());
        appStockSingleTask.setOrigin(origin);
        appStockSingleTask.setDestination(destination);
        appStockSingleTask.setComposeDestination(composeTask.getDestination());
        appStockSingleTask.setTaskStatus(StockSingleTaskStatusEnum.CREATE.getCode());
        appStockSingleTask.setCanCancel(TrueOrFalseEnum.TRUE.getCode());
        appStockSingleTask.setPriority(composeTask.getPriority());
        appStockSingleTask.setVehicleNo(composeTask.getVehicleNo());
        appStockSingleTask.setVehicleNoNumber(AppStringUtils.forceToInt(composeTask.getVehicleNo()));
        appStockSingleTask.setVehicleSize(composeTask.getVehicleSize());
        appStockSingleTask.setWeight(composeTask.getWeight());
        appStockSingleTask.setCreateTime(LocalDateTime.now());
        appStockSingleTask.setUpdateTime(LocalDateTime.now());
        appStockSingleTask.setTaskSource(composeTask.getTaskSource());
        appStockSingleTask.setCreatePerson(composeTask.getCreatePerson());
        return new Tuple2<>(null, appStockSingleTask);
    }
}
