package com.ruoyi.wms.service;


import com.alibaba.fastjson.JSONObject;
import com.cmeim.common.core.utils.BeanUtil;
import com.cmeim.common.core.utils.DateUtil;
import com.cmeim.common.core.utils.StringUtils;
import com.cmeim.common.core.web.domain.RespondEnum;
import com.ruoyi.ruiYiController.exception.ServiceException;
import com.ruoyi.wms.enums.AgvTaskEnum;
import com.ruoyi.wms.enums.RequestEnum;
import com.ruoyi.wms.po.*;
import com.ruoyi.wms.repository.*;
import com.ruoyi.wms.util.HttpRequest;
import com.ruoyi.wms.vo.AgvRequestVo;
import com.ruoyi.wms.vo.ContainerArrivedVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.Map.Entry.comparingByValue;
import static org.springframework.data.util.Pair.toMap;

/**
 * @Verasion:1.0
 * @Author:DZY
 * @Date:2023/6/26
 **/
@Service
@Slf4j
public class AGVService {
    @Autowired
    private AgvTaskRepository agvTaskRepository;

    @Autowired
    private ContainerInfoRepository containerInfoRepository;
    @Autowired
    private StationInfoRepository stationInfoRepository;
    @Autowired
    private StoreInfoRepository storeInfoRepository;
    @Autowired
    private OrderInfoRepository orderInfoRepository;
    @Autowired
    private AreaConfigRepository areaConfigRepository;
    @Autowired
    private ShelfInfoRepository shelfInfoRepository;
    @Autowired
    private SensorStoreBindRepository sensorStoreBindRepository;
    @Autowired
    private ContainerRecoderRepository containerRecoderRepository;

    /**
     * 生成AGV搬运请求参数
     *
     * @param requestVo
     */
    public String taskParamCreate(AgvRequestVo requestVo) {
        UUID uuid = UUID.randomUUID();
        String taskCode = uuid.toString();
        JSONObject data = new JSONObject(true);
        //搬运方式
        if (requestVo.getType() == 1) {
            //货架方式
            data.put("taskType", "putaway");
        } else {
            //搬运方式
            data.put("taskType", "carry");
        }
        //任务组优先级
        data.put("groupPriority", 0);
        List<JSONObject> taskList = new ArrayList<>();
        JSONObject data1 = new JSONObject(true);
        //任务单号
        data1.put("taskCode", taskCode);
        //任务优先级
        data1.put("taskPriority", 2);
        JSONObject data2 = new JSONObject(true);
        //容器编码
        data2.put("containerCode", requestVo.getContainerCode());
        //容器类型
        data2.put("containerType", "CT_KUBOT_STANDARD");
        if (requestVo.getRequestType() > 3) {
            data2.put("containerType", "CT_KIVA_STANDARD");
        }
        //工作为标签
        final AreaConfig areaConfig = areaConfigRepository.findByAreaType(requestVo.getRequestType());
        if (areaConfig == null) {
            data2.put("storageTag", "10");
        }
        //起始工作位
        data2.put("fromLocationCode", requestVo.getFromLocationCode());
        //目标工作位
        data2.put("toLocationCode", requestVo.getToLocationCode());
        //目标工作站
        data2.put("toStationCode", requestVo.getToStationCode());
        data1.put("taskDescribe", data2);
        taskList.add(data1);
        data.put("tasks", taskList);
        log.info("param:" + JSONObject.toJSONString(data));
        final String result = taskCreate(JSONObject.toJSONString(data), requestVo.getRequestType());
        log.info("result:" + result);
        //呼叫空箱或入水测调用容器送达接口
        if (requestVo.getRequestType() == 0 || requestVo.getRequestType() == 2) {
            ContainerArrivedVo containerArrivedVo = new ContainerArrivedVo();
            containerArrivedVo.setSlotCode(requestVo.getFromLocationCode());
            containerArrivedVo.setContainerCode(requestVo.getContainerCode());
            JSONObject data3 = new JSONObject(true);
            data3.put("containerCode", requestVo.getContainerCode());
            data3.put("slotCode", requestVo.getFromLocationCode());
            log.info("param2:" + JSONObject.toJSONString(data3));
            containerArrived(JSONObject.toJSONString(data3));
        }
        //出库调用容器离场接口
        //if (requestVo.getRequestType() == 9) {
        //    moveOut(requestVo.getContainerCode(), requestVo.getToLocationCode());
        //}
        return result;

    }

    /**
     * 发送AGV搬运请求
     *
     * @param param       请求参数
     * @param requestType 请求类型
     */
    @Transactional
    public String taskCreate(String param, Integer requestType) {
        final String result = HttpRequest.doPost("http://192.168.33.45:9046/task/create", param);
        if (JSONObject.parseObject(result).getInteger("code") == 0) {
            //根据任务列表存入调用记录
            JSONObject.parseObject(param).getJSONArray("tasks").forEach(e -> {
                String taskCode = JSONObject.parseObject(JSONObject.toJSONString(e)).getString("taskCode");
                updateAgvTask(taskCode, requestType, JSONObject.toJSONString(e), AgvTaskEnum.ONGOING.getCode(), "");
            });
        } else {
            String taskCode = JSONObject.parseObject(JSONObject.toJSONString(JSONObject.parseObject(param)
                    .getJSONArray("tasks").get(0))).getString("taskCode");
            updateAgvTask(taskCode, requestType, param, AgvTaskEnum.FAIL.getCode(), JSONObject.parseObject(result).getString("msg"));
        }
        return result;
    }

    /**
     * 发送容器到达通知
     *
     * @param param 请求参数
     */
    @Transactional
    public void containerArrived(String param) {
        HttpRequest.doPost("http://192.168.33.45:9046/conveyor/containerArrived", param);
    }

    /**
     * 是否允许取走/放置周转箱
     *
     * @param param 请求参数
     */
    @Transactional
    public String allowOperation(String param) {
        final String result = HttpRequest.doPost("http://192.168.33.211:8081/AllowOperation", param);
        return result;
    }

    /**
     * 更新agv任务表
     *
     * @param taskCode    请求单号
     * @param requestType 请求类型
     * @param param       请求参数
     * @param status      请求状态
     */
    public void updateAgvTask(String taskCode, Integer requestType, String param, Integer status, String message) {
        AgvTask agvTask = new AgvTask();
        agvTask = agvTaskRepository.findByRequestCode(taskCode);
        if (agvTask == null) {
            AgvTask task = new AgvTask();
            agvTask = BeanUtil.copyProperties(task, AgvTask.class);
            agvTask.setCreatedBy("admin");
            agvTask.setCreatedDt(DateUtil.getCurrentDate());
            agvTask.setDictType(requestType);
        } else {
            agvTask.setUpdatedBy("admin");
            agvTask.setUpdatedDt(DateUtil.getCurrentDate());

        }
        agvTask.setJson(param);
        agvTask.setRequestCode(taskCode);
        agvTask.setStatus(status);
        agvTask.setMessage(message);
        agvTaskRepository.save(agvTask);
    }

    /**
     * 取消修改周转箱
     *
     * @param param  json
     */
    public void updateContainer(String param, Integer dictType) {
        final String containerCode = JSONObject.parseObject(param).getString("containerCode");
        if (dictType == 3) {
            ContainerInfo containerInfo = containerInfoRepository.findByContainerNumber(containerCode);
            String productionTask = containerInfo.getProductionTask();
            //修改生产任务单的出库中数量和出库数量
            OrderInfo orderInfo = orderInfoRepository.findByProductionTask(productionTask);
            orderInfo.setOnoutingCheckQty(orderInfo.getOnoutingCheckQty() - containerInfo.getQty());
            orderInfo.setOutQty(orderInfo.getOutQty() + containerInfo.getQty());
            orderInfo.setUpdatedDt(DateUtil.getCurrentDate());
            orderInfoRepository.save(orderInfo);
            //修改对应周转箱为空闲（库外）
            containerInfo.setQty(0);
            containerInfo.setContainerStatus(5);
            containerInfo.setStoreCode(null);
            containerInfo.setOnInstoreTime(null);
            containerInfo.setProductionTask(null);
            containerInfo.setIsPdaEdit(0);
            containerInfo.setUpdatedDt(DateUtil.getCurrentDate());
            containerInfoRepository.save(containerInfo);
        }
    }

    /**
     * 取消AGV任务
     *
     * @param taskCode
     */

    public void taskCancel(String taskCode) {
        List<String> list = new ArrayList<>();
        list.add(taskCode);
        JSONObject data = new JSONObject();
        data.put("taskCodes", list);
        final AgvTask agvTask = agvTaskRepository.findByRequestCodeAndStatus(taskCode, 2);
        if (null == agvTask) {
            throw new com.ruoyi.ruiYiController.exception.ServiceException( "没有该待执行任务",10000);
        }
        final String result = HttpRequest.doPost("http://192.168.33.45:9046/task/cancel", JSONObject.toJSONString(data));
        log.info("取消任务result：" + JSONObject.toJSONString(result));
        if (JSONObject.parseObject(result).getInteger("code") == 0) {
            updateAgvTask(taskCode, agvTask.getDictType(), agvTask.getJson(), AgvTaskEnum.CANCEL.getCode(), "");
            updateContainer(agvTask.getJson(), agvTask.getDictType());
        } else {
            updateAgvTask(taskCode, agvTask.getDictType(), agvTask.getJson(), AgvTaskEnum.FAIL.getCode(), JSONObject.parseObject(result).getString("msg"));
            updateContainer(agvTask.getJson(), agvTask.getDictType());
        }
    }

    /**
     * 容器移入
     * @param containerCode
     * @param positionCode
     */
    public String moveIn(String containerCode, String positionCode) {
        JSONObject data1 = new JSONObject(true);
        data1.put("containerCode", containerCode);
        data1.put("positionCode", positionCode);
        JSONObject data = new JSONObject();
        List<JSONObject> taskList = new ArrayList<>();
        taskList.add(data1);
        data.put("containerMoveIns", taskList);
        log.info("容器移入：" + JSONObject.toJSONString(data));
        final String result = HttpRequest.doPost("http://192.168.33.45:9046/expand/api/moveIn/Container", JSONObject.toJSONString(data));
        return result;
    }

    /**
     * 容器离场
     * @param containerCode
     * @param positionCode
     */
    public void moveOut(String containerCode, String positionCode) {
        JSONObject data1 = new JSONObject(true);
        data1.put("containerCode", containerCode);
        data1.put("positionCode", positionCode);
        JSONObject data = new JSONObject();
        List<JSONObject> taskList = new ArrayList<>();
        taskList.add(data1);
        data.put("containerMoveOuts", taskList);
        final String result = HttpRequest.doPost("http://192.168.33.45:9046/expand/api/moveOut/Container", JSONObject.toJSONString(data));
    }

    /**
     * 告知滚筒线箱子已取走/已放下
     * @param param
     */
    public void noticeToPlc(String param)
    {
        HttpRequest.doPost("http://192.168.33.211:8081/OperationSucceed", param);
    }

    /**
     * 修改【取】点位的状态
     * @param locationCode
     */
    public void updateStationStatus(String locationCode)
    {
        StationInfo stationInfo = stationInfoRepository.findByStationCode(locationCode);
        if (stationInfo != null) {
            stationInfo.setStationStatus(5);
            stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
        }
    }

    /**
     * 请求空箱
     *
     * @param requestVo
     */
    @Transactional
    public void EmptyContainerOutStore(AgvRequestVo requestVo) {
        final List<ContainerInfo> containerInfos = containerInfoRepository.findByContainerStatus(10);
        if (containerInfos.size() == 0) {
            return;
        }
        //优化筛选逻辑，按货架的序号分组，取最多的一组
        for (ContainerInfo containerInfo : containerInfos) {
            if (StringUtils.isNotBlank(containerInfo.getStoreCode())) {
                containerInfo.setArea(containerInfo.getStoreCode().substring(6, 8));
            }
        }
        Map<String, List<ContainerInfo>> collect = containerInfos.stream().collect(Collectors.groupingBy(ContainerInfo::getArea));
        List<Map.Entry<String, List<ContainerInfo>>> sortedList = collect.entrySet().stream()
                .sorted(Comparator.comparingInt(entry -> entry.getValue().size()))
                .collect(Collectors.toList());
        final List<ContainerInfo> value = sortedList.get(sortedList.size()-1).getValue();
        //判断请求空箱数量是否大约仓库空箱数量
        if (value.size() < requestVo.getBoxNumber()) {
            requestVo.setBoxNumber(value.size());
        }
        List<ContainerInfo> sendContainer = new ArrayList<>();
        JSONObject data = new JSONObject(true);
        //搬运方式
        if (requestVo.getType() == 1) {
            //货架方式
            data.put("taskType", "putaway");
        } else {
            //搬运方式
            data.put("taskType", "carry");
        }
        //任务组优先级
        data.put("groupPriority", 0);
        List<JSONObject> taskList = new ArrayList<>();
        for (int i = 0; i < requestVo.boxNumber; i++) {
            UUID uuid = UUID.randomUUID();
            String taskCode = uuid.toString();
            ContainerInfo containerInfo = value.get(i);
            JSONObject data1 = new JSONObject(true);
            //任务单号
            data1.put("taskCode", taskCode);
            //任务优先级
            data1.put("taskPriority", 1);
            JSONObject data2 = new JSONObject(true);
            //容器编码
            data2.put("containerCode", containerInfo.getContainerNumber());
            //容器类型
            data2.put("containerType", "CT_KUBOT_STANDARD");
            //工作为标签
            data2.put("storageTag", "");
            //起始工作位
            data2.put("fromLocationCode", requestVo.getFromLocationCode());
            //目标工作位
            data2.put("toLocationCode", requestVo.getToLocationCode());
            //目标工作站
            data2.put("toStationCode", "");
            data1.put("taskDescribe", data2);
            taskList.add(data1);
            sendContainer.add(containerInfo);
        }
        if (taskList.size() == 0) {
            throw new ServiceException("仓库暂无空料箱！");
        }
        data.put("tasks", taskList);
        log.info("param:" + JSONObject.toJSONString(data));
        final String result = taskCreate(JSONObject.toJSONString(data), requestVo.getRequestType());
        int code = JSONObject.parseObject(result).getInteger("code");
        //请求发送成功
        if (code == 0) {
            sendContainer.forEach(e -> {
                //修改为出库中状态
                e.setContainerStatus(35);
                containerInfoRepository.save(e);
                //修改库位状态,待空闲
                StoreInfo storeInfo = storeInfoRepository.findByStoreCode(e.getStoreCode());
                if (storeInfo != null) {
                    storeInfo.setStoreStatus(20);
                    storeInfoRepository.save(storeInfo);
                }
            });
        } else {
            throw new ServiceException("任务发起失败",10000);
        }

    }


    /**
     * AGV回调处理成功信息
     *
     * @param agvTask    AGV任务列表数据
     * @param jsonObject 回调信息
     */
    @Transactional
    public void callBackSuccess(AgvTask agvTask, JSONObject jsonObject) {
        Integer type = agvTask.getDictType();
        switch (type) {
            //空箱
            case 1:
                callBackNullBox(jsonObject);
                break;
            //入恒温区
            case 2:
                callBackInStore(jsonObject);
                break;
            //出恒温区
            case 3:
                callBackOutStore(jsonObject);
                break;
            //送待检缓存区
            case 4:
                callBackSendWaitCheck(jsonObject);
                break;
            //送检验
            case 5:
                callBackSendCheck(jsonObject);
                break;
            //回待检区
            case 6:
                callBackBackWaitCheck(jsonObject);
                break;
            //送抽检
            case 7:
                callBackSendPortCheck(jsonObject);
                break;
            //送成品库
            case 8:
                callBackSendProdStore(jsonObject);
                break;
            //成品出库
            case 9:
                callBackOutProdStore(jsonObject);
                break;
            //空货架入库
            case 10:
                callBackSendNullShelf(jsonObject);
                break;
            //呼叫空货架
            case 11:
                callBackCallNullShelf(jsonObject);
                break;

        }
    }

    /**
     * 请求空箱子成功回调
     *
     * @param jsonObject 回调参数
     */
    @Transactional
    public void callBackNullBox(JSONObject jsonObject) {
        //容器编码
        final String containerCode = jsonObject.getString("containerCode");
        final ContainerInfo containerInfo = containerInfoRepository.findByContainerNumber(containerCode);
        //修改库位状态
        final StoreInfo storeInfo = storeInfoRepository.findByStoreCode(containerInfo.getStoreCode());
        if (null != storeInfo) {
            storeInfo.setStoreStatus(5);
            storeInfo.setUpdatedDt(DateUtil.getCurrentDate());
            storeInfoRepository.save(storeInfo);
        }
        //修改箱子状态为库外空闲
        containerInfo.setContainerStatus(5);
        containerInfo.setStoreCode(null);
        containerInfo.setUpdatedDt(DateUtil.getCurrentDate());
        ContainerInfo save1 = containerInfoRepository.save(containerInfo);
        //增加历史记录表
        ContainerRecoder containerRecoder = BeanUtil.copyProperties(save1, ContainerRecoder.class);
        containerRecoder.setCreatedDt(DateUtil.getCurrentDate());
        containerRecoder.setId(null);
        containerRecoderRepository.save(containerRecoder);

    }

    /**
     * 入恒温区成功回调
     *
     * @param jsonObject
     */
    @Transactional
    public void callBackInStore(JSONObject jsonObject) {
        //容器编码
        final String containerCode = jsonObject.getString("containerCode");
        final String locationCode = jsonObject.getString("locationCode");
        final ContainerInfo containerInfo = containerInfoRepository.findByContainerNumber(containerCode);
        containerInfo.setStoreCode(locationCode);
        //修改箱子状态在库
        if (containerInfo.getContainerStatus() == 25) {
            containerInfo.setContainerStatus(10);
        } else {
            containerInfo.setContainerStatus(30);
        }
        containerInfo.setInstoreTime(DateUtil.getCurrentDate());
        containerInfo.setUpdatedDt(DateUtil.getCurrentDate());
        ContainerInfo save = containerInfoRepository.save(containerInfo);
        //增加历史记录表
        ContainerRecoder containerRecoder = BeanUtil.copyProperties(save, ContainerRecoder.class);
        containerRecoder.setCreatedDt(DateUtil.getCurrentDate());
        containerRecoder.setId(null);
        containerRecoderRepository.save(containerRecoder);
        //修改库位信息状态在库
        final StoreInfo storeInfo = storeInfoRepository.findByStoreCode(locationCode);
        if (storeInfo != null) {
            storeInfo.setStoreStatus(15);
            storeInfo.setUpdatedDt(DateUtil.getCurrentDate());
            storeInfoRepository.save(storeInfo);
        }
        //修改单据出库数据
        final OrderInfo orderInfo = orderInfoRepository.findByProductionTask(containerInfo.getProductionTask());
        if (orderInfo != null) {
            if (orderInfo.getInQty() == null) {
                orderInfo.setInQty(0);
            }
            orderInfo.setInQty(orderInfo.getInQty() + containerInfo.getQty());
            orderInfo.setOngoingQty(orderInfo.getOngoingQty() - containerInfo.getQty());
            orderInfo.setUpdatedDt(DateUtil.getCurrentDate());
            if (orderInfo.getInQty().equals(orderInfo.getPlanQty())) {
                orderInfo.setOrderStatus(15);
            } else {
                orderInfo.setOrderStatus(10);
            }
            orderInfoRepository.save(orderInfo);
        }
    }

    /**
     * 出恒温区成功回调
     *
     * @param jsonObject
     */
    @Transactional
    public void callBackOutStore(JSONObject jsonObject) {
        //容器编码
        final String containerCode = jsonObject.getString("containerCode");
        final ContainerInfo containerInfo = containerInfoRepository.findByContainerNumber(containerCode);
        //如果容器现在状态是入库中则不更新
        //if (containerInfo.getContainerStatus() == 15 || containerInfo.getContainerStatus() == 20 ||containerInfo.getContainerStatus() == 25) {
        //    return;
        //}
        //修改单据出库数据
        final OrderInfo orderInfo = orderInfoRepository.findByProductionTask(containerInfo.getProductionTask());
        if (orderInfo != null) {
            orderInfo.setOutQty(orderInfo.getOutQty() + containerInfo.getQty());
            orderInfo.setOnoutingCheckQty(orderInfo.getOnoutingCheckQty() - containerInfo.getQty());
            orderInfo.setUpdatedDt(DateUtil.getCurrentDate());
            orderInfoRepository.save(orderInfo);
        }
        //修改箱子状态为库外空闲
        containerInfo.setContainerStatus(5);
        containerInfo.setOutstoreTime(DateUtil.getCurrentDate());

        //增加历史记录表
        ContainerRecoder containerRecoder = BeanUtil.copyProperties(containerInfo, ContainerRecoder.class);
        containerRecoder.setId(null);
        containerRecoder.setCreatedDt(DateUtil.getCurrentDate());
        containerRecoderRepository.save(containerRecoder);

        containerInfo.setStoreCode(null);
        containerInfo.setQty(0);
        containerInfo.setProductionTask(null);
        containerInfo.setOutstoreTime(null);
        containerInfo.setUpdatedDt(null);
        containerInfo.setOnInstoreTime(null);
        containerInfo.setInstoreTime(null);
        containerInfoRepository.save(containerInfo);
    }

    /**
     * 送待检区回调
     *
     * @param jsonObject 回调参数
     */
    @Transactional
    public void callBackSendWaitCheck(JSONObject jsonObject) {
        final String locationCode = jsonObject.getString("locationCode");

        //修改终点库位状态
        final StationInfo stationInfo = stationInfoRepository.findByStationCode(locationCode);
        if (stationInfo != null) {
            stationInfo.setStationStatus(20);
            stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
            stationInfoRepository.save(stationInfo);
        }
        //修改货架状态为待检
        final String shelfCode = jsonObject.getString("containerCode");
        final ShelfInfo shelfInfo = shelfInfoRepository.findByShelfCode(shelfCode);
        if (shelfInfo != null) {
            shelfInfo.setShelfStatus(5);
            shelfInfo.setOrderStatus(5);
            shelfInfo.setStationCode(locationCode);
            shelfInfo.setUpdatedDt(DateUtil.getCurrentDate());
            shelfInfoRepository.save(shelfInfo);
        }
        //修改单据出库数据
        final OrderInfo orderInfo = orderInfoRepository.findByProductionTask(shelfInfo.getProductionTask());
        orderInfo.setWaitCheckQty(orderInfo.getWaitCheckQty() + shelfInfo.getQty());
        orderInfo.setUpdatedDt(DateUtil.getCurrentDate());
        orderInfoRepository.save(orderInfo);
    }

    /**
     * 送检验回调
     *
     * @param jsonObject 回调参数
     */
    public void callBackSendCheck(JSONObject jsonObject) {
        //库位码
        final String locationCode = jsonObject.getString("locationCode");
        //修改库位状态
        final StationInfo stationInfo = stationInfoRepository.findByStationCode(locationCode);
        if (stationInfo != null) {
            stationInfo.setStationStatus(20);
            stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
            stationInfoRepository.save(stationInfo);
        }
        //修改货架状态为待检
        final String shelfCode = jsonObject.getString("containerCode");
        final ShelfInfo shelfInfo = shelfInfoRepository.findByShelfCode(shelfCode);
        if (shelfInfo != null) {
            shelfInfo.setShelfStatus(5);
            shelfInfo.setOrderStatus(20);
            shelfInfo.setStationCode(locationCode);
            shelfInfo.setUpdatedDt(DateUtil.getCurrentDate());
            shelfInfoRepository.save(shelfInfo);
        }
        //修改单据出库数据
        final OrderInfo orderInfo = orderInfoRepository.findByProductionTask(shelfInfo.getProductionTask());
        orderInfo.setWaitCheckQty(orderInfo.getWaitCheckQty() - shelfInfo.getQty());
        orderInfo.setUpdatedDt(DateUtil.getCurrentDate());
        orderInfoRepository.save(orderInfo);
    }

    /**
     * 送回待检区回调
     *
     * @param jsonObject
     */
    @Transactional
    public void callBackBackWaitCheck(JSONObject jsonObject) {
        //容器编码
        final String shelfCode = jsonObject.getString("containerCode");
        final ShelfInfo shelfInfo = shelfInfoRepository.findByShelfCode(shelfCode);
        //修改货架信息检验完成
        if (shelfInfo != null) {
            shelfInfo.setOrderStatus(15);
            shelfInfo.setUpdatedDt(DateUtil.getCurrentDate());
            shelfInfoRepository.save(shelfInfo);
        }
        //修改库位状态
        final String locationCode = jsonObject.getString("locationCode");
        final StationInfo stationInfo = stationInfoRepository.findByStationCode(locationCode);
        if (stationInfo != null) {
            stationInfo.setStationStatus(20);
            stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
            stationInfoRepository.save(stationInfo);
        }
        final OrderInfo orderInfo = orderInfoRepository.findByProductionTask(shelfInfo.getProductionTask());
        //修改任务单检验数量
        if (orderInfo != null) {
            orderInfo.setCheckQty(orderInfo.getCheckQty() - shelfInfo.getQty());
            orderInfo.setFinishCheckQty(orderInfo.getFinishCheckQty() + shelfInfo.getQty());
            orderInfo.setUpdatedDt(DateUtil.getCurrentDate());
            orderInfoRepository.save(orderInfo);
        }

    }

    /**
     * 送抽检回调
     *
     * @param jsonObject
     */

    @Transactional
    public void callBackSendPortCheck(JSONObject jsonObject) {
        //容器编码
        final String shelfCode = jsonObject.getString("containerCode");
        final String locationCode = jsonObject.getString("locationCode");
        final ShelfInfo shelfInfo = shelfInfoRepository.findByShelfCode(shelfCode);
        //修改货架信息待抽检
        if (shelfInfo != null) {
            shelfInfo.setOrderStatus(20);
            shelfInfo.setStationCode(locationCode);
            shelfInfo.setUpdatedDt(DateUtil.getCurrentDate());
            shelfInfoRepository.save(shelfInfo);
        }
        //修改库位状态
        final StationInfo stationInfo = stationInfoRepository.findByStationCode(locationCode);
        if (stationInfo != null) {
            stationInfo.setStationStatus(20);
            stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
            stationInfoRepository.save(stationInfo);
            //修改任务单检验数量
            final OrderInfo orderInfo = orderInfoRepository.findByProductionTask(shelfInfo.getProductionTask());
            if (orderInfo != null) {
                orderInfo.setCheckQty(orderInfo.getCheckQty() - shelfInfo.getQty());
                orderInfo.setFinishCheckQty(orderInfo.getFinishCheckQty() + shelfInfo.getQty());
                orderInfo.setUpdatedDt(DateUtil.getCurrentDate());
                orderInfoRepository.save(orderInfo);
            }
        }
    }

    /**
     * 送成品区回调
     *
     * @param jsonObject
     */
    @Transactional
    public void callBackSendProdStore(JSONObject jsonObject) {
        //容器编码
        final String shelfCode = jsonObject.getString("containerCode");
        //终点位置
        final String locationCode = jsonObject.getString("locationCode");
        StationInfo stationInfo = stationInfoRepository.findByStationCode(locationCode);
        if (stationInfo != null) {
            stationInfo.setStationStatus(20);
            stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
            stationInfoRepository.save(stationInfo);
        }
        //修改抽检工位状态为空闲
        final ShelfInfo shelfInfo = shelfInfoRepository.findByShelfCode(shelfCode);
        if (shelfInfo != null) {
            //修改货架状态为待出库
            shelfInfo.setOrderStatus(25);
            shelfInfo.setStationCode(locationCode);
            shelfInfo.setUpdatedDt(DateUtil.getCurrentDate());
            shelfInfoRepository.save(shelfInfo);
        }
        final OrderInfo orderInfo = orderInfoRepository.findByProductionTask(shelfInfo.getProductionTask());
        if (orderInfo != null) {
            //修改成品入库数量
            orderInfo.setProductInQty(orderInfo.getProductInQty() + shelfInfo.getQty());
            orderInfo.setProductOngoingQty(orderInfo.getProductOngoingQty() - shelfInfo.getQty());
            orderInfo.setUpdatedDt(DateUtil.getCurrentDate());
            orderInfoRepository.save(orderInfo);
        }
    }

    /**
     * 成品出库回调
     *
     * @param jsonObject
     */
    @Transactional
    public void callBackOutProdStore(JSONObject jsonObject) {
        //容器编码
        final String shelfCode = jsonObject.getString("containerCode");
        final String locationCode = jsonObject.getString("locationCode");
        final ShelfInfo shelfInfo = shelfInfoRepository.findByShelfCode(shelfCode);
        if (shelfInfo != null) {
            shelfInfo.setProductionTask(null);
            shelfInfo.setStationCode(null);
            shelfInfo.setShelfStatus(50);
            shelfInfo.setUpdatedDt(DateUtil.getCurrentDate());
            shelfInfoRepository.save(shelfInfo);
        }
        final StationInfo stationInfo = stationInfoRepository.findByStationCode(locationCode);
        if (stationInfo != null) {
            stationInfo.setStationStatus(20);
            stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
            stationInfoRepository.save(stationInfo);
        }
        //调用海柔离场接口
        moveOut(shelfCode, locationCode);
    }

    /**
     * 空货架入库
     *
     * @param jsonObject
     */
    @Transactional
    public void callBackSendNullShelf(JSONObject jsonObject) {
        //容器编码
        final String shelfCode = jsonObject.getString("containerCode");
        final String locationCode = jsonObject.getString("locationCode");
        //清空货架信息，空货架入库
        final ShelfInfo shelfInfo = shelfInfoRepository.findByShelfCode(shelfCode);
        if (shelfInfo != null) {
            shelfInfo.setUpdatedDt(null);
            shelfInfo.setOrderStatus(40);
            shelfInfo.setPriority(0);
            shelfInfo.setProductionTask(null);
            shelfInfo.setQty(0);
            shelfInfo.setStationCode(jsonObject.getString("locationCode"));
            shelfInfoRepository.save(shelfInfo);
        }
        StationInfo stationInfo = stationInfoRepository.findByStationCode(locationCode);
        if (stationInfo != null) {
            stationInfo.setStationStatus(20);
            stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
            stationInfoRepository.save(stationInfo);
        }
    }

    /**
     * 呼叫空货架
     *
     * @param jsonObject
     */
    @Transactional
    public void callBackCallNullShelf(JSONObject jsonObject) {
        //容器编码
        final String shelfCode = jsonObject.getString("containerCode");
        final ShelfInfo shelfInfo = shelfInfoRepository.findByShelfCode(shelfCode);
        if (shelfInfo != null) {
            shelfInfo.setOrderStatus(40);
            shelfInfo.setUpdatedDt(DateUtil.getCurrentDate());
            shelfInfo.setStationCode(jsonObject.getString("locationCode"));
            shelfInfoRepository.save(shelfInfo);
        }
    }

    /**
     * 成品出库
     */
    public void outProdStore(String code) {
        final SensorStoreBind sensor = sensorStoreBindRepository.findBySensor(code);
        if (sensor == null) {
            return;
        }
        List<AgvTask> agvTasks=new ArrayList<>();
        //判断当前库位是否已存在任务
        //查找任务类型为成品出库，状态为进行中的任务
        agvTasks = agvTaskRepository.findByDictTypeAndStatus(RequestEnum.OUTPRODSTORE.getCode(), AgvTaskEnum.ONGOING.getCode());
        if(agvTasks.size()>0){
            agvTasks.forEach(e->{
                 String toLocationCode = JSONObject.parseObject(e.getJson()).getJSONObject("taskDescribe").getString("toLocationCode");
                 if(sensor.getStationCode().equals(toLocationCode)){
                     return;
                 }
            });
        }
        StationInfo stationInfo = stationInfoRepository.findByStationCode(sensor.getStationCode());
        //查询在成品库的货架
        final List<ShelfInfo> shelfInfos = shelfInfoRepository.findByOrderStatus(25);
        if (shelfInfos.size() == 0) {
            return;
        }
        //根据优先级和入库时间排序
        final List<ShelfInfo> sorted = shelfInfos.stream().sorted(Comparator.comparing(ShelfInfo::getPriority, Comparator.reverseOrder()).thenComparing(ShelfInfo::getUpdatedDt)).collect(Collectors.toList());

        AgvRequestVo agvRequestVo = new AgvRequestVo();
        agvRequestVo.setType(0);
        if (sorted.size() > 0) {
            agvRequestVo.setToLocationCode(sensor.getStationCode());
            agvRequestVo.setFromLocationCode(sorted.get(0).getStationCode());
            agvRequestVo.setContainerCode(sorted.get(0).getShelfCode());
        }
        agvRequestVo.setRequestType(RequestEnum.OUTPRODSTORE.getCode());
        try {
            final String result = taskParamCreate(agvRequestVo);
            if (JSONObject.parseObject(result).getInteger("code") == 0) {
                //修改起点工位为空闲
                StationInfo byStationCode = stationInfoRepository.findByStationCode(agvRequestVo.getFromLocationCode());
                byStationCode.setStationStatus(5);
                byStationCode.setUpdatedDt(DateUtil.getCurrentDate());
                stationInfoRepository.save(byStationCode);
                //修改出库工位状态为作业中
                stationInfo.setStationStatus(10);
                stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
                stationInfoRepository.save(stationInfo);
                //修改货架状态为出库位待出库
                sorted.get(0).setOrderStatus(30);
                shelfInfoRepository.save(sorted.get(0));
                //修改订单出库中数量
                final OrderInfo orderInfo = orderInfoRepository.findByProductionTask(shelfInfos.get(0).getProductionTask());
                orderInfo.setProductOnoutingQty(orderInfo.getProductOnoutingQty() + shelfInfos.get(0).getQty());
                orderInfo.setUpdatedDt(DateUtil.getCurrentDate());
                orderInfoRepository.save(orderInfo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sendNullShelf(String code) {
        AgvRequestVo agvRequestVo = new AgvRequestVo();
        agvRequestVo.setType(0);
        agvRequestVo.setRequestType(RequestEnum.SENDNULLSHELF.getCode());
        final SensorStoreBind sensor = sensorStoreBindRepository.findBySensor(code);
        List<AgvTask> agvTasks=new ArrayList<>();
        //查找任务类型为空货架入库，状态为进行中的任务
        agvTasks = agvTaskRepository.findByDictTypeAndStatus(RequestEnum.SENDNULLSHELF.getCode(), AgvTaskEnum.ONGOING.getCode());
        if(agvTasks.size()>0){
            agvTasks.forEach(e->{
                String toLocationCode = JSONObject.parseObject(e.getJson()).getJSONObject("taskDescribe").getString("fromLocationCode");
                //当任务起点相同时，不再发送命令
                if(sensor.getStationCode().equals(toLocationCode)){
                    return;
                }
            });
        }
        agvRequestVo.setFromLocationCode(sensor.getStationCode());
        //查找空闲终点位置(先找缓存库位待检区，再找成品缓存库位)
        String toLocationCode = null;
        List<StationInfo> stationInfoList = stationInfoRepository.findByStationTypeAndStationStatus(15, 5);
        if (stationInfoList.size() > 0) {
            toLocationCode = stationInfoList.get(0).getStationCode();
        } else {
            List<StationInfo> stationInfoList2 = stationInfoRepository.findByStationTypeAndStationStatus(30, 5);
            toLocationCode = stationInfoList2.get(0).getStationCode();
        }
        agvRequestVo.setToLocationCode(toLocationCode);
        taskParamCreate(agvRequestVo);
    }

    public String sendNullShelf2(String fromLocationCode, String shelfCode) {
        AgvRequestVo agvRequestVo = new AgvRequestVo();
        agvRequestVo.setType(0);
        agvRequestVo.setRequestType(RequestEnum.SENDNULLSHELF.getCode());
        agvRequestVo.setContainerCode(shelfCode);
        agvRequestVo.setFromLocationCode(fromLocationCode);
        //查找空闲终点位置(先找缓存库位待检区，再找成品缓存库位)
        String toLocationCode = null;
        List<StationInfo> stationInfoList = stationInfoRepository.findByStationTypeAndStationStatus(15, 5);
        if (stationInfoList.size() > 0) {
            toLocationCode = stationInfoList.get(0).getStationCode();
        } else {
            List<StationInfo> stationInfoList2 = stationInfoRepository.findByStationTypeAndStationStatus(30, 5);
            toLocationCode = stationInfoList2.get(0).getStationCode();
        }
        agvRequestVo.setToLocationCode(toLocationCode);
        String result = taskParamCreate(agvRequestVo);
        if (JSONObject.parseObject(result).getInteger("code") == 0) {
            StationInfo stationInfo = stationInfoRepository.findByStationCode(toLocationCode);
            stationInfo.setStationStatus(10);
            stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
            stationInfoRepository.save(stationInfo);
        }
        return result;
    }
}
