package com.wms_main.service.quartz_job.job_executor;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wms_main.constant.enums.wcs.WcsStackerTaskStatusEnums;
import com.wms_main.constant.enums.wcs.WcsStackerTaskTypeEnums;
import com.wms_main.constant.enums.wms.WmsStackerTaskStatusEnums;
import com.wms_main.constant.enums.wms.WmsTaskTypeEnums;
import com.wms_main.dao.ITAppTaskService;
import com.wms_main.dao.ITAppWcsTaskService;
import com.wms_main.model.po.TAppTask;
import com.wms_main.model.po.TAppWcsTask;
import com.wms_main.repository.utils.ConvertUtils;
import com.wms_main.repository.utils.StringUtils;
import com.wms_main.repository.utils.UUIDUtils;
import com.wms_main.service.business.IStackerTaskService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;

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

/**
 * 定时任务定义类---堆垛机任务解析类
 */
@Slf4j
@PersistJobDataAfterExecution
// 以下注解用于实现fixed_delay
@DisallowConcurrentExecution
@RequiredArgsConstructor
public class WmsTaskExecutor {
    /**
     * Wms任务服务
     */
    private final ITAppTaskService appTaskService;
    /**
     * Wcs任务服务
     */
    private final ITAppWcsTaskService appWcsTaskService;
    /**
     * 堆垛机任务服务
     */
    private final IStackerTaskService stackerTaskService;
    /**
     * 运行定时任务
     * 向Wcs发送堆垛机任务
     *
     * @param jobExecutionContext 定时任务执行的环境（上下文）
     */
    public void execute(JobExecutionContext jobExecutionContext) {
        // 获取到所有待下发的任务
        List<TAppTask> waitSendWmsTaskList = appTaskService.list(
                new LambdaQueryWrapper<TAppTask>()
                        .eq(TAppTask::getTaskStatus, WmsStackerTaskStatusEnums.WAIT.getCode())
        );
        // 筛选入库任务
        List<TAppTask> stackerInTasks = waitSendWmsTaskList.stream()
                .filter(task -> Objects.equals(WmsTaskTypeEnums.IN.getCode(), task.getTaskType()))
                .toList();
        if (!stackerInTasks.isEmpty()) {
            executeStackerInTask(stackerInTasks);// 解析入库任务
        }
        // 筛选出库任务
        List<TAppTask> stackerOutTasks = waitSendWmsTaskList.stream()
                .filter(task -> Objects.equals(WmsTaskTypeEnums.OUT.getCode(), task.getTaskType()))
                .toList();
        if (!stackerOutTasks.isEmpty()) {
            executeStackerOutTask(stackerOutTasks);// 解析出库任务
        }
    }

    /**
     * 解析入库任务 实现
     * @param stackerInTasks 入库任务
     */
    public void executeStackerInTask(List<TAppTask> stackerInTasks) {
        // 查找到wcsTask表中所有的入库任务
        List<TAppWcsTask> wcsInTaskList = appWcsTaskService.list(
                new LambdaQueryWrapper<TAppWcsTask>()
                        .eq(TAppWcsTask::getWcsTaskType, WcsStackerTaskTypeEnums.IN.getCode())
        );
        // 将上述入库任务列表转成map，键为载具号，值为请求
        Map<String, TAppWcsTask> wcsInTaskMap = wcsInTaskList.stream().collect(Collectors.toMap(TAppWcsTask::getVehicleId, appWcsTask -> appWcsTask));
        Map<String, TAppWcsTask> wcsInTaskMapThisTime = new HashMap<>();
        // 之前解析过的任务
        List<TAppTask> executedBeforeTaskList = new ArrayList<>();
        for (TAppTask wmsTask : stackerInTasks) {
            // 判断当前箱子是否已经解析成WCS任务并且已经存表
            if (wcsInTaskMap.containsKey(wmsTask.getVehicleId())) {
                // 设置状态与wcsTaskId
                wmsTask.setWcsTaskId(wcsInTaskMap.get(wmsTask.getVehicleId()).getWcsTaskId());
                wmsTask.setTaskStatus(ConvertUtils.convertWcsStackerTaskStatusToWmsTaskStatus(wcsInTaskMap.get(wmsTask.getVehicleId()).getWcsTaskStatus()));
                executedBeforeTaskList.add(wmsTask);
                continue;
            }
            // 判断当前箱子是不是已经在本次解析中已经解析完
            if (wcsInTaskMapThisTime.containsKey(wmsTask.getVehicleId())) {
                continue;
            }
            if (StringUtils.isEmpty(wmsTask.getDestination())) {
                continue;
            }
            // 生成新的wcs任务
            TAppWcsTask wcsInTask = new TAppWcsTask();
            wcsInTask.setWcsTaskId(UUIDUtils.getNewUUID());
            wcsInTask.setWcsTaskType(WcsStackerTaskTypeEnums.IN.getCode());
            wcsInTask.setWcsTaskStatus(WcsStackerTaskStatusEnums.INIT.getCode());
            wcsInTask.setTaskPriority(wmsTask.getTaskPriority());
            wcsInTask.setOrigin(wmsTask.getOrigin() != null ? wmsTask.getOrigin() : "");
            wcsInTask.setDestination(wmsTask.getDestination());
            wcsInTask.setVehicleId(wmsTask.getVehicleId());
            wcsInTask.setCreateTime(LocalDateTime.now());
            wcsInTaskMapThisTime.put(wmsTask.getVehicleId(), wcsInTask);
        }
        try {
            // 更新已解析的入库任务列表
            appTaskService.updateBatchById(executedBeforeTaskList);
        } catch (Exception e) {
            log.error("更新已解析入库任务状态失败，任务列表：{}", executedBeforeTaskList.stream().map(TAppTask::getTaskId).toList());
        }
        if (!wcsInTaskMapThisTime.isEmpty()) {
            for (TAppWcsTask wcsInTask : wcsInTaskMapThisTime.values()) {
                stackerTaskService.saveWcsTaskAndUpdateWmsTask(wcsInTask);
            }
        }
    }

    /**
     * 解析出库任务 实现
     * @param stackerOutTasks 出库任务
     */
    public void executeStackerOutTask(List<TAppTask> stackerOutTasks) {
        // 查找到wcsTask表中所有的出库任务
        List<TAppWcsTask> wcsOutTaskList = appWcsTaskService.list(
                new LambdaQueryWrapper<TAppWcsTask>()
                        .eq(TAppWcsTask::getWcsTaskType, WcsStackerTaskTypeEnums.OUT.getCode())
        );
        // 将上述入库任务列表转成map，键为载具号，值为请求
        Map<String, TAppWcsTask> wcsOutTaskMap = wcsOutTaskList.stream().collect(Collectors.toMap(TAppWcsTask::getVehicleId, appWcsTask -> appWcsTask));
        Map<String, TAppWcsTask> wcsOutTaskMapThisTime = new HashMap<>();
        // 之前解析过的任务
        List<TAppTask> executedBeforeTaskList = new ArrayList<>();
        for (TAppTask wmsTask : stackerOutTasks) {
            // 判断当前箱子是否已经解析成WCS任务并且已经存表
            if (wcsOutTaskMap.containsKey(wmsTask.getVehicleId())) {
                // 设置状态与wcsTaskId
                wmsTask.setWcsTaskId(wcsOutTaskMap.get(wmsTask.getVehicleId()).getWcsTaskId());
                wmsTask.setTaskStatus(ConvertUtils.convertWcsStackerTaskStatusToWmsTaskStatus(wcsOutTaskMap.get(wmsTask.getVehicleId()).getWcsTaskStatus()));
                executedBeforeTaskList.add(wmsTask);
                continue;
            }
            // 判断当前箱子是不是已经在本次解析中已经解析完
            if (wcsOutTaskMapThisTime.containsKey(wmsTask.getVehicleId())) {
                continue;
            }
            if (StringUtils.isEmpty(wmsTask.getOrigin())) {
                continue;
            }
            // 生成新的wcs任务
            TAppWcsTask wcsOutTask = new TAppWcsTask();
            wcsOutTask.setWcsTaskId(UUIDUtils.getNewUUID());
            wcsOutTask.setWcsTaskType(WcsStackerTaskTypeEnums.OUT.getCode());
            wcsOutTask.setWcsTaskStatus(WcsStackerTaskStatusEnums.INIT.getCode());
            wcsOutTask.setTaskPriority(wmsTask.getTaskPriority());
            wcsOutTask.setOrigin(wmsTask.getOrigin());
            wcsOutTask.setDestination(wmsTask.getDestination() != null ? wmsTask.getDestination() : "");
            wcsOutTask.setVehicleId(wmsTask.getVehicleId());
            wcsOutTask.setCreateTime(LocalDateTime.now());
            wcsOutTaskMapThisTime.put(wmsTask.getVehicleId(), wcsOutTask);
        }
        try {
            // 更新已解析的入库任务列表
            appTaskService.updateBatchById(executedBeforeTaskList);
        } catch (Exception e) {
            log.error("更新已解析出库任务状态失败，任务列表：{}", executedBeforeTaskList.stream().map(TAppTask::getTaskId).toList());
        }
        if (!wcsOutTaskMapThisTime.isEmpty()) {
            for (TAppWcsTask wcsOutTask : wcsOutTaskMapThisTime.values()) {
                stackerTaskService.saveWcsTaskAndUpdateWmsTask(wcsOutTask);
            }
        }
    }
}
