package com.wms_main.service.quartz_job.job_executor;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.wms_main.constant.enums.wcs.WcsApiResponseCodeEnums;
import com.wms_main.constant.enums.wcs.WcsStackerTaskStatusEnums;
import com.wms_main.constant.enums.wcs.WcsStackerTaskTypeEnums;
import com.wms_main.constant.enums.wms.*;
import com.wms_main.dao.*;
import com.wms_main.model.bo.wcs.WcsStackerTask;
import com.wms_main.model.dto.request.wcs.WcsStackerTaskRequest;
import com.wms_main.model.dto.response.wcs.WcsApiResponse;
import com.wms_main.model.po.*;
import com.wms_main.repository.utils.StringUtils;
import com.wms_main.repository.utils.UUIDUtils;
import com.wms_main.service.api.IWcsApiService;
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.ArrayList;
import java.util.List;

/**
 * 定时任务定义类---发送堆垛机任务
 */
@Slf4j
@PersistJobDataAfterExecution
// 以下注解用于实现fixed_delay
@DisallowConcurrentExecution
@RequiredArgsConstructor
public class WcsStackerTaskSender implements Job {
    /**
     * Wcs任务服务
     */
    private final ITAppWcsTaskService appWcsTaskService;
    /**
     * Wcs接口服务
     */
    private final IWcsApiService wcsApiService;
    /**
     * 库存服务
     */
    private final ITAppStockService stockService;
    /**
     * 堆垛机服务
     */
    private final IStackerTaskService stackerTaskService;

    private final ITAppVehicleService appVehicleService;

    private final ITAppLocationService appLocationService;

    /**
     * 运行定时任务
     * 向Wcs发送堆垛机任务
     *
     * @param jobExecutionContext 定时任务执行的环境（上下文）
     */
    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        List<TAppWcsTask> appWcsTasks = appWcsTaskService.list(
                new LambdaQueryWrapper<TAppWcsTask>()
                        .eq(TAppWcsTask::getWcsTaskStatus, WcsStackerTaskStatusEnums.INIT.getCode())
                        .eq(TAppWcsTask::getWcsTaskType, WcsStackerTaskTypeEnums.OUT.getCode()));
        for (TAppWcsTask wcsTask : appWcsTasks) {
            String locationId = wcsTask.getOrigin();
            TAppLocation loc = appLocationService.list(
                    new LambdaQueryWrapper<TAppLocation>()
                            .eq(TAppLocation::getLocationId, locationId)
            ).getFirst();
            Integer locType = loc.getLocationType();
            WmsLocationTypeEnums locEnum = WmsLocationTypeEnums.getEnum(locType);
            String[] str_lst = locationId.split("-");
            Integer equipmentId = appWcsTaskService.getEquipmentByLocation(locationId);
            Integer depth = appWcsTaskService.getDepthByLocation(locationId);
            // 深度1, 直接出库
            if (depth == 1) {
                WcsStackerTaskRequest request = new WcsStackerTaskRequest();
                request.setTaskId(wcsTask.getWcsTaskId());
                request.setTaskType(WcsStackerTaskTypeEnums.OUT.getCode());
                request.setPriority(1);
                request.setOrigin(wcsTask.getOrigin());
                request.setDestination(wcsTask.getDestination());
                request.setVehicleNo(wcsTask.getVehicleId());
                try {
                    WcsApiResponse<WcsStackerTask> wcsResponse = wcsApiService.sendWcsStackerTask(request);
                    if (wcsResponse != null && WcsApiResponseCodeEnums.SUCCESS.getCode() == wcsResponse.getCode()) {
                        appWcsTaskService.update(
                                new LambdaUpdateWrapper<TAppWcsTask>()
                                        .eq(TAppWcsTask::getWcsTaskId, wcsTask.getWcsTaskId())
                                        .set(TAppWcsTask::getWcsTaskStatus, WcsStackerTaskStatusEnums.WAIT.getCode()));
                        // TODO appOrderOutService?
                    }
                } catch (Exception e) {
                    log.error("堆垛机任务发送失败，任务号：{}，载具号：{}，起点：{}，终点：{}。", request.getTaskId(), request.getVehicleNo(), request.getOrigin(), request.getDestination());
                }
            }
            // 深度2, 考虑移库
            else {
                str_lst[str_lst.length - 1] = String.format("%02d", depth - 1);
                locationId = String.join("-", str_lst);
                // 判断浅深度有无出库任务
                List<TAppWcsTask> outTasks = appWcsTaskService.list(
                        new LambdaQueryWrapper<TAppWcsTask>()
                                .eq(TAppWcsTask::getOrigin, locationId)
                                .eq(TAppWcsTask::getWcsTaskType, WcsStackerTaskTypeEnums.OUT.getCode()));
                if (outTasks != null && !outTasks.isEmpty()) {
                    continue;
                }
                // 判断浅深度有无入库任务
                List<TAppWcsTask> inTasks = appWcsTaskService.list(
                        new LambdaQueryWrapper<TAppWcsTask>()
                                .eq(TAppWcsTask::getDestination, locationId)
                                .eq(TAppWcsTask::getWcsTaskType, WcsStackerTaskTypeEnums.IN.getCode()));
                if (inTasks != null && !inTasks.isEmpty()) {
                    continue;
                }
                // 判断浅深度有没有库存
                List<TAppStock> preStocks = stockService.list(
                        new LambdaQueryWrapper<TAppStock>()
                                .eq(TAppStock::getLocationId, locationId)
                                .eq(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode()));
                // 若有库存
                if (preStocks != null && !preStocks.isEmpty()) {
                    TAppLocation preLocation = stackerTaskService.getEmptyLocation(equipmentId, locEnum);

                    WcsStackerTaskRequest request = new WcsStackerTaskRequest();
                    request.setTaskId(UUIDUtils.getNewUUID());
                    request.setTaskType(WcsStackerTaskTypeEnums.IN.getCode());
                    request.setPriority(2);
                    request.setOrigin(locationId);
                    request.setDestination(preLocation.getLocationId());
                    request.setVehicleNo(preStocks.getFirst().getVehicleId());

                    try {
                        WcsApiResponse<WcsStackerTask> wcsResponse = wcsApiService.sendWcsStackerTask(request);
                        if (wcsResponse != null && WcsApiResponseCodeEnums.SUCCESS.getCode() == wcsResponse.getCode()) {
                            stockService.update(
                                    new LambdaUpdateWrapper<TAppStock>()
                                        .eq(TAppStock::getLocationId, locationId)
                                        .eq(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode())
                                        .set(TAppStock::getLocationId, preLocation.getLocationId()));
                            appVehicleService.update(
                                    new LambdaUpdateWrapper<TAppVehicle>()
                                        .eq(TAppVehicle::getLocationId, locationId)
                                        .eq(TAppVehicle::getVehicleStatus, WmsVehicleStatusEnums.ON.getCode())
                                        .set(TAppVehicle::getLocationId, preLocation.getLocationId()));
                        }
                    } catch (Exception e) {
                        log.error("堆垛机任务发送失败，任务号：{}，载具号：{}，起点：{}，终点：{}。", request.getTaskId(), request.getVehicleNo(), request.getOrigin(), request.getDestination());
                    }
                }

                // 若浅深度无任务, 无库存
                WcsStackerTaskRequest request = new WcsStackerTaskRequest();
                request.setTaskId(wcsTask.getWcsTaskId());
                request.setTaskType(WcsStackerTaskTypeEnums.OUT.getCode());
                request.setPriority(1);
                request.setOrigin(wcsTask.getOrigin());
                request.setDestination(wcsTask.getDestination());
                request.setVehicleNo(wcsTask.getVehicleId());
                try {
                    WcsApiResponse<WcsStackerTask> wcsResponse = wcsApiService.sendWcsStackerTask(request);
                    if (wcsResponse != null && WcsApiResponseCodeEnums.SUCCESS.getCode() == wcsResponse.getCode()) {
                        appWcsTaskService.update(
                                new LambdaUpdateWrapper<TAppWcsTask>()
                                        .eq(TAppWcsTask::getWcsTaskId, wcsTask.getWcsTaskId())
                                        .set(TAppWcsTask::getWcsTaskStatus, WcsStackerTaskStatusEnums.WAIT.getCode()));
                        // TODO appOrderOutService?
                    }
                } catch (Exception e) {
                    log.error("堆垛机任务发送失败，任务号：{}，载具号：{}，起点：{}，终点：{}。", request.getTaskId(), request.getVehicleNo(), request.getOrigin(), request.getDestination());
                }
            }
        }
    }
}
