package com.ruoyi.wms.controller;

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.ExcelExportUtil;
import com.cmeim.common.core.web.controller.GenericController;
import com.cmeim.common.core.web.domain.Respond;
import com.cmeim.common.core.web.page.PageVo;

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.service.AGVService;
import com.ruoyi.wms.service.ScheduleService;
import com.ruoyi.wms.vo.*;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Verasion:1.0
 * @Author:DZY
 * @Date:2023/6/26
 **/
@Api(tags = "数据采集接口")
@RestController
@Slf4j
@RequestMapping(value = "agv")
public class AgvController extends GenericController {

    @Autowired
    private AgvTaskRepository agvTaskRepository;
    @Autowired
    private AGVService agvService;
    @Autowired
    private ContainerInfoRepository containerInfoRepository;
    @Autowired
    private OrderInfoRepository orderInfoRepository;
    @Autowired
    private StationInfoRepository stationInfoRepository;
    @Autowired
    private ShelfInfoRepository shelfInfoRepository;
    @Autowired
    private ScheduleService scheduleService;
    @Autowired
    private ContainerRecoderRepository containerRecoderRepository;

    @ApiOperation(value = "test")
    @PostMapping(value = "test")
    public List<AgvTask> test(PageVo pv, AgvTask agvTask) {
        List<AgvTask> agvTaskList = new ArrayList<>();
        List<ContainerRecoder> containerRecoderList = containerRecoderRepository.findByProductionTask("WORK027548");
        for (ContainerRecoder containerRecoder : containerRecoderList) {
            List<AgvTask> agvTasks = agvTaskRepository.findByJsonLikeAndCreatedDtAfterAndCreatedDtBeforeAndDictTypeAndStatus(containerRecoder.getContainerNumber(), "2023-11-08 00:12:35", "2023-11-08 23:12:35", 3, 3);
            agvTaskList.addAll(agvTasks);
        }
        return agvTaskList;
    }

    @ApiOperation(value = "列表")
    @GetMapping(value = "list")
    public Respond list(PageVo pv, AgvTask agvTask) {
        PageRequest pageRequest = PageRequest.of(pv.getPageNo() - 1, pv.getPageSize(),
                Sort.by(sortOrder(agvTask.getOrders())));
        Page page = agvTaskRepository.findAll(buildSpecification(agvTask), pageRequest);
        List<AgvTask> list = page.getContent();
        pv.setRecordsTotal(page.getTotalElements());
        pv.setData(list);
        return buildSuccess(pv);
    }

    @ApiOperation(value = "导出excel")
    @PostMapping("exportExcel")
    public void export(AgvTask agvTask, HttpServletResponse response) throws Exception {
        List<AgvTask> list = agvTaskRepository.findAll(buildSpecification(agvTask));
        List<AgvTaskExportVo> exportList = new ArrayList<>();
        for (AgvTask task : list) {
            AgvTaskExportVo agvTaskExportVo = BeanUtil.copyProperties(task, AgvTaskExportVo.class);
            exportList.add(agvTaskExportVo);
        }
        // 创建工作簿对象
        SXSSFWorkbook workbook = new SXSSFWorkbook(1000);
        // 创建工作表
        SXSSFSheet sheet = workbook.createSheet("AGV任务列表");

        String[] rowsName = new String[]{"序号", "请求单号", "类型", "json", "任务状态", "处理结果", "创建人", "创建时间"};
        List<Object[]> dataList = new ArrayList<Object[]>();
        Object[] objs = null;
        int i = 1;
        for (AgvTaskExportVo agvTaskExportVo : exportList) {
            if (agvTaskExportVo.getDictType() == 1) {
                agvTaskExportVo.setDictTypeShow("请求空箱");
            } else if (agvTaskExportVo.getDictType() == 2) {
                agvTaskExportVo.setDictTypeShow("入水测");
            } else if (agvTaskExportVo.getDictType() == 3) {
                agvTaskExportVo.setDictTypeShow("出水测");
            } else if (agvTaskExportVo.getDictType() == 4) {
                agvTaskExportVo.setDictTypeShow("送待检");
            } else if (agvTaskExportVo.getDictType() == 5) {
                agvTaskExportVo.setDictTypeShow("送检验");
            } else if (agvTaskExportVo.getDictType() == 6) {
                agvTaskExportVo.setDictTypeShow("回待检");
            } else if (agvTaskExportVo.getDictType() == 7) {
                agvTaskExportVo.setDictTypeShow("送抽检");
            } else if (agvTaskExportVo.getDictType() == 8) {
                agvTaskExportVo.setDictTypeShow("送成品库");
            } else if (agvTaskExportVo.getDictType() == 9) {
                agvTaskExportVo.setDictTypeShow("出成品库");
            } else if (agvTaskExportVo.getDictType() == 10) {
                agvTaskExportVo.setDictTypeShow("空箱入库");
            } else if (agvTaskExportVo.getDictType() == 11) {
                agvTaskExportVo.setDictTypeShow("呼叫空货架");
            }
            if (agvTaskExportVo.getStatus() == 1) {
                agvTaskExportVo.setStatusShow("未发起");
            } else if (agvTaskExportVo.getDictType() == 2) {
                agvTaskExportVo.setStatusShow("进行中");
            } else if (agvTaskExportVo.getDictType() == 3) {
                agvTaskExportVo.setStatusShow("已完成");
            } else if (agvTaskExportVo.getDictType() == 4) {
                agvTaskExportVo.setStatusShow("失败");
            } else if (agvTaskExportVo.getDictType() == 5) {
                agvTaskExportVo.setStatusShow("取消");
            } else if (agvTaskExportVo.getStatus() == 6) {
                agvTaskExportVo.setStatusShow("挂起");
            }

            objs = new Object[rowsName.length];
            objs[0] = i;
            objs[1] = agvTaskExportVo.getRequestCode();
            objs[2] = agvTaskExportVo.getDictTypeShow();
            objs[3] = agvTaskExportVo.getJson();
            objs[4] = agvTaskExportVo.getStatusShow();
            objs[5] = agvTaskExportVo.getMessage();
            objs[6] = agvTaskExportVo.getCreatedBy();
            objs[7] = agvTaskExportVo.getCreatedDt();
            dataList.add(objs);
            i += 1;
        }
        ExcelExportUtil.getExportWorkbook(workbook, sheet, rowsName, dataList);
        ExcelExportUtil.sendHttpResponse(response, "Agv", workbook);
    }

    private Specification buildSpecification(AgvTask agvTask) {
        Specification<AgvTask> specification = new Specification<AgvTask>() {
            @Override
            public Predicate toPredicate(Root<AgvTask> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                List<Predicate> predicates = Lists.newArrayList();
                if (agvTask.getRequestCode() != null) {
                    predicates.add(cb.like(root.get("requestCode").as(String.class), "%" + agvTask.getRequestCode() + "%"));
                }
                if (agvTask.getJson() != null) {
                    predicates.add(cb.like(root.get("json").as(String.class), "%" + agvTask.getJson() + "%"));
                }
                if (agvTask.getMessage() != null) {
                    predicates.add(cb.like(root.get("message").as(String.class), "%" + agvTask.getMessage() + "%"));
                }
                if (agvTask.getDictType() != null) {
                    predicates.add(cb.equal(root.get("dictType").as(Integer.class), agvTask.getDictType()));
                }
                if (agvTask.getStatus() != null) {
                    predicates.add(cb.equal(root.get("status").as(Integer.class), agvTask.getStatus()));
                }
                if (StringUtils.isNotBlank(agvTask.getCreatedDtStart())) {
                    predicates.add(cb.greaterThanOrEqualTo(root.get("createdDt").as(String.class), agvTask.getCreatedDtStart()));
                }
                if (StringUtils.isNotBlank(agvTask.getCreatedDtEnd())) {
                    predicates.add(cb.lessThanOrEqualTo(root.get("createdDt").as(String.class), agvTask.getCreatedDtEnd()));
                }
                if (agvTask.getStatusArr() != null) {
                    CriteriaBuilder.In<Integer> in = cb.in(root.get("status").as(Integer.class));
                    for (Integer status : agvTask.getStatusArr()) {
                        in.value(status);
                    }
                    predicates.add(in);
                }
                if (agvTask.getDictTypeArr() != null) {
                    CriteriaBuilder.In<Integer> in = cb.in(root.get("dictType").as(Integer.class));
                    for (Integer status : agvTask.getDictTypeArr()) {
                        in.value(status);
                    }
                    predicates.add(in);
                }
                return cb.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };

        return specification;
    }

    /**
     * AGV任务回调
     *
     * @param jsonObject 回调参数
     * @return 结果返回
     */
    @ApiOperation(value = "AGV任务回调")
    @PostMapping(value = "TaskStatusCallback")
    public JSONObject TaskStatusCallback(@RequestBody JSONObject jsonObject) {
        //log.info("回调任务all：" + jsonObject);
        JSONObject result = new JSONObject();
        result.put("code", 0);
        result.put("msg", "success");
        result.put("data", "");
        String taskCode = jsonObject.getString("taskCode");
        final AgvTask agvTask = agvTaskRepository.findByRequestCode(taskCode);
        if (agvTask == null) {
            return result;
        }
        String status = jsonObject.getString("status");
        if (StringUtils.isNotBlank(status)) {
            if (status.equals("fail")) {
                agvService.updateAgvTask(taskCode, agvTask.getDictType(), agvTask.getJson(), AgvTaskEnum.FAIL.getCode(), jsonObject.getString("message"));
            } else if (status.equals("success")) {
                //获取回调类型
                String eventType = jsonObject.getString("eventType");
                if (eventType.equals("task")) {
                    log.info("回调任务task：" + jsonObject);
                    //更新任务状态
                    agvService.updateAgvTask(taskCode, agvTask.getDictType(), agvTask.getJson(), AgvTaskEnum.FINISH.getCode(), jsonObject.getString("message"));
                    //成功回调
                    agvService.callBackSuccess(agvTask, jsonObject);
                }
                //取箱完成时，修改工位状态
                else if (eventType.equals("tote_load") && agvTask.getDictType() > 3) {
                    String locationCode = jsonObject.getString("locationCode");
                    log.info("取箱完成任务单号：" + taskCode + "," + locationCode);
                    agvService.updateStationStatus(locationCode);
                }
                //放箱完成回调，滚筒线请求空箱
                else if (eventType.equals("tote_unload") && agvTask.getDictType() == 1) {
                    String param = jsonObject.toJSONString();
                    agvService.noticeToPlc(param);
                }

            } else if (status.equals("cancel")) {
                agvService.updateAgvTask(taskCode, agvTask.getDictType(), agvTask.getJson(), AgvTaskEnum.CANCEL.getCode(), jsonObject.getString("message"));
            } else if (status.equals("suspend")) {
                agvService.updateAgvTask(taskCode, agvTask.getDictType(), agvTask.getJson(), AgvTaskEnum.PENDING.getCode(), jsonObject.getString("message"));
            }
        }
        return result;
    }

    @ApiOperation(value = "空箱入库")
    @PostMapping(value = "EmptyContainerInStore")
    @Transactional
    public Respond EmptyContainerInStore(@RequestBody AgvRequestVo requestVo) {
        //校验周转箱是否存在以及状态
        ContainerInfo containerInfo = containerInfoRepository.findByContainerNumber(requestVo.getContainerCode());
        if (containerInfo == null) {
            throw new ServiceException("周转箱号不存在:" + requestVo.getContainerCode());
        }
        if (containerInfo.getContainerStatus() != 15 && containerInfo.getContainerStatus() != 20 && containerInfo.getContainerStatus() != 25) {
            throw new ServiceException("周转箱号状态不是入库中的状态:" + requestVo.getContainerCode());
        }
        requestVo.setType(1);
        requestVo.setRequestType(RequestEnum.NULLBOXINSTORE.getCode());
        requestVo.setFromLocationCode(requestVo.getFromLocationCode());
        requestVo.setToLocationCode("LA_SHELF_STORAGE");
        requestVo.setContainerCode(requestVo.getContainerCode());
        String result = agvService.taskParamCreate(requestVo);
        if (JSONObject.parseObject(result).getInteger("code") == 0) {
            return buildSuccess("请求成功");
        }
        return buildFailure(JSONObject.parseObject(result).getString("msg"));
    }

    @ApiOperation(value = "空料箱出库")
    @PostMapping(value = "EmptyContainerOutStore")
    public Respond EmptyContainerOutStore(@RequestBody AgvRequestVo agvRequestVo) {
        //判断空箱出库任务是否唯一
        List<AgvTask> agvTaskList = agvTaskRepository.findByDictTypeAndStatus(RequestEnum.NULLBOX.getCode(), 2);
        if (agvTaskList.size() > 5) {
            return buildFailure("还有正在执行的出库任务：" + agvTaskList);
        }
        //设置agv请求类型
        agvRequestVo.setRequestType(RequestEnum.NULLBOX.getCode());
        agvRequestVo.setType(0);
        agvService.EmptyContainerOutStore(agvRequestVo);
        return buildSuccess();
    }

    @ApiOperation(value = "料箱入库")
    @PostMapping(value = "ContainerInStore")
    public Respond ContainerInStore(@RequestBody AgvRequestVo requestVo) {
        //校验周转箱是否存在以及状态
        ContainerInfo containerInfo = containerInfoRepository.findByContainerNumber(requestVo.getContainerCode());
        if (containerInfo == null) {
            throw new ServiceException("周转箱号不存在:" + requestVo.getContainerCode());
        }
        if (containerInfo.getContainerStatus() != 15 && containerInfo.getContainerStatus() != 20 && containerInfo.getContainerStatus() != 25) {
            throw new ServiceException("该料箱状态不符合入库要求！" + requestVo.getContainerCode());
        }
        requestVo.setType(1);
        requestVo.setRequestType(RequestEnum.INSTORE.getCode());
        requestVo.setToStationCode("LA_SHELF_STORAGE");
        String result = agvService.taskParamCreate(requestVo);
        if (JSONObject.parseObject(result).getInteger("code") == 0) {
            //final ContainerInfo containerInfo = containerInfoRepository.findByContainerNumber(requestVo.getContainerCode());
            //containerInfo.setProductionTask(requestVo.productionTask);
            //containerInfo.setOnInstoreTime(DateUtil.getCurrentDate());
            //final OrderInfo orderInfo = orderInfoRepository.findByProductionTask(requestVo.getProductionTask());
            //Integer qty = orderInfo.getPlanQty() - (orderInfo.getInQty() + orderInfo.getOngoingQty() + orderInfo.getOutQty() + orderInfo.getOnoutingCheckQty());
            //if (qty > 6) {
            //    qty = 6;
            //}
            ////入库中数量
            //orderInfo.setOngoingQty(orderInfo.getOngoingQty() + qty);
            //containerInfo.setQty(qty);
            //orderInfoRepository.save(orderInfo);
            //containerInfoRepository.save(containerInfo);
            return buildSuccess("请求成功");
        } else {
            return buildSuccess(JSONObject.parseObject(result).getString("msg"));
        }
    }

    @ApiOperation(value = "送待检缓存区")
    @PostMapping(value = "sendWaitCheck")
    public Respond sendWaitCheck(@RequestBody AgvRequestVo agvRequestVo) {
        //校验
        if (StringUtils.isBlank(agvRequestVo.getContainerCode())) {
            throw new ServiceException("无货架编码，请检查！");
        }
        if (StringUtils.isBlank(agvRequestVo.getProductionTask())) {
            throw new ServiceException("无生产工单号，请检查！");
        }
        if (StringUtils.isBlank(agvRequestVo.getFromLocationCode())) {
            throw new ServiceException("无起始点位置，请检查！");
        }
        if (agvRequestVo.getBoxNumber() == null) {
            throw new ServiceException("无货架数量，请检查！");
        }
        agvRequestVo.setType(0);
        agvRequestVo.setRequestType(RequestEnum.SENDWAITCHECK.getCode());
        String toLocationCode = findToLocationCode(15);
        agvRequestVo.setToLocationCode(toLocationCode);
        final String result = agvService.taskParamCreate(agvRequestVo);
        if (JSONObject.parseObject(result).getInteger("code") == 0) {
            //修改起点位状态为空闲
            StationInfo stationInfo = stationInfoRepository.findByStationCode(agvRequestVo.getFromLocationCode());
            if (stationInfo != null) {
                stationInfo.setStationStatus(5);
                stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
                stationInfoRepository.save(stationInfo);
            }
            //修改终点点位状态为待占用
            StationInfo stationInfo1 = stationInfoRepository.findByStationCode(toLocationCode);
            stationInfo1.setStationStatus(10);
            stationInfo1.setUpdatedDt(DateUtil.getCurrentDate());
            stationInfoRepository.save(stationInfo1);
            //修改货架信息
            ShelfInfo shelfInfo = shelfInfoRepository.findByShelfCode(agvRequestVo.getContainerCode());
            if (shelfInfo != null) {
                shelfInfo.setStationCode(agvRequestVo.getFromLocationCode());
                shelfInfo.setProductionTask(agvRequestVo.getProductionTask());
                shelfInfo.setQty(agvRequestVo.getBoxNumber());
                shelfInfo.setUpdatedDt(DateUtil.getCurrentDate());
                shelfInfo.setPriority(0);
                shelfInfo.setStationCode(agvRequestVo.getFromLocationCode());
                shelfInfoRepository.save(shelfInfo);
            } else {
                ShelfInfo shelfInfo1 = new ShelfInfo();
                shelfInfo1.setShelfCode(agvRequestVo.getContainerCode());
                shelfInfo1.setStationCode(agvRequestVo.getFromLocationCode());
                shelfInfo1.setProductionTask(agvRequestVo.getProductionTask());
                shelfInfo1.setQty(agvRequestVo.getBoxNumber());
                shelfInfo1.setUpdatedDt(DateUtil.getCurrentDate());
                shelfInfo1.setPriority(0);
                shelfInfo1.setStationCode(agvRequestVo.getFromLocationCode());
                shelfInfoRepository.save(shelfInfo1);
            }
            return buildSuccess("请求成功");
        }
        return buildFailure(JSONObject.parseObject(result).getString("msg"));
    }

    @ApiOperation(value = "从缓存库位到检验库位")
    @PostMapping(value = "sendCheck")
    @Transactional
    public Respond sendCheck(@RequestBody AgvRequestVo agvRequestVo) {
        //校验
        if (StringUtils.isNotBlank(agvRequestVo.getLastRequestCode())) {
            AgvTask agvTask = agvTaskRepository.findByRequestCode(agvRequestVo.getLastRequestCode());
            if (agvTask != null) {
                if (agvTask.getStatus() <= 2) {
                    throw new ServiceException("上次任务还在执行中，任务号：" + agvRequestVo.getLastRequestCode());
                }
            }
        }
        if (StringUtils.isBlank(agvRequestVo.getProductionTask())) {
            throw new ServiceException("无生产工单号，请检查！");
        }
        if (StringUtils.isBlank(agvRequestVo.getToLocationCode())) {
            throw new ServiceException("无终点位置，请检查！");
        }
        List<ShelfInfo> shelfInfoList = shelfInfoRepository.findByProductionTaskAndOrderStatus(agvRequestVo.getProductionTask(), 5);
        for (ShelfInfo shelfInfo : shelfInfoList) {
            if (shelfInfo.getShelfStatus() == 55) {
                shelfInfoList.remove(shelfInfo);
            }
        }
        if (shelfInfoList.size() == 0) {
            throw new ServiceException("该订单没有货架在缓存库位！");
        }
        agvRequestVo.setType(0);
        agvRequestVo.setContainerCode(shelfInfoList.get(0).getShelfCode());
        agvRequestVo.setFromLocationCode(shelfInfoList.get(0).getStationCode());
        agvRequestVo.setRequestType(RequestEnum.SENDCHECK.getCode());
        String result = agvService.taskParamCreate(agvRequestVo);
        if (JSONObject.parseObject(result).getInteger("code") == 0) {
            //修改起始点位状态为空闲
            StationInfo stationInfo = stationInfoRepository.findByStationCode(agvRequestVo.getFromLocationCode());
            if (stationInfo != null) {
                stationInfo.setStationStatus(5);
                stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
                stationInfoRepository.save(stationInfo);
            }
            //修改终点工位待占用状态
            StationInfo stationInfo1 = stationInfoRepository.findByStationCode(agvRequestVo.getToLocationCode());
            if (stationInfo1 != null) {
                stationInfo1.setStationStatus(10);
                stationInfo1.setUpdatedDt(DateUtil.getCurrentDate());
                stationInfoRepository.save(stationInfo1);
            }
            //修改货架的工单状态
            ShelfInfo shelfInfo = shelfInfoList.get(0);
            shelfInfo.setOrderStatus(10);
            shelfInfo.setUpdatedDt(DateUtil.getCurrentDate());
            ShelfInfo save = shelfInfoRepository.save(shelfInfo);
            String data = JSONObject.parseObject(result).getString("data");
            SpotCheckVo spotCheckVo = BeanUtil.copyProperties(save, SpotCheckVo.class);
            data = data.replaceAll("\\\"","");
            data = data.replace("{", "").replace("}","");
            spotCheckVo.setRequestCode(data.substring(0, data.indexOf(":")));
            return buildSuccess(spotCheckVo);
        }
        return buildFailure(JSONObject.parseObject(result).getString("msg"));
    }

    Lock lock = new ReentrantLock();

    @ApiOperation(value = "送抽检")
    @PostMapping(value = "sendSpotCheck")
    public Respond sendSpotCheck(@RequestBody AgvRequestVo agvRequestVo) {
        if (StringUtils.isBlank(agvRequestVo.getFromLocationCode())) {
            throw new ServiceException("无起始位置，请检查！");
        }
        agvRequestVo.setType(0);
        agvRequestVo.setRequestType(RequestEnum.SENDSPOTCHECK.getCode());
        String result = null;
        lock.lock();
        try {
            //查起始点位对应的货架编码
            List<ShelfInfo> shelfInfoList = shelfInfoRepository.findByStationCode(agvRequestVo.getFromLocationCode());
            //修改货架对应的送抽检工位编码
            ShelfInfo shelfInfo = shelfInfoList.get(0);
            shelfInfo.setStationCodeSpotCheck(agvRequestVo.getFromLocationCode());
            shelfInfoRepository.save(shelfInfo);
            if (shelfInfoList.size() > 0) {
                agvRequestVo.setContainerCode(shelfInfoList.get(0).getShelfCode());
            } else {
                throw new ServiceException("该位置无货架：" + agvRequestVo.getFromLocationCode());
            }
            final List<StationInfo> stationInfos = stationInfoRepository.findByStationTypeAndStationStatus(25, 5);
            if (stationInfos.size() > 0) {
                agvRequestVo.setToLocationCode(stationInfos.get(0).getStationCode());
            } else {
                List<StationInfo> stationInfos1 = stationInfoRepository.findByStationTypeAndStationStatus(15, 5);
                if (stationInfos1.size() == 0) {
                    throw new ServiceException("抽检工位和成品缓存库位待检区都无空闲位置！");
                }
                agvRequestVo.setToLocationCode(stationInfos1.get(0).getStationCode());
                agvRequestVo.setRequestType(RequestEnum.BACKWAITCHECK.getCode());
            }
            result = agvService.taskParamCreate(agvRequestVo);
            //查找任务单号
            if (JSONObject.parseObject(result).getInteger("code") == 0) {
                if (stationInfos.size() > 0) {
                    //修改起始点位状态为空闲
                    StationInfo stationInfo = stationInfoRepository.findByStationCode(agvRequestVo.getFromLocationCode());
                    stationInfo.setStationStatus(5);
                    stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
                    stationInfoRepository.save(stationInfo);
                    //修改抽检工位待占用状态
                    stationInfos.get(0).setStationStatus(10);
                    stationInfoRepository.save(stationInfos.get(0));
                }
                String data = JSONObject.parseObject(result).getString("data");
                SpotCheckVo spotCheckVo = BeanUtil.copyProperties(shelfInfoList.get(0), SpotCheckVo.class);
                data = data.replaceAll("\\\"","");
                data = data.replace("{", "").replace("}","");
                spotCheckVo.setRequestCode(data.substring(0, data.indexOf(":")));
                return buildSuccess(spotCheckVo);
            }
        } finally {
            lock.unlock();
        }
        return buildFailure(JSONObject.parseObject(result).getString("msg"));
    }

    @ApiOperation(value = "送成品库")
    @PostMapping(value = "sendProdStore")
    public Respond sendProdStore(@RequestBody AgvRequestVo agvRequestVo) {
        //校验
        if (StringUtils.isBlank(agvRequestVo.getContainerCode())) {
            throw new ServiceException("无货架编码，请检查！");
        }
        ShelfInfo byShelfCode = shelfInfoRepository.findByShelfCode(agvRequestVo.getContainerCode());
        if (StringUtils.isBlank(byShelfCode.getProductionTask())) {
            throw new ServiceException("无生产任务单，请从工作台处绑定！");
        }
        agvRequestVo.setFromLocationCode(byShelfCode.getStationCode());
        agvRequestVo.setType(0);
        agvRequestVo.setRequestType(RequestEnum.SENDPRODSTORE.getCode());
        String toLocationCode = findToLocationCode(30);
        agvRequestVo.setToLocationCode(toLocationCode);
        final String result = agvService.taskParamCreate(agvRequestVo);
        if (JSONObject.parseObject(result).getInteger("code") == 0) {
            //修改起始点位状态为空闲
            StationInfo stationInfo = stationInfoRepository.findByStationCode(agvRequestVo.getFromLocationCode());
            stationInfo.setStationStatus(5);
            stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
            stationInfoRepository.save(stationInfo);
            //修改终点点位状态为待占用
            StationInfo stationInfo1 = stationInfoRepository.findByStationCode(toLocationCode);
            stationInfo1.setStationStatus(10);
            stationInfo1.setUpdatedDt(DateUtil.getCurrentDate());
            stationInfoRepository.save(stationInfo1);
            final ShelfInfo shelfInfo = shelfInfoRepository.findByShelfCode(agvRequestVo.getContainerCode());
            final OrderInfo orderInfo = orderInfoRepository.findByProductionTask(shelfInfo.getProductionTask());
            orderInfo.setProductOngoingQty(orderInfo.getProductOngoingQty() + shelfInfo.getQty());
            orderInfo.setUpdatedDt(DateUtil.getCurrentDate());
            orderInfoRepository.save(orderInfo);
            return buildSuccess("请求成功");
        }
        return buildFailure(JSONObject.parseObject(result).getString("msg"));
    }

    @ApiOperation(value = "空货架送回(不用，用tcpUtil的空箱入库方法)")
    @PostMapping(value = "sendNullShelf")
    public Respond sendNullShelf(@RequestBody AgvRequestVo agvRequestVo) {
        agvRequestVo.setType(0);
        agvRequestVo.setRequestType(RequestEnum.SENDNULLSHELF.getCode());
        final String result = agvService.taskParamCreate(agvRequestVo);
        if (JSONObject.parseObject(result).getInteger("code") == 0) {
            return buildSuccess("请求成功");
        }
        return buildFailure(JSONObject.parseObject(result).getString("msg"));
    }

    @ApiOperation(value = "呼叫空货架")
    @PostMapping(value = "callNullShelf")
    public Respond callNullShelf(@RequestBody AgvRequestVo agvRequestVo) {
        //校验
        if (StringUtils.isBlank(agvRequestVo.getToLocationCode())) {
            throw new ServiceException("无终点位置，请检查！");
        }
        agvRequestVo.setType(0);
        agvRequestVo.setRequestType(RequestEnum.CALLNULLSHELF.getCode());
        String result = null;
        lock.lock();
        try {
            //查找状态为空的货架
            final List<ShelfInfo> shelfInfos = shelfInfoRepository.findByShelfStatus(55);
            if (shelfInfos.size() == 0) {
                return buildFailure("暂无空货架");
            }
            agvRequestVo.setContainerCode(shelfInfos.get(0).getShelfCode());
            StationInfo stationInfo = stationInfoRepository.findByStationCode(shelfInfos.get(0).getStationCode());
            if (stationInfo == null) {
                return buildFailure("位置不存在：" + shelfInfos.get(0).getStationCode());
            }
            agvRequestVo.setFromLocationCode(stationInfo.getStationCode());
            result = agvService.taskParamCreate(agvRequestVo);
            if (JSONObject.parseObject(result).getInteger("code") == 0) {
                shelfInfos.get(0).setProductionTask("待绑定");
                shelfInfoRepository.save(shelfInfos.get(0));
                return buildSuccess("请求成功");
            }
        } finally {
            lock.unlock();
        }

        return buildFailure(JSONObject.parseObject(result).getString("msg"));
    }

    @ApiOperation(value = "取消AGV任务")
    @GetMapping(value = "cancelTask")
    public Respond cancelTask(@RequestParam("taskCode") String taskCode) {
        agvService.taskCancel(taskCode);

        return buildSuccess();
    }

    @ApiOperation(value = "机器人是否允许取走/放置周转箱")
    @PostMapping(value = "allowOperation")
    public String allowOperation(@RequestBody String Bash) {
        String result = agvService.allowOperation(Bash);
        return result;
    }

    @ApiOperation(value = "料箱出库（定时任务测试）")
    @PostMapping(value = "waterTest")
    public void waterTest() {
        scheduleService.waterTest();
    }

    @ApiOperation(value = "成品出库（测试）")
    @GetMapping(value = "outProdStore")
    public void outProdStore(String status) {
        agvService.outProdStore(status);
    }

    @ApiOperation(value = "空货架入库（测试）")
    @GetMapping(value = "sendNullShelf")
    public void sendNullShelf(String status) {
        agvService.sendNullShelf(status);
    }

    @ApiOperation(value = "空货架入库（PDA）")
    @GetMapping(value = "nullShelfIn")
    public Respond nullShelfIn(@RequestParam("containerCode") String containerCode, @RequestParam("positionCode") String positionCode) {
        String result = agvService.moveIn(containerCode, positionCode);
        if (JSONObject.parseObject(result).getInteger("code") == 0) {
            ShelfInfo shelfInfo = shelfInfoRepository.findByShelfCode(containerCode);
            if (shelfInfo != null) {
                shelfInfo.setStationCode(positionCode);
                shelfInfo.setUpdatedDt(DateUtil.getCurrentDate());
                shelfInfo.setShelfStatus(55);
                shelfInfoRepository.save(shelfInfo);
            } else {
                ShelfInfo shelfInfo1 = new ShelfInfo();
                shelfInfo.setShelfStatus(55);
                shelfInfo1.setShelfCode(containerCode);
                shelfInfo1.setStationCode(positionCode);
                shelfInfo1.setProductionTask(null);
                shelfInfo1.setQty(0);
                shelfInfo1.setCreatedDt(DateUtil.getCurrentDate());
                shelfInfo1.setUpdatedDt(DateUtil.getCurrentDate());
                shelfInfo1.setPriority(0);
                shelfInfoRepository.save(shelfInfo1);
            }
            StationInfo stationInfo = stationInfoRepository.findByStationCode(positionCode);
            if (stationInfo != null) {
                stationInfo.setStationStatus(20);
                stationInfo.setUpdatedDt(DateUtil.getCurrentDate());
                stationInfoRepository.save(stationInfo);
            }
            String result2 = agvService.sendNullShelf2(positionCode, containerCode);
        } else {
            return buildFailure("海柔报错：" + JSONObject.parseObject(result).getString("msg"));
        }
        return buildSuccess();
    }

    @ApiOperation(value = "容器离场（PDA）")
    @GetMapping(value = "nullShelfOut")
    public Respond nullShelfOut(@RequestParam("containerCode") String containerCode, @RequestParam("positionCode") String positionCode) {
        agvService.moveOut(containerCode, positionCode);
        ShelfInfo shelfInfo = shelfInfoRepository.findByShelfCode(containerCode);
        shelfInfo.setStationCode(null);
        shelfInfo.setUpdatedDt(DateUtil.getCurrentDate());
        shelfInfo.setShelfStatus(0);
        shelfInfoRepository.save(shelfInfo);
        if (StringUtils.isNotBlank(shelfInfo.getStationCode())) {
            StationInfo stationInfo = stationInfoRepository.findByStationCode(shelfInfo.getStationCode());
            stationInfo.setStationStatus(5);
            stationInfoRepository.save(stationInfo);
        }
        if (StringUtils.isNotBlank(positionCode)) {
            StationInfo stationInfo = stationInfoRepository.findByStationCode(positionCode);
            stationInfo.setStationStatus(5);
            stationInfoRepository.save(stationInfo);
        }
        return buildSuccess("离场成功：" + containerCode);
    }

    @ApiOperation(value = "容器移入（PDA）")
    @GetMapping(value = "shelfIn")
    public Respond shelfIn(@RequestParam("containerCode") String containerCode, @RequestParam("positionCode") String positionCode, @RequestParam("productionTask") String productionTask, @RequestParam("qty") Integer qty) {
        StationInfo stationInfo = stationInfoRepository.findByStationCode(positionCode);
        if (stationInfo == null) {
            return buildFailure("位置不存在：" + positionCode);
        }
        if (stationInfo.getStationType() == 15 && StringUtils.isBlank(productionTask)) {
            ShelfInfo shelfInfo = shelfInfoRepository.findByShelfCode(containerCode);
            if (shelfInfo != null) {
                agvService.moveOut(containerCode, shelfInfo.getStationCode());
            }
            //入场
            agvService.moveIn(containerCode, positionCode);
            shelfInfo.setShelfStatus(55);
            shelfInfo.setQty(0);
            shelfInfo.setStationCode(positionCode);
            shelfInfo.setUpdatedDt(DateUtil.getCurrentDate());
            shelfInfoRepository.save(shelfInfo);
            stationInfo.setStationStatus(20);
            stationInfoRepository.save(stationInfo);
            return buildSuccess("移入成功：" + containerCode);
        }
        if (stationInfo.getStationType() != 40 && StringUtils.isBlank(productionTask)) {
            return buildFailure("除空车缓存区外必传工单");
        }
        //容器先离场
        ShelfInfo shelfInfo = shelfInfoRepository.findByShelfCode(containerCode);
        if (shelfInfo != null) {
            agvService.moveOut(containerCode, shelfInfo.getStationCode());
        }
        //入场
        agvService.moveIn(containerCode, positionCode);
        shelfInfo.setQty(qty);
        shelfInfo.setStationCode(positionCode);
        shelfInfo.setProductionTask(productionTask);
        shelfInfo.setUpdatedDt(DateUtil.getCurrentDate());
        shelfInfoRepository.save(shelfInfo);
        stationInfo.setStationStatus(20);
        stationInfoRepository.save(stationInfo);
        return buildSuccess("移入成功：" + containerCode);
    }

    @ApiOperation(value = "找终点位置")
    @PostMapping(value = "findToLocationCode")
    public String findToLocationCode(Integer storeType) {
        String toLocationCode = null;
        List<StationInfo> stationInfoList = stationInfoRepository.findByStationTypeAndStationStatus(storeType, 5);
        if (stationInfoList.size() > 0) {
            toLocationCode = stationInfoList.get(0).getStationCode();
        } else {
            throw new ServiceException("暂无空闲的点位！");
        }
        return toLocationCode;
    }

}
