package com.wms.service.business.serviceImplements;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.wms.constants.enums.*;
import com.wms.entity.app.ResponseEntity;
import com.wms.entity.app.wcs.WcsStandTaskRequest;
import com.wms.entity.app.wcs.WcsTaskRequest;
import com.wms.entity.table.*;
import com.wms.service.*;
import com.wms.service.business.IWmsJobService;
import com.wms.utils.HttpUtils;
import com.wms.utils.StringUtils;
import com.wms.utils.WmsUtils;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.time.LocalDateTime;
import java.util.*;

import static com.wms.config.InitLocalConfig.configMap;
import static com.wms.config.InitLocalConfig.instantLocationMap;
import static com.wms.utils.StringUtils.convertJsonString;

/**
 * Wms定时任务服务实现
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class WmsJobServiceImplements implements IWmsJobService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());// 日志
    private final LogService logService;// 日志服务
    private final TaskService taskService;// 任务服务
    private final PickTaskService pickTaskService;// 拣选任务服务
    private final OutsideVehiclesService outsideVehiclesService;// 流转中箱子服务
    private final StandService standService;// 站台服务

    /**
     * 发送正常的任务
     */
    @Override
    public void sendCommonTasks() throws Exception {
        try {
            // 检索任务表---新建未下发的任务
            LambdaQueryWrapper<Task> waitForDistributeTaskQuery = new LambdaQueryWrapper<Task>()
                    .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode());
            List<Task> allTasks = taskService.list(waitForDistributeTaskQuery);
            if (!allTasks.isEmpty()) {
                String max_wcs_accept_nums = configMap.get(ConfigMapKeyEnum.MAX_WCS_ACCEPT_NUMS.getConfigKey());
                if (StringUtils.isEmpty(max_wcs_accept_nums)) {
                    logger.error("配置未生成");
                    return;
                }
                int maxWcsAcceptNums = Integer.parseInt(max_wcs_accept_nums);
                // 需要发送给wcs的任务列表
                List<WcsTaskRequest> request = new ArrayList<>();
                // 已经下发的任务组列表
                List<String> taskGroupIds = new ArrayList<>();
                // 这里单独处理站台拣选出库以外的任务
                for (Task task : allTasks) {
                    if (request.size() >= maxWcsAcceptNums) {
                        // 每次给wcs下发数量
                        break;
                    }
                    if (taskGroupIds.contains(task.getTaskGroup())) {
                        // 该任务组已经下发
                        continue;
                    }
                    if (StringUtils.isNotEmpty(task.getPreTask())) {// 当前任务具有前置任务
                        // 查询一下前置的任务有没有存在，存在则不下发
                        if (taskService.exists(new LambdaQueryWrapper<Task>().eq(Task::getTaskId, task.getPreTask()))) {
                            continue;
                        }
                    }
                    if (task.getTaskPriority() == 1) {
                        if (Objects.equals(task.getTaskType(), TaskType.OUT.getCode())
                                && task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())) {
                            continue;
                        }
                    }
                    // 创建发送的任务
                    WcsTaskRequest tempTask = new WcsTaskRequest();
                    tempTask.setTaskId(task.getTaskGroup());
                    if (Objects.equals(task.getTaskType(), TaskType.INVENTORY.getCode())) {
                        tempTask.setTaskType(TaskType.OUT.getCode());
                    } else {
                        tempTask.setTaskType(task.getTaskType());
                    }
                    tempTask.setOrigin(task.getOrigin());
                    tempTask.setDestination(task.getDestination());
                    tempTask.setVehicleNo(task.getVehicleId());
                    tempTask.setVehicleSize(task.getVehicleSize());
                    tempTask.setWeight(task.getWeight());
                    tempTask.setPriority(task.getTaskPriority());
                    request.add(tempTask);
                    // 已经发送过的任务组
                    taskGroupIds.add(task.getTaskGroup());
                }
                if (request.size() == 0) {
                    // 没有新任务发送
                    return;
                }
                // 发送任务
                String url = configMap.get(ConfigMapKeyEnum.URL_WCS_TASK.getConfigKey());
                if (url != null) {
                    logger.info("向WCS发送任务，地址：{}，请求详情：{}", url, convertJsonString(request));
                    ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(url, convertJsonString(request)), ResponseEntity.class);
                    try {
                        logService.save(new WmsLog(WmsUtils.generateId("LOG_"), "向WCS发送任务", "SetStackerTask", JSON.toJSONString(request), JSON.toJSONString(result), url, LocalDateTime.now(), "WMS"));
                    } catch (Exception e) {
                        logger.error("插入日志错误。");
                    }
                    if (result == null) {
                        logger.error("发送任务异常。");
                    } else {
                        if (Objects.equals(ResponseCode.OK.getCode(), result.getCode())) {
                            logger.info("发送WCS任务成功。");
                            taskService.update(new LambdaUpdateWrapper<Task>()
                                    .set(Task::getTaskStatus, WmsTaskStatus.WAIT.getCode())
                                    .in(Task::getTaskGroup, taskGroupIds)
                                    .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode()));
                        } else {
                            // 判断returnData的数据
                            if (result.getReturnData() != null) {
                                List<WcsTaskRequest> errorTasks = JSON.parseArray(result.getReturnData().toString(), WcsTaskRequest.class);
                                if (!errorTasks.isEmpty()) {
                                    List<String> failedTaskIds = errorTasks.stream().map(WcsTaskRequest::getTaskId).distinct().toList();
                                    // 更新任务状态为异常
                                    taskService.update(new LambdaUpdateWrapper<Task>()
                                            .set(Task::getTaskStatus, WmsTaskStatus.EXCEPTION.getCode())
                                            .in(Task::getTaskGroup, failedTaskIds)
                                            .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode()));
                                }
                            }
                            logger.error("发送任务错误：{}", convertJsonString(result));
                        }
                    }
                } else {
                    logger.error("WCS发送任务地址为空。");
                }
            }
        } catch (Exception exception) {
            logger.error("向WCS发送任务时发生异常：{}", convertJsonString(exception));
            throw new Exception("向WCS发送任务时发生异常。");
        }
    }

    /**
     * 发送PickOut任务
     * @throws Exception 异常
     */
    @Override
    public void sendPickOutTasks() throws Exception {
        try {
            // 检索任务表---新建未下发的任务
            LambdaQueryWrapper<Task> waitForDistributeTaskQuery = new LambdaQueryWrapper<Task>()
                    .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode())
                    .eq(Task::getTaskType, TaskType.OUT.getCode())
                    .eq(Task::getTaskPriority, 1);
            List<Task> allTasks = taskService.list(waitForDistributeTaskQuery);
            if (!allTasks.isEmpty()) {
                String max_vehicle_nums = configMap.get(ConfigMapKeyEnum.MAX_VEHICLE_NUMS.getConfigKey());
                String max_wcs_accept_nums = configMap.get(ConfigMapKeyEnum.MAX_WCS_ACCEPT_NUMS.getConfigKey());
                if (StringUtils.isEmpty(max_vehicle_nums) || StringUtils.isEmpty(max_wcs_accept_nums)) {
                    logger.error("配置未生成");
                    return;
                }
                int maxVehicleNums = Integer.parseInt(max_vehicle_nums);
                int maxWcsAcceptNums = Integer.parseInt(max_wcs_accept_nums);// wcs最大一次性可接受任务数量
                List<String> outsideVehicles = outsideVehiclesService.selectDistinctVehicles();
                if (outsideVehicles == null || outsideVehicles.isEmpty()) {
                    outsideVehicles = Collections.emptyList();
                }
                int remainVehicleNums = maxVehicleNums - outsideVehicles.size();// 线体剩余箱子数量
                if (remainVehicleNums <= 0) {
                    return;
                }

                // 需要发送给wcs的任务列表
                List<WcsTaskRequest> request = new ArrayList<>();
                // 已经下发的任务组列表
                List<String> taskGroupIds = new ArrayList<>();
                // 本次生成的箱子
                List<String> pickVehicleIds = new ArrayList<>();
                // 本次跳过的箱子
                List<String> skipVehicleIds = new ArrayList<>();
                // 查找所有站台拣选任务
                List<PickTask> standPickTasks = pickTaskService.list();
                // 生成一个Map，计算每个站台已经出库的拣选任务
                Map<String, Integer> outPickTaskMap = new HashMap<>();
                Map<String, Integer> updatedOutPickTaskMap = new HashMap<>();
                // 轮询工作站台，判断是否需要下发任务
                List<Stand> stands = standService.list(new LambdaQueryWrapper<Stand>()
                        .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0)
                        .eq(Stand::getStandType, 2));
                for (Stand workStation : stands) {
                    outPickTaskMap.put(workStation.getStandId(), workStation.getPickVehicleCount());
                    updatedOutPickTaskMap.put(workStation.getStandId(), workStation.getPickVehicleCount());
                }
                // 轮询堆垛机状态
                List<Stand> stackerList = standService.list(new LambdaQueryWrapper<Stand>()
                        .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0)
                        .eq(Stand::getStandType, 3));
                List<Task> stackRunningTasks = taskService.list(new LambdaQueryWrapper<Task>()
                        .eq(Task::getTaskType, TaskType.OUT.getCode())
                        .and(wrapper -> wrapper.eq(Task::getTaskStatus, WmsTaskStatus.WAIT.getCode())
                                .or().eq(Task::getTaskStatus, WmsTaskStatus.RUN.getCode())));
                Map<Integer, Integer> runningTaskNumToEquipmentMap = new HashMap<>();
                for (Stand stacker : stackerList) {
                    // 找这台堆垛机正在执行的拣选出库任务数量
                    runningTaskNumToEquipmentMap.put(stacker.getEquipmentId(), 0);
                }
                // 生成堆垛机可用列表
                for (Task tempStackRunningTask : stackRunningTasks) {
                    if (instantLocationMap.containsKey(tempStackRunningTask.getOrigin())) {
                        int key = instantLocationMap.get(tempStackRunningTask.getOrigin()).getEquipmentId();
                        if (runningTaskNumToEquipmentMap.isEmpty()) {
                            // 没有可用堆垛机
                            break;
                        }
                        if (runningTaskNumToEquipmentMap.containsKey(key)) {
                            if (runningTaskNumToEquipmentMap.get(key) >= 3) {
                                runningTaskNumToEquipmentMap.remove(key);
                            } else {
                                runningTaskNumToEquipmentMap.replace(key, runningTaskNumToEquipmentMap.get(key) + 1);
                            }
                        }
                    }
                }
                if (runningTaskNumToEquipmentMap.isEmpty()) {
                    // 没有可用堆垛机
                    return;
                }
                // 还有可用堆垛机
                while(!runningTaskNumToEquipmentMap.isEmpty()) {
                    if (request.size() >= maxWcsAcceptNums || remainVehicleNums <= 0) {
                        // 超过wcs一次可接受数量
                        break;
                    }
                    // 先找出目前数量最少的站台
                    String standId = outPickTaskMap.entrySet().stream()
                            .min(Comparator.comparingInt(Map.Entry::getValue))
                            .map(Map.Entry::getKey)
                            .orElse("");
                    List<String> vehicleIds;
                    if (StringUtils.isNotEmpty(standId)) {
                        // 查找这个站台未下发的料箱
                        vehicleIds = standPickTasks.stream()
                                .filter(pickTask -> pickTask.getStandId().equals(standId) && pickTask.getPickStatus().equals(PickTaskStatusEnum.TEMP.getCode())
                                        && !pickVehicleIds.contains(pickTask.getVehicleId())
                                && !skipVehicleIds.contains(pickTask.getVehicleId()))
                                .map(PickTask::getVehicleId)
                                .distinct()
                                .toList();
                        if (vehicleIds.isEmpty()) {
                            outPickTaskMap.remove(standId);
                            continue;
                        }
                    } else {
                        vehicleIds = standPickTasks.stream()
                                .filter(pickTask -> pickTask.getPickStatus().equals(PickTaskStatusEnum.TEMP.getCode())
                                        && !pickVehicleIds.contains(pickTask.getVehicleId())
                                        && !skipVehicleIds.contains(pickTask.getVehicleId()))
                                .map(PickTask::getVehicleId)
                                .distinct()
                                .toList();
                        if (vehicleIds.isEmpty()) {
                            break;
                        }
                    }
                    // 生成箱子-站台数量的Map
                    Map<String, Integer> vehicleStandsMap = new HashMap<>();
                    standPickTasks.forEach(pickTask -> {
                        if (vehicleIds.contains(pickTask.getVehicleId())) {
                            vehicleStandsMap.put(pickTask.getVehicleId(),
                                    vehicleStandsMap.getOrDefault(pickTask.getVehicleId(), 0) + 1);
                        }
                    });
                    // 最多使用的箱子
                    String maxVehicleId = vehicleStandsMap.entrySet().stream()
                            .max(Comparator.comparingInt(Map.Entry::getValue))
                            .map(Map.Entry::getKey)
                            .orElse("");
                    if (!StringUtils.isEmpty(maxVehicleId)) {
                        // 找到这个箱子的任务
                        List<Task> outPickTasks = allTasks.stream().filter(task -> task.getVehicleId().equals(maxVehicleId) && !pickVehicleIds.contains(task.getVehicleId())
                                && task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())).toList();
                        if (!outPickTasks.isEmpty()) {
                            // 更新每个站台的拣选箱数量
                            List<String> maxStandIds = standPickTasks.stream()
                                    .filter(pickTask -> pickTask.getVehicleId().equals(maxVehicleId))
                                    .map(PickTask::getStandId)
                                    .distinct()
                                    .toList();
                            // 给当前设备号+1
                            int equipmentId = instantLocationMap.get(outPickTasks.get(0).getOrigin()).getEquipmentId();
                            if (runningTaskNumToEquipmentMap.containsKey(equipmentId)) {
                                boolean flag = false;
                                for (Task task : outPickTasks) {
                                    if (taskGroupIds.contains(task.getTaskGroup())) {
                                        // 该任务组已经下发
                                        continue;
                                    }
                                    if (StringUtils.isNotEmpty(task.getPreTask())) {// 当前任务具有前置任务
                                        // 查询一下前置的任务有没有存在，存在则不下发
                                        if (taskService.exists(new LambdaQueryWrapper<Task>().eq(Task::getTaskId, task.getPreTask()))) {
                                            continue;
                                        }
                                    }
                                    // 创建发送的任务
                                    WcsTaskRequest tempTask = new WcsTaskRequest();
                                    tempTask.setTaskId(task.getTaskGroup());
                                    tempTask.setTaskType(task.getTaskType());
                                    tempTask.setOrigin(task.getOrigin());
                                    tempTask.setDestination(task.getDestination());
                                    tempTask.setVehicleNo(task.getVehicleId());
                                    tempTask.setVehicleSize(task.getVehicleSize());
                                    tempTask.setWeight(task.getWeight());
                                    tempTask.setPriority(task.getTaskPriority());
                                    request.add(tempTask);
                                    // 已经发送过的任务组
                                    taskGroupIds.add(task.getTaskGroup());
                                    flag = true;
                                }
                                if (flag) {
                                    if (!maxStandIds.isEmpty()) {
                                        maxStandIds.forEach(tempStandId -> {
                                            outPickTaskMap.put(tempStandId, outPickTaskMap.getOrDefault(tempStandId, 0) + 1);
                                            updatedOutPickTaskMap.put(tempStandId, updatedOutPickTaskMap.getOrDefault(tempStandId, 0) + 1);
                                        });
                                    }
                                    runningTaskNumToEquipmentMap.replace(equipmentId, runningTaskNumToEquipmentMap.get(equipmentId) + 1);
                                    // 已经发送过的vehicleId
                                    pickVehicleIds.add(maxVehicleId);
                                    // 剩余线体可继续出库料箱数量
                                    remainVehicleNums--;
                                }
                            } else {
                                if (!skipVehicleIds.contains(maxVehicleId)) {
                                    skipVehicleIds.add(maxVehicleId);
                                }
                            }
                        } else {
                            if (!skipVehicleIds.contains(maxVehicleId)) {
                                skipVehicleIds.add(maxVehicleId);
                            }
                        }
                    }
                    // 最少使用的箱子
                    String minVehicleId = vehicleStandsMap.entrySet().stream()
                            .min(Comparator.comparingInt(Map.Entry::getValue))
                            .map(Map.Entry::getKey)
                            .orElse("");
                    if (!StringUtils.isEmpty(minVehicleId)) {
                        // 找到这个箱子的任务
                        List<Task> outPickTasks = allTasks.stream().filter(task -> task.getVehicleId().equals(minVehicleId) && !pickVehicleIds.contains(task.getVehicleId())
                                && task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())).toList();
                        if (!outPickTasks.isEmpty()) {
                            // 更新每个站台的拣选箱数量
                            List<String> minStandIds = standPickTasks.stream()
                                    .filter(pickTask -> pickTask.getVehicleId().equals(minVehicleId))
                                    .map(PickTask::getStandId)
                                    .distinct()
                                    .toList();
                            // 给当前设备号+1
                            int equipmentId = instantLocationMap.get(outPickTasks.get(0).getOrigin()).getEquipmentId();
                            if (runningTaskNumToEquipmentMap.containsKey(equipmentId)) {
                                boolean flag = false;
                                for (Task task : outPickTasks) {
                                    if (taskGroupIds.contains(task.getTaskGroup())) {
                                        // 该任务组已经下发
                                        continue;
                                    }
                                    if (StringUtils.isNotEmpty(task.getPreTask())) {// 当前任务具有前置任务
                                        // 查询一下前置的任务有没有存在，存在则不下发
                                        if (taskService.exists(new LambdaQueryWrapper<Task>().eq(Task::getTaskId, task.getPreTask()))) {
                                            continue;
                                        }
                                    }
                                    // 创建发送的任务
                                    WcsTaskRequest tempTask = new WcsTaskRequest();
                                    tempTask.setTaskId(task.getTaskGroup());
                                    tempTask.setTaskType(task.getTaskType());
                                    tempTask.setOrigin(task.getOrigin());
                                    tempTask.setDestination(task.getDestination());
                                    tempTask.setVehicleNo(task.getVehicleId());
                                    tempTask.setVehicleSize(task.getVehicleSize());
                                    tempTask.setWeight(task.getWeight());
                                    tempTask.setPriority(task.getTaskPriority());
                                    request.add(tempTask);
                                    // 已经发送过的任务组
                                    taskGroupIds.add(task.getTaskGroup());
                                    flag = true;
                                }
                                if (flag) {
                                    if (!minStandIds.isEmpty()) {
                                        minStandIds.forEach(tempStandId -> {
                                            outPickTaskMap.put(tempStandId, outPickTaskMap.getOrDefault(tempStandId, 0) + 1);
                                            updatedOutPickTaskMap.put(tempStandId, updatedOutPickTaskMap.getOrDefault(tempStandId, 0) + 1);
                                        });
                                    }
                                    runningTaskNumToEquipmentMap.replace(equipmentId, runningTaskNumToEquipmentMap.get(equipmentId) + 1);
                                    // 已经发送过的vehicleId
                                    pickVehicleIds.add(minVehicleId);
                                    // 剩余线体可继续出库料箱数量
                                    remainVehicleNums--;
                                }
                            } else {
                                if (!skipVehicleIds.contains(minVehicleId)) {
                                    skipVehicleIds.add(minVehicleId);
                                }
                            }
                        } else {
                            if (!skipVehicleIds.contains(minVehicleId)) {
                                skipVehicleIds.add(minVehicleId);
                            }
                        }
                    }
                    List<Integer> removeKeys = new ArrayList<>(runningTaskNumToEquipmentMap.keySet().stream().toList());
                    for (int equipmentId : removeKeys) {
                        // 剩余任务有没有这台堆垛机的
                        List<Task> remainTasks = allTasks.stream().filter(task -> !skipVehicleIds.contains(task.getVehicleId()) && !pickVehicleIds.contains(task.getVehicleId())
                                && task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())).toList();
                        if (remainTasks.isEmpty() || runningTaskNumToEquipmentMap.get(equipmentId) >= 3) {
                            runningTaskNumToEquipmentMap.remove(equipmentId);
                        }
                    }
                }

                if (request.size() == 0) {
                    // 没有新任务发送
                    return;
                }
                // 发送任务
                String url = configMap.get(ConfigMapKeyEnum.URL_WCS_TASK.getConfigKey());
                if (url != null) {
                    logger.info("向WCS发送拣选出库任务，地址：{}，请求详情：{}", url, convertJsonString(request));
                    ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(url, convertJsonString(request)), ResponseEntity.class);
                    try {
                        logService.save(new WmsLog(WmsUtils.generateId("LOG_"), "向WCS发送任务", "SetStackerTask", JSON.toJSONString(request), JSON.toJSONString(result), url, LocalDateTime.now(), "WMS"));
                    } catch (Exception e) {
                        logger.error("插入日志错误。");
                    }
                    if (result == null) {
                        logger.error("发送拣选出库任务异常。");
                    } else {
                        if (Objects.equals(ResponseCode.OK.getCode(), result.getCode())) {
                            logger.info("发送WCS拣选出库任务成功。");
                            taskService.update(new LambdaUpdateWrapper<Task>()
                                    .set(Task::getTaskStatus, WmsTaskStatus.WAIT.getCode())
                                    .in(Task::getTaskGroup, taskGroupIds)
                                    .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode()));
                            // 流转载具状态变更
                            if (!pickVehicleIds.isEmpty()) {
                                outsideVehiclesService.update(new LambdaUpdateWrapper<OutsideVehicles>()
                                        .set(OutsideVehicles::getOutStatus, 1)
                                        .in(OutsideVehicles::getVehicleId, pickVehicleIds));
                                // 更新站台拣选箱数
                                for (String tempStandId : updatedOutPickTaskMap.keySet()) {
                                    standService.update(new LambdaUpdateWrapper<Stand>()
                                            .set(Stand::getPickVehicleCount, updatedOutPickTaskMap.get(tempStandId))
                                            .eq(Stand::getStandId, tempStandId));
                                }
                            }
                        } else {
                            // 判断returnData的数据
                            if (result.getReturnData() != null) {
                                List<WcsTaskRequest> errorTasks = JSON.parseArray(result.getReturnData().toString(), WcsTaskRequest.class);
                                if (!errorTasks.isEmpty()) {
                                    List<String> failedTaskIds = errorTasks.stream().map(WcsTaskRequest::getTaskId).distinct().toList();
                                    // 更新任务状态为异常
                                    taskService.update(new LambdaUpdateWrapper<Task>()
                                            .set(Task::getTaskStatus, WmsTaskStatus.EXCEPTION.getCode())
                                            .in(Task::getTaskGroup, failedTaskIds)
                                            .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode()));
                                }
                            }
                            logger.error("发送拣选出库任务错误：{}", convertJsonString(result));
                        }
                    }
                } else {
                    logger.error("WCS发送任务地址为空。");
                }
            }
        } catch (Exception exception) {
            logger.error("向WCS发送拣选出库任务时发生异常：{}", convertJsonString(exception));
            throw new Exception("向WCS发送拣选出库任务时发生异常。");
        }
    }

    /**
     * 发送拣选任务
     */
    @Override
    public void sendPickTasks() throws Exception {
        try {
            // 检索任务表---新建未下发的拣选任务
            LambdaQueryWrapper<PickTask> waitForDistributePickTaskQuery = new LambdaQueryWrapper<PickTask>()
                    .eq(PickTask::getPickStatus, PickTaskStatusEnum.NEW.getCode());
            List<PickTask> allPickTasks = pickTaskService.list(waitForDistributePickTaskQuery);
            if (allPickTasks == null || allPickTasks.isEmpty()) {
                return;
            }
            // 需要发送给wcs的拣选任务列表
            List<WcsStandTaskRequest> request = new ArrayList<>();
            // 载具对应站台列表
            Map<String, List<String>> vehicleAndStansMap = new HashMap<>();
            // 循环生成载具对应站台列表
            for (PickTask pickTask : allPickTasks) {
                // 当前载具已经添加过站台
                if (vehicleAndStansMap.containsKey(pickTask.getVehicleId())) {
                    List<String> oldStandIds = vehicleAndStansMap.get(pickTask.getVehicleId());
                    oldStandIds.add(pickTask.getStandId());
                    vehicleAndStansMap.replace(pickTask.getVehicleId(), oldStandIds);
                } else {// 新载具
                    List<String> newStandIds = new ArrayList<>();
                    newStandIds.add(pickTask.getStandId());
                    vehicleAndStansMap.put(pickTask.getVehicleId(), newStandIds);
                }
            }
            // 循环生成Wcs任务请求
            for (String vehicleId : vehicleAndStansMap.keySet()) {
                WcsStandTaskRequest requestSingle = new WcsStandTaskRequest();
                requestSingle.setTaskGroup(WmsUtils.generateId(vehicleId));
                requestSingle.setTaskType(1);
                requestSingle.setVehicleNo(vehicleId);
                requestSingle.setLocation(vehicleAndStansMap.get(vehicleId));
                requestSingle.setRemark("站台拣选任务");
                request.add(requestSingle);
            }
            if (!request.isEmpty()) {
                // 发送任务
                String url = configMap.get(ConfigMapKeyEnum.URL_WCS_PICK_TASK.getConfigKey());
                if (url != null) {
                    logger.info("向WCS发送拣选任务，地址：{}，请求详情：{}", url, convertJsonString(request));
                    ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(url, convertJsonString(request)), ResponseEntity.class);
                    try {
                        logService.save(new WmsLog(WmsUtils.generateId("LOG_"), "向WCS发送拣选任务", "setConveyTask", convertJsonString(request), convertJsonString(result), url, LocalDateTime.now(), "WMS"));
                    } catch (Exception e) {
                        logger.error("插入日志错误。");
                    }
                    if (result != null && Objects.equals(ResponseCode.OK.getCode(), result.getCode())) {
                        logger.info("发送拣选任务成功。");
                        pickTaskService.update(new LambdaUpdateWrapper<PickTask>()
                                .set(PickTask::getPickStatus, PickTaskStatusEnum.SEND.getCode())
                                .in(PickTask::getVehicleId, vehicleAndStansMap.keySet())
                                .eq(PickTask::getPickStatus, PickTaskStatusEnum.NEW.getCode()));
                    } else {
                        logger.error("发送拣选任务错误：{}", convertJsonString(result));
                    }
                } else {
                    logger.error("WCS发送拣选任务地址为空。");
                }
            }
        } catch (Exception exception) {
            logger.error("向WCS发送拣选任务时发生异常：{}", convertJsonString(exception));
            throw new Exception("向WCS发送拣选任务时发生异常。");
        }
    }

    /**
     * 处理重复入库的任务
     */
    @Override
    public void solveDuplicateTask() throws Exception {
        try {
            // 检索任务表---重复入库的任务
            LambdaQueryWrapper<Task> duplicateTaskQueryWrapper = new LambdaQueryWrapper<Task>()
                    .eq(Task::getTaskType, TaskType.IN.getCode())
                    .eq(Task::getTaskStatus, WmsTaskStatus.DUPLICATE.getCode());
            List<Task> duplicateTasks = taskService.list(duplicateTaskQueryWrapper);
            // 需要发送给wcs的任务列表
            List<WcsTaskRequest> request = new ArrayList<>();
            // 已经下发的任务组列表
            List<String> taskGroupIds = new ArrayList<>();
            if (!duplicateTasks.isEmpty()) {
                for (Task task : duplicateTasks) {
                    if (StringUtils.isNotEmpty(task.getPreTask())) {// 当前任务具有前置任务
                        // 查询一下前置的任务有没有存在，存在则不下发
                        if (taskService.exists(new LambdaQueryWrapper<Task>().eq(Task::getTaskId, task.getPreTask()))) {
                            continue;
                        }
                    }
                    if (taskGroupIds.contains(task.getTaskGroup())) {
                        // 已经发送过的任务组，跳过
                        continue;
                    }
                    // 创建发送的任务
                    WcsTaskRequest tempTask = new WcsTaskRequest();
                    tempTask.setTaskId(task.getTaskGroup());
                    tempTask.setDestination(task.getDestination());
                    tempTask.setVehicleNo(task.getVehicleId());
                    request.add(tempTask);
                    // 已经发送过的任务组
                    taskGroupIds.add(task.getTaskGroup());
                }
                if (request.isEmpty()) {
                    return;
                }
                // 发送任务
                String url = configMap.get(ConfigMapKeyEnum.URL_NEW_DESTINATION.getConfigKey());
                if (url != null) {
                    logger.info("向WCS发送新目的地，地址：{}，请求详情：{}", url, convertJsonString(request));
                    request.forEach(wcsTaskRequest -> {
                        ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(url, convertJsonString(wcsTaskRequest)), ResponseEntity.class);
                        try {
                            logService.save(new WmsLog(WmsUtils.generateId("LOG_"), "向WCS发送新目的地", "setStackerTaskNewDestination", convertJsonString(wcsTaskRequest), convertJsonString(result), url, LocalDateTime.now(), "WMS"));
                        } catch (Exception e) {
                            logger.error("插入日志错误");
                        }
                        if (result != null && Objects.equals(ResponseCode.OK.getCode(), result.getCode())) {
                            taskService.update(new LambdaUpdateWrapper<Task>()
                                    .set(Task::getTaskStatus, WmsTaskStatus.WAIT.getCode())
                                    .in(Task::getTaskGroup, taskGroupIds)
                                    .eq(Task::getTaskStatus, WmsTaskStatus.DUPLICATE.getCode()));
                        } else {
                            logger.error("发送新目的地错误：{}", convertJsonString(result));
                        }
                    });
                } else {
                    logger.error("向WCS发送新目的地的地址为空");
                }
            }
        } catch (Exception exception) {
            logger.error("向WCS发送新目的地时发生异常：{}", convertJsonString(exception));
            throw new Exception("向WCS发送新目的地时发生异常");
        }
    }

    /**
     * 定期清除日志
     */
    @Override
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    public void deleteLogsRegularly() {
        try {
            int interval = 30;
            try {
                interval = Integer.parseInt(configMap.get(ConfigMapKeyEnum.LOG_DELETE_INTERVAL.getConfigKey()));
            } catch (Exception e) {
                logger.error("获取日志清理天数错误，使用默认值30天");
            }
            LambdaQueryWrapper<WmsLog> lambdaQueryWrapper = new LambdaQueryWrapper<WmsLog>()
                    .apply("log_time <= date_add(curdate(),INTERVAL -{0} DAY)", interval);
            logService.remove(lambdaQueryWrapper);
        } catch (Exception exception) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 定期清除记录
     */
    @Override
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    public void deleteRecordsRegularly() {
        try {
            int interval = 180;// 普通接口记录默认保留180天
            int importantInterval = 365;// 重要接口记录默认保留一年
            try {
                interval = Integer.parseInt(configMap.get(ConfigMapKeyEnum.LOG_DELETE_INTERVAL.getConfigKey()));
            } catch (Exception e) {
                logger.error("获取普通记录清理天数错误，使用默认值180天");
            }
            try {
                importantInterval = Integer.parseInt(configMap.get(ConfigMapKeyEnum.LOG_DELETE_INTERVAL.getConfigKey()));
            } catch (Exception e) {
                logger.error("获取重要记录清理天数错误，使用默认值365天");
            }
            // 普通记录---入出库记录、拣选任务记录
            // 重要记录---盘点记录、工作总结、库存更新记录、非计划领料记录、上传文件记录
        } catch (Exception exception) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }
}
