package com.wms_main.service.controller.serviceImpl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.wms_main.constant.enums.wcs.WcsStackerTaskStatusEnums;
import com.wms_main.constant.enums.wcs.WcsStackerTaskTypeEnums;
import com.wms_main.constant.enums.wms.OrderStatusEnum;
import com.wms_main.constant.enums.wms.WmsLocationTypeEnums;
import com.wms_main.dao.ITAppLocationService;
import com.wms_main.dao.ITAppOrderInService;
import com.wms_main.dao.ITAppWcsTaskService;
import com.wms_main.model.dto.request.wcs.WcsVehicleInRequest;
import com.wms_main.model.dto.response.wcs.InTaskResp;
import com.wms_main.model.dto.response.wcs.WcsApiResponse;
import com.wms_main.model.po.TAppLocation;
import com.wms_main.model.po.TAppOrderIn;
import com.wms_main.model.po.TAppWcsTask;
import com.wms_main.repository.utils.StringUtils;
import com.wms_main.repository.utils.UUIDUtils;
import com.wms_main.service.business.IStackerTaskService;
import com.wms_main.service.controller.IWcsControllerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class WcsControllerServiceImpl implements IWcsControllerService {

    private final ITAppOrderInService orderInService;
    private final IStackerTaskService stackerTaskService;
    private final ITAppWcsTaskService wcsTaskService;
    private final ITAppLocationService locationService;

    @Override
    @Transactional
    public WcsApiResponse<InTaskResp> requireInTask(WcsVehicleInRequest request) {
        log.info("WCS请求入栈任务请求参数{}", JSON.toJSON(request));
        if(request == null) return WcsApiResponse.error("参数错误", null);
        String point = request.getPoint();
        if(StringUtils.isEmpty(request.getVehicleNo()) || StringUtils.isEmpty(point)) {
            return WcsApiResponse.error("参数错误", null);
        }
        // 一号堆垛机，全部存空托盘
        if(point.equals("105") || point.equals("106") || point.equals("107")) {
            String goodsId567 = "";
            if (point.equals("105")) {
                goodsId567 = "2";
            } else if (point.equals("106")) {
                goodsId567 = "3";
            } else {
                goodsId567 = "4";
            }

            List<TAppOrderIn> withOrderId = orderInService.list(
                    new LambdaQueryWrapper<TAppOrderIn>()
                            .like(TAppOrderIn::getVehicleNo, "FC")
                            .in(TAppOrderIn::getInStand, List.of("105", "106", "107"))
                            .eq(TAppOrderIn::getOrderStatus, OrderStatusEnum.CREATE.getCode())
            );
            if(withOrderId == null) {
                return WcsApiResponse.error("数据服务异常，请稍后重试", null);
            }
            if(withOrderId.isEmpty()) {
                return WcsApiResponse.error("无入库订单", null);
            }
            List<String> vehicleNos = withOrderId.stream().map(TAppOrderIn::getVehicleNo).toList();
            for (String vehicleNo : vehicleNos) {
                // 选一个库位
                TAppLocation targetLocation = stackerTaskService.getEmptyLocation(1, point.equals("105") ? WmsLocationTypeEnums.TYPE_600 : WmsLocationTypeEnums.TYPE_500);
                if(targetLocation == null) {
                    return WcsApiResponse.error("没有空闲库位，请稍后再试", null);
                }
                orderInService.update(
                        new LambdaUpdateWrapper<TAppOrderIn>()
                                .eq(TAppOrderIn::getVehicleNo, vehicleNo)
                                .set(TAppOrderIn::getOrderStatus, OrderStatusEnum.RUNNING.getCode())
                                .set(TAppOrderIn::getDestination, targetLocation.getLocationId())
                                .set(TAppOrderIn::getGoodsId, goodsId567)
                                .set(TAppOrderIn::getBatch, "0")
                                .set(TAppOrderIn::getQuantity, 4.0)

                                .set(TAppOrderIn::getSpecification, "empty")
                                .set(TAppOrderIn::getXsfbillno, goodsId567)
                                .set(TAppOrderIn::getXsfseq, 0)
                                .set(TAppOrderIn::getNeibubianhao, "0")
                                .set(TAppOrderIn::getUpdateTime, LocalDateTime.now())
                );
                // 插入一条WcsTask
                String taskId = UUIDUtils.getNewUUID();
                TAppWcsTask wcsTask = new TAppWcsTask();
                wcsTask.setWcsTaskId(taskId);
                wcsTask.setWcsTaskStatus(WcsStackerTaskStatusEnums.RUN.getCode());
                wcsTask.setWcsTaskType(WcsStackerTaskTypeEnums.IN.getCode());
                wcsTask.setTaskPriority(0);
                wcsTask.setVehicleId(vehicleNo);
                wcsTask.setOrigin(point);
                wcsTask.setDestination(targetLocation.getLocationId());
                wcsTask.setCreateTime(LocalDateTime.now());
                wcsTask.setSendTime(LocalDateTime.now());
                wcsTask.setRemark("WCS");
                boolean saveWcsTask = wcsTaskService.save(wcsTask);
                if(!saveWcsTask) {
                    return WcsApiResponse.error("任务创建失败，请稍后再试", null);
                }
                // 锁定库位
                boolean lockLocation = locationService.updateLocationOccupy(targetLocation.getLocationId(), 1);
                if(!lockLocation) {
                    return WcsApiResponse.error("库位锁定失败，请稍后再试", null);
                }
                InTaskResp inTaskResp = new InTaskResp();
                inTaskResp.setTaskId(taskId);
                inTaskResp.setUser("WMS");
                inTaskResp.setVehicleNo(vehicleNo);
                inTaskResp.setDestination(targetLocation.getLocationId());
                inTaskResp.setSpare1("");
                inTaskResp.setSpare2("");
                return WcsApiResponse.success(inTaskResp);
            }
        }
        // 二号堆垛机，一部分存空一部分存有货位置
        if(point.equals("103") || point.equals("104")) {
            List<String> vehicleNos = List.of(request.getVehicleNo().split(";"));
            for (String vehicleNo : vehicleNos) {
                if(vehicleNo.equals("0")) {   // 空托盘
                    String goodsId34 = point.equals("103") ? "0" : "1";

                    List<TAppOrderIn> withOrderId = orderInService.list(
                            new LambdaQueryWrapper<TAppOrderIn>()
                                    .like(TAppOrderIn::getVehicleNo, "FC")
                                    .in(TAppOrderIn::getInStand, List.of("103", "104"))
                                    .eq(TAppOrderIn::getOrderStatus, OrderStatusEnum.CREATE.getCode())
                    );
                    if(withOrderId == null) {
                        return WcsApiResponse.error("数据服务异常，请稍后重试", null);
                    }
                    if(withOrderId.isEmpty()) {
                        return WcsApiResponse.error("无入库订单", null);
                    }
                    List<String> withVehicleNos = withOrderId.stream().map(TAppOrderIn::getVehicleNo).toList();
                    for (String withVehicleNo : withVehicleNos) {
                        // 选一个库位
                        TAppLocation targetLocation = stackerTaskService.getEmptyLocation(2, WmsLocationTypeEnums.TYPE_EMPTY);
                        if(targetLocation == null) {
                            return WcsApiResponse.error("没有空闲库位，请稍后再试", null);
                        }
                        orderInService.update(
                                new LambdaUpdateWrapper<TAppOrderIn>()
                                        .eq(TAppOrderIn::getVehicleNo, withVehicleNo)
                                        .set(TAppOrderIn::getOrderStatus, OrderStatusEnum.RUNNING.getCode())
                                        .set(TAppOrderIn::getDestination, targetLocation.getLocationId())
                                        .set(TAppOrderIn::getGoodsId, goodsId34)
                                        .set(TAppOrderIn::getBatch, "0")
                                        .set(TAppOrderIn::getQuantity, 1.0)

                                        .set(TAppOrderIn::getSpecification, "empty")
                                        .set(TAppOrderIn::getXsfbillno, goodsId34)
                                        .set(TAppOrderIn::getXsfseq, 0)
                                        .set(TAppOrderIn::getNeibubianhao, "0")
                                        .set(TAppOrderIn::getUpdateTime, LocalDateTime.now())
                        );
                        // 插入一条WcsTask
                        String taskId = UUIDUtils.getNewUUID();
                        TAppWcsTask wcsTask = new TAppWcsTask();
                        wcsTask.setWcsTaskId(taskId);
                        wcsTask.setWcsTaskStatus(WcsStackerTaskStatusEnums.RUN.getCode());
                        wcsTask.setWcsTaskType(WcsStackerTaskTypeEnums.IN.getCode());
                        wcsTask.setTaskPriority(0);
                        wcsTask.setVehicleId(withVehicleNo);
                        wcsTask.setOrigin(point);
                        wcsTask.setDestination(targetLocation.getLocationId());
                        wcsTask.setCreateTime(LocalDateTime.now());
                        wcsTask.setSendTime(LocalDateTime.now());
                        wcsTask.setRemark("WCS");
                        boolean saveWcsTask = wcsTaskService.save(wcsTask);
                        if(!saveWcsTask) {
                            return WcsApiResponse.error("任务创建失败，请稍后再试", null);
                        }
                        // 锁定库位
                        boolean lockLocation = locationService.updateLocationOccupy(targetLocation.getLocationId(), 1);
                        if(!lockLocation) {
                            return WcsApiResponse.error("库位锁定失败，请稍后再试", null);
                        }
                        InTaskResp inTaskResp = new InTaskResp();
                        inTaskResp.setTaskId(taskId);
                        inTaskResp.setUser("WMS");
                        inTaskResp.setVehicleNo(withVehicleNo);
                        inTaskResp.setDestination(targetLocation.getLocationId());
                        inTaskResp.setSpare1("");
                        inTaskResp.setSpare2("");
                        return WcsApiResponse.success(inTaskResp);
                    }
                } else {    // 带料
                    // 选一个库位
                    TAppLocation targetLocation = stackerTaskService.getEmptyLocation(2, WmsLocationTypeEnums.TYPE_PRODUCT);
                    if(targetLocation == null) {
                        return WcsApiResponse.error("没有空闲库位，请稍后再试", null);
                    }
                    // 校验是否存在入库单
                    List<TAppOrderIn> withOrderId = orderInService.getWithVehicleNoAndStatus(vehicleNo, OrderStatusEnum.CREATE);
                    if(withOrderId == null) {
                        return WcsApiResponse.error("数据服务异常，请稍后重试", null);
                    }
                    if(withOrderId.isEmpty()) {
                        log.error("载具号无效或过期{}", vehicleNo);
                        continue;
                    }
                    // TODO 和 入库单校验，WCS 传过来的子条吗数据在条吗里面，用分号隔开
                    // TODO 和 mes 校验
                    // 更新入库单状态为运行中
                    boolean updateStatusWithVehicleNo = orderInService.updateStatusAndDestinationWithVehicleNo(vehicleNo, OrderStatusEnum.RUNNING, targetLocation.getLocationId());
                    if(!updateStatusWithVehicleNo) {
                        return WcsApiResponse.error("入库单状态更新失败，请稍后再试", null);
                    }
                    // 插入一条WcsTask
                    String taskId = UUIDUtils.getNewUUID();
                    TAppWcsTask wcsTask = new TAppWcsTask();
                    wcsTask.setWcsTaskId(taskId);
                    wcsTask.setWcsTaskStatus(WcsStackerTaskStatusEnums.RUN.getCode());
                    wcsTask.setWcsTaskType(WcsStackerTaskTypeEnums.IN.getCode());
                    wcsTask.setTaskPriority(0);
                    wcsTask.setVehicleId(vehicleNo);
                    wcsTask.setOrigin(point);
                    wcsTask.setDestination(targetLocation.getLocationId());
                    wcsTask.setCreateTime(LocalDateTime.now());
                    wcsTask.setSendTime(LocalDateTime.now());
                    wcsTask.setRemark(withOrderId.getFirst().getClientId());
                    boolean saveWcsTask = wcsTaskService.save(wcsTask);
                    if(!saveWcsTask) {
                        return WcsApiResponse.error("任务创建失败，请稍后再试", null);
                    }
                    // 锁定库位
                    boolean lockLocation = locationService.updateLocationOccupy(targetLocation.getLocationId(), 1);
                    if(!lockLocation) {
                        return WcsApiResponse.error("库位锁定失败，请稍后再试", null);
                    }
                    InTaskResp inTaskResp = new InTaskResp();
                    inTaskResp.setTaskId(taskId);
                    inTaskResp.setUser("WMS");
                    inTaskResp.setVehicleNo(vehicleNo);
                    inTaskResp.setDestination(targetLocation.getLocationId());
                    inTaskResp.setSpare1("");
                    inTaskResp.setSpare2("");
                    return WcsApiResponse.success(inTaskResp);
                }
            }
        }
        // 三号堆垛机
        if(point.equals("101") || point.equals("102")) {
            List<String> vehicleNos = List.of(request.getVehicleNo().split(";"));
            for (String vehicleNo : vehicleNos) {
                // 选一个库位
                TAppLocation targetLocation = stackerTaskService.getEmptyLocation(3, WmsLocationTypeEnums.TYPE_PRODUCT);
                if(targetLocation == null) {
                    return WcsApiResponse.error("没有空闲库位，请稍后再试", null);
                }
                // 校验是否存在入库单
                List<TAppOrderIn> withOrderId = orderInService.getWithVehicleNoAndStatus(vehicleNo, OrderStatusEnum.CREATE);
                if(withOrderId == null) {
                    return WcsApiResponse.error("数据服务异常，请稍后重试", null);
                }
                if(withOrderId.isEmpty()) {
                    log.error("载具号无效或过期{}", vehicleNo);
                    continue;
                }
                // TODO 和 入库单校验，WCS 传过来的子条吗数据在条吗里面，用分号隔开
                // TODO 和 mes 校验
                // 更新入库单状态为运行中
                boolean updateStatusWithVehicleNo = orderInService.updateStatusAndDestinationWithVehicleNo(vehicleNo, OrderStatusEnum.RUNNING, targetLocation.getLocationId());
                if(!updateStatusWithVehicleNo) {
                    return WcsApiResponse.error("入库单状态更新失败，请稍后再试", null);
                }
                // 插入一条WcsTask
                String taskId = UUIDUtils.getNewUUID();
                TAppWcsTask wcsTask = new TAppWcsTask();
                wcsTask.setWcsTaskId(taskId);
                wcsTask.setWcsTaskStatus(WcsStackerTaskStatusEnums.RUN.getCode());
                wcsTask.setWcsTaskType(WcsStackerTaskTypeEnums.IN.getCode());
                wcsTask.setTaskPriority(0);
                wcsTask.setVehicleId(vehicleNo);
                wcsTask.setOrigin(point);
                wcsTask.setDestination(targetLocation.getLocationId());
                wcsTask.setCreateTime(LocalDateTime.now());
                wcsTask.setSendTime(LocalDateTime.now());
                wcsTask.setRemark(withOrderId.getFirst().getClientId());
                boolean saveWcsTask = wcsTaskService.save(wcsTask);
                if(!saveWcsTask) {
                    return WcsApiResponse.error("任务创建失败，请稍后再试", null);
                }
                // 锁定库位
                boolean lockLocation = locationService.updateLocationOccupy(targetLocation.getLocationId(), 1);
                if(!lockLocation) {
                    return WcsApiResponse.error("库位锁定失败，请稍后再试", null);
                }
                InTaskResp inTaskResp = new InTaskResp();
                inTaskResp.setTaskId(taskId);
                inTaskResp.setUser("WMS");
                inTaskResp.setVehicleNo(vehicleNo);
                inTaskResp.setDestination(targetLocation.getLocationId());
                inTaskResp.setSpare1("");
                inTaskResp.setSpare2("");
                return WcsApiResponse.success(inTaskResp);
            }
        }
        return WcsApiResponse.error("不支持的入库位置", null);
    }
}
