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.app.AppCommon;
import com.wms_main.constant.enums.wms.OrderStatusEnum;
import com.wms_main.constant.enums.wms.WmsStackerTaskStatusEnums;
import com.wms_main.constant.enums.wms.WmsStockStatusEnums;
import com.wms_main.constant.enums.wms.WmsTaskTypeEnums;
import com.wms_main.dao.ITAppOrderOutService;
import com.wms_main.dao.ITAppStockService;
import com.wms_main.dao.ITAppTaskService;
import com.wms_main.model.po.TAppLocation;
import com.wms_main.model.po.TAppOrderOut;
import com.wms_main.model.po.TAppStock;
import com.wms_main.model.po.TAppTask;
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.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.PersistJobDataAfterExecution;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Slf4j
@PersistJobDataAfterExecution
// 以下注解用于实现fixed_delay
@DisallowConcurrentExecution
@RequiredArgsConstructor
public class MyOutExecutor implements Job {
    private final ITAppOrderOutService appOrderOutService;
    private final ITAppStockService appStockService;
    private final ITAppTaskService appTaskService;
    private final IStackerTaskService stackerTaskService;
    private final AppCommon appCommon;

    @Override
    public void execute(JobExecutionContext context) {
        processOutOrders();
    }

    /**
     * 处理所有待处理的出库订单
     */
    private void processOutOrders() {
        // 获取状态为CREATE的出库订单
        List<TAppOrderOut> orders = appOrderOutService.list(
                new LambdaQueryWrapper<TAppOrderOut>()
                        .eq(TAppOrderOut::getOrderStatus, OrderStatusEnum.CREATE.getCode()));

        orders.forEach(this::processSingleOrder);
    }

    /**
     * 处理单个出库订单
     */
    private void processSingleOrder(TAppOrderOut order) {
        try {
            // 1. 根据载具号获取关联库存
            TAppStock stock = getStockByVehicleNo(order.getVehicleNo());
            if (stock == null) {
                log.error("未找到载具号关联的库存: {}", order.getVehicleNo());
                return;
            }

            // 2. 获取库位深度
            Integer depth = getLocationDepth(stock.getLocationId());
            if (depth == null) {
                log.error("无法解析库位深度: {}", stock.getLocationId());
                return;
            }

            // 3. 根据深度生成任务
            List<TAppTask> tasks = new ArrayList<>();
            if (depth == 1) {
                tasks.add(createOutTask(order, stock));
            } else if (depth == 2) {
                // 检查深度1是否有阻挡货物
                List<TAppStock> blockingStocks = getBlockingStocks(stock.getLocationId());
                if (!blockingStocks.isEmpty()) {
                    // 生成移库任务移走阻挡货物
                    blockingStocks.forEach(blocking -> tasks.add(createTransferTask(blocking, order)));
                }
                tasks.add(createOutTask(order, stock));
            } else {
                log.error("不支持的库存深度: {}", depth);
                return;
            }

            // 4. 保存任务并更新状态
            if (saveTasks(tasks, order)) {
                updateStockStatus(stock); // 更新库存状态为出库中
                updateOrderStatus(order); // 更新订单状态
            }
        } catch (Exception e) {
            log.error("处理出库订单失败: {}", order.getOrderId(), e);
        }
    }

    /**
     * 根据载具号获取唯一库存
     */
    private TAppStock getStockByVehicleNo(String vehicleNo) {
        return appStockService.getOne(
                new LambdaQueryWrapper<TAppStock>()
                        .eq(TAppStock::getVehicleId, vehicleNo)
                        .eq(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode()));
    }

    /**
     * 获取深度1的阻挡库存
     */
    private List<TAppStock> getBlockingStocks(String locationId) {
        String[] parts = locationId.split("-");
        if (parts.length < 4)
            return Collections.emptyList();

        // 构建深度1库位ID (格式: 排-列-层-01)
        String depth1Loc = parts[0] + "-" + parts[1] + "-" + parts[2] + "-01";

        return appStockService.list(
                new LambdaQueryWrapper<TAppStock>()
                        .eq(TAppStock::getLocationId, depth1Loc)
                        .eq(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode()));
    }

    /**
     * 创建移库任务
     */
    private TAppTask createTransferTask(TAppStock blockingStock, TAppOrderOut order) {
        // 申请空闲库位
        TAppLocation target = stackerTaskService.requestOneLocation(null, blockingStock.getVehicleId());

        TAppTask task = new TAppTask();
        task.setTaskId(UUIDUtils.getNewUUID());
        task.setTaskType(WmsTaskTypeEnums.TRANSFER.getCode());
        task.setTaskGroup(order.getOrderId());
        task.setTaskStatus(WmsStackerTaskStatusEnums.WAIT.getCode());
        task.setOrigin(blockingStock.getLocationId());
        task.setDestination(target.getLocationId());
        task.setVehicleId(blockingStock.getVehicleId());
        task.setCreateTime(LocalDateTime.now());
        task.setTaskPriority(2);
        task.setRemark("移走深度1阻挡货物");

        appCommon.updateWorkingLocations(blockingStock.getLocationId(), 1);
        appCommon.updateWorkingLocations(target.getLocationId(), 1);
        return task;
    }

    /**
     * 创建出库任务
     */
    private TAppTask createOutTask(TAppOrderOut order, TAppStock stock) {
        TAppTask task = new TAppTask();
        task.setTaskId(UUIDUtils.getNewUUID());
        task.setTaskType(WmsTaskTypeEnums.OUT.getCode());
        task.setTaskGroup(order.getOrderId());
        task.setTaskStatus(WmsStackerTaskStatusEnums.WAIT.getCode());
        task.setOrigin(stock.getLocationId());
        task.setDestination("CR");
        task.setVehicleId(stock.getVehicleId());
        task.setCreateTime(LocalDateTime.now());
        task.setTaskPriority(1);
        task.setRemark(stock.getLocationId().endsWith("-01") ? "深度1直接出库" : "深度2出库");

        appCommon.updateWorkingLocations(stock.getLocationId(), 1);
        return task;
    }

    /**
     * 批量保存任务
     */
    private boolean saveTasks(List<TAppTask> tasks, TAppOrderOut order) {
        return !tasks.isEmpty() && appTaskService.saveBatch(tasks);
    }

    /**
     * 更新库存状态
     */
    private void updateStockStatus(TAppStock stock) {
        appStockService.update(
                new LambdaUpdateWrapper<TAppStock>()
                        .eq(TAppStock::getStockId, stock.getStockId())
                        .set(TAppStock::getStockStatus, WmsStockStatusEnums.OUTING.getCode()));
    }

    /**
     * 更新订单状态
     */
    private void updateOrderStatus(TAppOrderOut order) {
        appOrderOutService.update(
                new LambdaUpdateWrapper<TAppOrderOut>()
                        .eq(TAppOrderOut::getRecordId, order.getRecordId())
                        .set(TAppOrderOut::getOrderStatus, OrderStatusEnum.RUNNING.getCode()));
    }

    /**
     * 获取指定库位的深度信息
     * 解析库位ID获取深度值
     */
    private Integer getLocationDepth(String locationId) {
        if (StringUtils.isEmpty(locationId)) {
            return 0;
        }

        try {
            // 解析库位ID格式：A03-1-2-3（排-列-层-深度）
            String[] parts = locationId.split("-");
            if (parts.length >= 4) {
                return Integer.parseInt(parts[3]);
            }
        } catch (Exception e) {
            log.warn("解析库位深度失败：{}", locationId, e);
        }

        return 0;
    }
}