package org.wcs.business.stock.impl;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.wcs.business.pub.ReportStandard;
import org.wcs.business.stock.intf.IStockSingleTaskExecuteEvent;
import org.wcs.constant.enums.common.TrueOrFalseEnum;
import org.wcs.constant.enums.database.*;
import org.wcs.constant.enums.http.StockCallBackStatusEnum;
import org.wcs.mapper.intf.AppStackerLocationService;
import org.wcs.mapper.intf.AppStockComposeTaskService;
import org.wcs.mapper.intf.AppStockSingleTaskService;
import org.wcs.mapper.intf.AppTrayConveyLocationService;
import org.wcs.model.po.app.AppStockComposeTask;
import org.wcs.model.po.app.AppStockSingleTask;
import org.wcs.model.po.app.AppTrayConveyLocation;
import org.wcs.plugin.plc.PlcCommunicationFactory;
import org.wcs.plugin.plc.model.TaskConveyTask;
import org.wcs.utils.AppStringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * 独立任务执行事件
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StockSingleTaskExecuteEvent implements IStockSingleTaskExecuteEvent {

    private final AppStockSingleTaskService stockSingleTaskService;
    private final AppStockComposeTaskService stockComposeTaskService;
    private final AppStackerLocationService stackerLocationService;
    private final AppTrayConveyLocationService trayConveyLocationService;


    /**
     * 任务开始
     * @param appStockSingleTask 开始的任务
     * @param message 信息
     * @return 执行结果
     */
    @Override
    public String taskStart(AppStockSingleTask appStockSingleTask, String message) {
        // 更新任务为执行中
        AppStockSingleTask stockSingleTaskUpdate = new AppStockSingleTask();
        stockSingleTaskUpdate.setTaskId(appStockSingleTask.getTaskId());
        stockSingleTaskUpdate.setTaskStatus(StockSingleTaskStatusEnum.EXECUTING.getCode());
        stockSingleTaskUpdate.setStartTime(LocalDateTime.now());
        stockSingleTaskUpdate.setTaskMsg(message);
        boolean singleTaskUpdated = stockSingleTaskService.update(stockSingleTaskUpdate);
        log.info("独立任务开始执行更新独立任务数据库行：{} 更新结果：{}", AppStringUtils.objectToString(appStockSingleTask), singleTaskUpdated);
        // 更新库位状态
        if(appStockSingleTask.getTaskType().equals(StockSingleTaskTypeEnum.STACKER_IN.getCode())) {
            // 入库更新库位状态
            stackerLocationService.updateStatusAndVehicleNoById(appStockSingleTask.getDestination(), StackerLocationStatusEnum.IN_ING.getCode(), appStockSingleTask.getVehicleNo());
        }
        if(appStockSingleTask.getTaskType().equals(StockSingleTaskTypeEnum.STACKER_OUT.getCode())) {
            // 出库更新库位状态
            stackerLocationService.updateStatusAndVehicleNoById(appStockSingleTask.getOrigin(), StackerLocationStatusEnum.OUT_ING.getCode(), appStockSingleTask.getVehicleNo());
        }
        if(appStockSingleTask.getTaskType().equals(StockSingleTaskTypeEnum.STACKER_MOVE.getCode())) {
            // 移库更新库位状态
            stackerLocationService.updateStatusAndVehicleNoById(appStockSingleTask.getOrigin(), StackerLocationStatusEnum.OUT_ING.getCode(), appStockSingleTask.getVehicleNo());
            stackerLocationService.updateStatusAndVehicleNoById(appStockSingleTask.getDestination(), StackerLocationStatusEnum.IN_ING.getCode(), appStockSingleTask.getVehicleNo());
        }
        if(AppStringUtils.isEmpty(appStockSingleTask.getUpperTaskId())) {
            return null;
        }
        // 查看主任务状态
        AppStockComposeTask stockComposeTask = stockComposeTaskService.queryByTaskId(appStockSingleTask.getUpperTaskId());
        if(stockComposeTask ==  null) {
            log.info("独立任务开始执行检索组合任务数据服务异常，上位任务号：{}", appStockSingleTask.getUpperTaskId());
            return null;
        }
        if(!Objects.equals(stockComposeTask.getTaskStatus(), StockComposeTaskStatusEnum.EXECUTING.getCode())) {
            AppStockComposeTask stockComposeTaskUpdate = new AppStockComposeTask();
            stockComposeTaskUpdate.setTaskId(stockComposeTask.getTaskId());
            stockComposeTaskUpdate.setTaskStatus(StockComposeTaskStatusEnum.EXECUTING.getCode());
            stockComposeTaskUpdate.setStepStatus(StockComposeTaskStepStatusEnum.RUNNING.getCode());
            stockComposeTaskUpdate.setCanCancel(TrueOrFalseEnum.FALSE.getCode());
            stockComposeTaskUpdate.setStartTime(LocalDateTime.now());
            stockComposeTaskUpdate.setTaskMsg(message);
            boolean composeTaskUpdated = stockComposeTaskService.update(stockComposeTaskUpdate);
            log.info("独立任务开始执行更新组合任务数据库行：{} 状态：{} 更新结果：{}", AppStringUtils.objectToString(stockComposeTask), StockComposeTaskStatusEnum.EXECUTING.getCode(), composeTaskUpdated);
            ReportStandard.stockTaskReport(StockCallBackStatusEnum.START, stockComposeTask, message);
        }
        return null;
    }

    /**
     * 任务完成
     * @param appStockSingleTask 开始的任务
     * @param message 信息
     * @return 执行结果
     */
    @Override
    public String taskFinish(AppStockSingleTask appStockSingleTask, String message) {
        // 更新任务为完成
        AppStockSingleTask stockSingleTaskUpdate = new AppStockSingleTask();
        stockSingleTaskUpdate.setTaskId(appStockSingleTask.getTaskId());
        stockSingleTaskUpdate.setTaskStatus(StockSingleTaskStatusEnum.COMPLETE.getCode());
        stockSingleTaskUpdate.setStartTime(LocalDateTime.now());
        stockSingleTaskUpdate.setTaskMsg(message);
        boolean singleTaskUpdated = stockSingleTaskService.update(stockSingleTaskUpdate);
        log.info("独立任务完成更新独立任务数据库行：{} 更新结果：{}", AppStringUtils.objectToString(appStockSingleTask), singleTaskUpdated);
        // 更新库位状态
        if(appStockSingleTask.getTaskType().equals(StockSingleTaskTypeEnum.STACKER_IN.getCode())) { // 堆垛机入库
            // 入库更新库位状态
            stackerLocationService.updateStatusAndVehicleNoById(appStockSingleTask.getDestination(), StackerLocationStatusEnum.OCCUPY.getCode(), appStockSingleTask.getVehicleNo());
        }
        if(appStockSingleTask.getTaskType().equals(StockSingleTaskTypeEnum.STACKER_OUT.getCode())) { // 堆垛机出库
            // 出库更新库位状态
            stackerLocationService.updateStatusAndVehicleNoById(appStockSingleTask.getOrigin(), StackerLocationStatusEnum.EMPTY.getCode(), "");
            // 出库完成后绑定载具号到输送机
            List<AppTrayConveyLocation> destinationInfoList = trayConveyLocationService.getDataByLocationId(appStockSingleTask.getDestination());
            if(destinationInfoList != null && !destinationInfoList.isEmpty()) {
                AppTrayConveyLocation destinationInfo = destinationInfoList.getFirst();
                TaskConveyTask taskConveyTask = new TaskConveyTask();
                taskConveyTask.setPlcTaskId(appStockSingleTask.getPlcTaskId());
                taskConveyTask.setTaskType(StockSingleTaskTypeEnum.BINDING_VEHICLE_NO.getCode().shortValue());
                taskConveyTask.setOrigin((short)0);
                taskConveyTask.setDestination((short)0);
                taskConveyTask.setVehicleSize(appStockSingleTask.getVehicleSize().shortValue());
                taskConveyTask.setWeight(appStockSingleTask.getWeight().intValue());
                taskConveyTask.setVehicleNo(appStockSingleTask.getVehicleNo());
                String writeTaskResult = PlcCommunicationFactory.getPlcCommunicationByPlcId(destinationInfo.getPlcId()).writeTaskConveyTask(appStockSingleTask.getDestination(), taskConveyTask);
                if(AppStringUtils.isNotEmpty(writeTaskResult)) {
                    log.warn("托盘线：{} 写入绑定载具号任务失败，站台：{}，载具号：{}。原因：{}", appStockSingleTask.getTaskId(), appStockSingleTask.getDestination(),appStockSingleTask.getVehicleNo(), writeTaskResult);
                } else {
                    log.info("托盘线：{} 写入绑定载具号任务成功，站台：{}，载具号：{}", appStockSingleTask.getTaskId(), appStockSingleTask.getDestination(),appStockSingleTask.getVehicleNo());
                }
            }
        }
        if(appStockSingleTask.getTaskType().equals(StockSingleTaskTypeEnum.STACKER_MOVE.getCode())) { // 堆垛机移库
            // 移库更新库位状态
            stackerLocationService.updateStatusAndVehicleNoById(appStockSingleTask.getOrigin(), StackerLocationStatusEnum.EMPTY.getCode(), "");
            stackerLocationService.updateStatusAndVehicleNoById(appStockSingleTask.getDestination(), StackerLocationStatusEnum.OCCUPY.getCode(), appStockSingleTask.getVehicleNo());
        }
        return null;
    }

    /**
     * 任务异常
     * @param appStockSingleTask 开始的任务
     * @param message 信息
     * @return 执行结果
     */
    @Override
    public String taskError(AppStockSingleTask appStockSingleTask, String message) {
        // 更新任务为异常
        AppStockSingleTask stockSingleTaskUpdate = new AppStockSingleTask();
        stockSingleTaskUpdate.setTaskId(appStockSingleTask.getTaskId());
        stockSingleTaskUpdate.setTaskStatus(StockSingleTaskStatusEnum.ERROR.getCode());
        stockSingleTaskUpdate.setStartTime(LocalDateTime.now());
        stockSingleTaskUpdate.setTaskMsg(message);
        boolean singleTaskUpdated = stockSingleTaskService.update(stockSingleTaskUpdate);
        log.info("独立任务异常更新独立任务数据库行：{} 更新结果：{}", AppStringUtils.objectToString(appStockSingleTask), singleTaskUpdated);
        return null;
    }

    /**
     * 任务取消
     * @param appStockSingleTask 开始的任务
     * @param message 信息
     * @return 执行结果
     */
    @Override
    public String taskCancel(AppStockSingleTask appStockSingleTask, String message) {
        // 更新任务为取消
        AppStockSingleTask stockSingleTaskUpdate = new AppStockSingleTask();
        stockSingleTaskUpdate.setTaskId(appStockSingleTask.getTaskId());
        stockSingleTaskUpdate.setTaskStatus(StockSingleTaskStatusEnum.CANCEL.getCode());
        stockSingleTaskUpdate.setStartTime(LocalDateTime.now());
        stockSingleTaskUpdate.setTaskMsg(message);
        boolean singleTaskUpdated = stockSingleTaskService.update(stockSingleTaskUpdate);
        log.info("独立任务取消更新独立任务数据库行：{} 更新结果：{}", AppStringUtils.objectToString(appStockSingleTask), singleTaskUpdated);
        // 更新库位状态
        if(appStockSingleTask.getTaskType().equals(StockSingleTaskTypeEnum.STACKER_IN.getCode())) {
            // 入库更新库位状态
            stackerLocationService.updateStatusAndVehicleNoById(appStockSingleTask.getDestination(), StackerLocationStatusEnum.EMPTY.getCode(), "");
        }
        if(appStockSingleTask.getTaskType().equals(StockSingleTaskTypeEnum.STACKER_OUT.getCode())) {
            // 出库更新库位状态
            stackerLocationService.updateStatusAndVehicleNoById(appStockSingleTask.getOrigin(), StackerLocationStatusEnum.OCCUPY.getCode(), appStockSingleTask.getVehicleNo());
        }
        if(appStockSingleTask.getTaskType().equals(StockSingleTaskTypeEnum.STACKER_MOVE.getCode())) {
            // 移库更新库位状态
            stackerLocationService.updateStatusAndVehicleNoById(appStockSingleTask.getOrigin(), StackerLocationStatusEnum.OCCUPY.getCode(), appStockSingleTask.getVehicleNo());
            stackerLocationService.updateStatusAndVehicleNoById(appStockSingleTask.getDestination(), StackerLocationStatusEnum.EMPTY.getCode(), "");
        }
        return null;
    }

    /**
     * 任务重复入库
     * @param appStockSingleTask 开始的任务
     * @param message 信息
     * @return 执行结果
     */
    @Override
    public String taskDoubleIn(AppStockSingleTask appStockSingleTask, String message) {
        // 更新任务为重复入库
        AppStockSingleTask stockSingleTaskUpdate = new AppStockSingleTask();
        stockSingleTaskUpdate.setTaskId(appStockSingleTask.getTaskId());
        stockSingleTaskUpdate.setTaskStatus(StockSingleTaskStatusEnum.ERROR.getCode());
        stockSingleTaskUpdate.setStartTime(LocalDateTime.now());
        stockSingleTaskUpdate.setTaskMsg("[重复入库]" + message);
        boolean singleTaskUpdated = stockSingleTaskService.update(stockSingleTaskUpdate);
        log.info("独立任务重复入库更新独立任务数据库行：{} 更新结果：{}", AppStringUtils.objectToString(appStockSingleTask), singleTaskUpdated);
        if(AppStringUtils.isEmpty(appStockSingleTask.getUpperTaskId())) {
            return null;
        }
        // 查看主任务状态
        AppStockComposeTask stockComposeTask = stockComposeTaskService.queryByTaskId(appStockSingleTask.getUpperTaskId());
        if(stockComposeTask ==  null) {
            log.info("独立任务重复入库检索组合任务数据服务异常，上位任务号：{}", appStockSingleTask.getUpperTaskId());
            return null;
        }
        if(!Objects.equals(stockComposeTask.getTaskStatus(), StockComposeTaskStatusEnum.ERROR.getCode())) {
            AppStockComposeTask stockComposeTaskUpdate = new AppStockComposeTask();
            stockComposeTaskUpdate.setTaskId(stockComposeTask.getTaskId());
            stockComposeTaskUpdate.setTaskStatus(StockComposeTaskStatusEnum.ERROR.getCode());
            stockComposeTaskUpdate.setStepStatus(StockComposeTaskStepStatusEnum.ERROR.getCode());
            stockComposeTaskUpdate.setStartTime(LocalDateTime.now());
            stockComposeTaskUpdate.setTaskMsg("[重复入库]" + message);
            boolean composeTaskUpdated = stockComposeTaskService.update(stockComposeTaskUpdate);
            log.info("独立任务重复入库更新组合任务数据库行：{} 状态：{} 更新结果：{}", AppStringUtils.objectToString(stockComposeTask), StockComposeTaskStatusEnum.EXECUTING.getCode(), composeTaskUpdated);
            ReportStandard.stockTaskReport(StockCallBackStatusEnum.DOUBLE_IN,stockComposeTask,  message);
        }
        return null;
    }

    /**
     * 任务空出库
     * @param appStockSingleTask 开始的任务
     * @param message 信息
     * @return 执行结果
     */
    @Override
    public String taskEmptyOut(AppStockSingleTask appStockSingleTask, String message) {
        // 更新任务为空出库
        AppStockSingleTask stockSingleTaskUpdate = new AppStockSingleTask();
        stockSingleTaskUpdate.setTaskId(appStockSingleTask.getTaskId());
        stockSingleTaskUpdate.setTaskStatus(StockSingleTaskStatusEnum.CANCEL.getCode());
        stockSingleTaskUpdate.setStartTime(LocalDateTime.now());
        stockSingleTaskUpdate.setTaskMsg("[空出库]" + message);
        boolean singleTaskUpdated = stockSingleTaskService.update(stockSingleTaskUpdate);
        log.info("独立任务空出库更新独立任务数据库行：{} 更新结果：{}", AppStringUtils.objectToString(appStockSingleTask), singleTaskUpdated);
        if(AppStringUtils.isEmpty(appStockSingleTask.getUpperTaskId())) {
            return null;
        }
        // 查看主任务状态
        AppStockComposeTask stockComposeTask = stockComposeTaskService.queryByTaskId(appStockSingleTask.getUpperTaskId());
        if(stockComposeTask ==  null) {
            log.info("独立任务空出库检索组合任务数据服务异常，上位任务号：{}", appStockSingleTask.getUpperTaskId());
            return null;
        }
        if(!Objects.equals(stockComposeTask.getTaskStatus(), StockComposeTaskStatusEnum.CANCEL.getCode())) {
            AppStockComposeTask stockComposeTaskUpdate = new AppStockComposeTask();
            stockComposeTaskUpdate.setTaskId(stockComposeTask.getTaskId());
            stockComposeTaskUpdate.setTaskStatus(StockComposeTaskStatusEnum.CANCEL.getCode());
            stockComposeTaskUpdate.setStepStatus(StockComposeTaskStepStatusEnum.ERROR.getCode());
            stockComposeTaskUpdate.setStartTime(LocalDateTime.now());
            stockComposeTaskUpdate.setTaskMsg("[空出库]" + message);
            boolean composeTaskUpdated = stockComposeTaskService.update(stockComposeTaskUpdate);
            log.info("独立任务空出库更新组合任务数据库行：{} 状态：{} 更新结果：{}", AppStringUtils.objectToString(stockComposeTask), StockComposeTaskStatusEnum.EXECUTING.getCode(), composeTaskUpdated);
            ReportStandard.stockTaskReport(StockCallBackStatusEnum.EMPTY_OUT,stockComposeTask,  message);
        }
        return null;
    }

    /**
     * 任务超时
     * @param appStockSingleTask 开始的任务
     * @param message 信息
     * @return 执行结果
     */
    @Override
    public String taskTimeOut(AppStockSingleTask appStockSingleTask, String message) {
        // 更新任务为任务超时
        AppStockSingleTask stockSingleTaskUpdate = new AppStockSingleTask();
        stockSingleTaskUpdate.setTaskId(appStockSingleTask.getTaskId());
        stockSingleTaskUpdate.setTaskStatus(StockSingleTaskStatusEnum.TIMEOUT.getCode());
        stockSingleTaskUpdate.setStartTime(LocalDateTime.now());
        stockSingleTaskUpdate.setTaskMsg(message);
        boolean singleTaskUpdated = stockSingleTaskService.update(stockSingleTaskUpdate);
        log.info("独立任务超时更新独立任务数据库行：{} 更新结果：{}", AppStringUtils.objectToString(appStockSingleTask), singleTaskUpdated);
        return null;
    }
}
