package com.shkj.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shkj.common.constant.RedisConstant;
import com.shkj.common.core.domain.Result;
import com.shkj.common.enums.HttpStatus;
import com.shkj.common.utils.DateUtils;
import com.shkj.common.utils.SecurityUtils;
import com.shkj.common.utils.StringUtils;
import com.shkj.plc.sdk.device.PLCReadAndWrite;
import com.shkj.plc.sdk.device.PlcOperate;
import com.shkj.system.service.ISysParameterService;
import com.shkj.wms.bo.*;
import com.shkj.wms.constants.ParameterConstants;
import com.shkj.wms.domain.*;
import com.shkj.wms.enums.TaskStatusEnum;
import com.shkj.wms.enums.TaskTypeEnum;
import com.shkj.wms.mapper.*;
import com.shkj.wms.plc.PlcInit;
import com.shkj.wms.service.*;
import com.shkj.wms.third.rcs.RCSUtil;
import com.shkj.wms.third.rcs.dto.RcsCreateTaskDto;
import com.shkj.wms.third.rcs.dto.RcsIdList;
import com.shkj.wms.third.rcs.enums.RCSTaskTypeEnum;
import com.shkj.wms.utils.JsonUtil;
import com.shkj.wms.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author zjx
 */
@Slf4j
@Service
public class BusinPickupServiceImpl extends ServiceImpl<BusinPickupMapper, BusinPickup> implements IBusinPickupService {


    @Autowired
    IBusinPickupDtlService iBusinPickupDtlService;

    @Autowired
    IBasePointService basePointService;

    @Autowired
    IBusinEnptyContainerService iBusinEnptyContainerService;

    @Resource
    BusinDataTaskMapper businDataTaskMapper;

    @Autowired
    IBusinDataTaskService businDataTaskService;

    @Resource
    ISysParameterService sysParameterService;

    @Resource
    BasePointDeviceMapper basePointDeviceMapper;

    @Resource
    private IBusinBillheadService iBusinBillheadService;

    @Resource
    private  ISysStockService iSysStockService;

    @Resource
    private  IBusinDataTaskService iBusinDataTaskService;

    @Resource
    private IBusinDataTaskGoodsService iBusinDataTaskGoodsService;

    @Autowired
    private IBasePunchRecordService iBasePunchRecordService;

    @Resource
    private BaseLocationMapper baseLocationMapper;

    @Resource
    private BaseLocationPlcMapper baseLocationPlcMapper;

    @Resource
    private RCSUtil rcsUtil;

    @Resource
    private IPutInOutStorageService iPutInOutStorageService;
    @Resource
    private SysStockDetailMapper sysStockDetailMapper;
    @Resource
    private SysStockMapper sysStockMapper;
    @Autowired
    private IBaseGoodsDataService iBaseGoodsDataService;

    @Autowired
    private ISysStockDetailService iSysStockDetailService;

    @Resource
    BaseLocationServiceImpl baseLocationService;

    @Resource
    RedisTemplate redisTemplate;

    @Resource
    IBaseBarcodesInService iBaseBarcodesInService;

    @Resource
    IBaseBarcodesOutService iBaseBarcodesOutService ;
    @Autowired
    ISysParameterService isysParameterService;

    @Resource
    PlcInit plcInit;

    @Override
    public List<BusinPickupVo> getBusinPickupList(BusinPickupQueryBo bo) {
        return baseMapper.getBusinPickupList(bo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> saveBusinPickupRecord(BusinPickupAddBo bo) {

        List<BusinPickupDtlAddBo> dtlAddBos = bo.getDtlAddBos();
        BusinPickup businPickup = new BusinPickup();
        businPickup.setPointNo(bo.getPointNo());
        businPickup.setTaskCode(bo.getTaskCode());
        businPickup.setContainerId(bo.getContainerId());
        businPickup.setCreateTime(DateUtils.getNowDate());
        businPickup.setBranchId(2L);
        businPickup.setCreateBy(SecurityUtils.getUsername());
        Long puckupId = this.baseMapper.insertPuckup(businPickup);
        String taskType = bo.getTaskType();

        List<BusinPickupDtl> dtlList = new ArrayList<>();
        for (BusinPickupDtlAddBo dtlAddBo : dtlAddBos) {
            BusinPickupDtl businPickupDtl = BeanUtil.toBean(dtlAddBo, BusinPickupDtl.class);
            businPickupDtl.setPickupId(puckupId);
            businPickupDtl.setPickupTime(DateUtils.getNowDate());
            businPickupDtl.setBranchId(SecurityUtils.getCurrentBranchId());
            dtlList.add(businPickupDtl);
        }

        iBusinPickupDtlService.saveBusinPickupDtl(dtlList);
        BusinDataTask DataTask = businDataTaskService.getOne(new LambdaQueryWrapper<BusinDataTask>()
                .eq(BusinDataTask::getId, bo.getTaskCode())
                .last("limit 1"));
        String agvno=DataTask.getAgvNo();

        DataTask.setTaskStatus("2");
        businDataTaskService.updateById(DataTask);

        //查询任务对应的产品数量
        List<BusinDataTaskGoodsVo> businDataTaskGoodsVos = iBusinDataTaskGoodsService.selectBusinTaskGoodsByTaskCode(DataTask.getId());
        //如果没有全部取完走当前代码块
        if (businDataTaskGoodsVos.size()>dtlAddBos.size()&&!bo.getTaskType().equals("1")){
            //在任务对应的产品信息里删除已经取完货的产品信息
            for (int i=0;i<businDataTaskGoodsVos.size();i++){
                int finalI = i;
                dtlAddBos.stream().forEach(
                        e->{
                            if (e.getQrCode().equals(businDataTaskGoodsVos.get(finalI).getQrCode())){
                                businDataTaskGoodsVos.remove(finalI);
                            }
                        }
                );
            }
            //剩余产品创建任务进入待补货区
            //查询待补货区货位
            Long abnormalArea =Long.valueOf(sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.replenish_area));
            List<BaseLocationVo> baseLocationVos = baseLocationMapper.getLocationByAreaId(abnormalArea);
            if(baseLocationVos.size()<=0){
                //待补货区已满查询缓冲区是否还有货位
                Long bufferArea =Long.valueOf(sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.buffer_area));
                baseLocationVos = baseLocationMapper.getLocationByAreaId(bufferArea);
            }
            if (baseLocationVos.size()<=0){
                return Result.err().msg("缓冲区也没有货位了,报警报警");
            }
            Long stkPlcId=null;
            Long PlcId = null;
            BaseLocationVo locationVo = new BaseLocationVo();
            locationVo=baseLocationVos.get(0);
           /* if ("4".equals(taskType)||"5".equals(taskType)) {
                //如果是出库任务扣减库存
                this.subtractStockDetail(dtlAddBos,DataTask);
            }*/
            //更改货位状态为空闲
          /*  locationVo.setLocationStatus("0");
            BaseLocation baseLocation = BeanUtil.toBean(locationVo,BaseLocation.class);
            baseLocationMapper.updateById(baseLocation);*/
            //创建任务
            BusinDataTask businDataTask = new BusinDataTask();
            businDataTask.setToColumn(locationVo.getLocationColumn());
            businDataTask.setToLayer(locationVo.getLayer());
            businDataTask.setToRow(locationVo.getLocationRow());
            businDataTask.setTaskType("0");
            //巷道号
            String tunnel = locationVo.getTunnel();
            businDataTask.setTunnel(tunnel);
            //获取对应点位
            BasePointDeviceQueryBo pointQueryBo=new BasePointDeviceQueryBo();
            BasePointDeviceVo basePointDeviceVo = new BasePointDeviceVo();
            pointQueryBo.setTunnel(tunnel);
            pointQueryBo.setDirection("0");
            List<BasePointDeviceVo> basePointDeviceVos = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo);
            if (basePointDeviceVos.size() > 0) {
                basePointDeviceVo = basePointDeviceVos.get(0);
            }
            //获取巷道对应的堆垛机信息
            pointQueryBo.setDevType("1");
            BaseDevicePlcVo baseDevicePlcVo = baseLocationPlcMapper.selectBaseDevicePlc(pointQueryBo);
            stkPlcId = baseDevicePlcVo.getPlcId();
            PlcId = Long.valueOf(isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.LK_plc_id));
            String toPointNo = basePointDeviceVo.getPointNo();
            List<String> points = new ArrayList<>();
            //上个任务的终点是当前任务的起点
            String startPoint = DataTask.getTaskPath();
            points.add(startPoint);
            Map<String,String> snPointMap = new HashMap<>(3);
            snPointMap.put("1",startPoint);
            points.add(toPointNo);
            //非机械手输送线方向入库的执行agv任务类型25
            int  agvTaskType = Integer.valueOf(RCSTaskTypeEnum.A_TO_B_GOODS_MOVE.getValue());
            snPointMap.put("2",toPointNo);
            String taskCode = "T_" + DateUtils.dateTimeNow();
            businDataTask.setTaskCode(taskCode);
            businDataTask.setTaskPath(toPointNo);
            businDataTask.setDpsNoOne(PlcId);
            businDataTask.setDpsNoTwo(stkPlcId);
            businDataTask.setPoints(JsonUtil.toJSONString(snPointMap));
            businDataTask.setTaskStatus("0");
            businDataTask.setBatch(DateUtils.getDate());
            businDataTask.setContainerId(DataTask.getContainerId());
            businDataTask.setIsDown(String.valueOf(agvTaskType));
            iBusinDataTaskService.save(businDataTask);
            Long taskId = businDataTask.getId();
            //添加任务对应的产品信息
            for (BusinDataTaskGoodsVo businDataTaskGoodsvo:businDataTaskGoodsVos ) {
                BusinDataTaskGoods dataTaskGoods = iBusinDataTaskGoodsService.getById(businDataTaskGoodsvo.getGoodsId());
                dataTaskGoods.setTaskCode(taskId);
                iBusinDataTaskGoodsService.updateById(dataTaskGoods);
            }


            BusinTaskExeBo exeBo = new BusinTaskExeBo();
            //入库单信息
            exeBo.setTaskCode(taskId);
            exeBo.setBusinDataTaskGoodsVo(businDataTaskGoodsVos);
            exeBo.setContainerId(DataTask.getContainerId());
            exeBo.setBaseLocationVo(locationVo);
            exeBo.setTransNo("1");
            exeBo.setTransQual("1");

            //呼叫agv
            Result<Boolean> booleanResult = callAGV(taskId, agvTaskType, points,null);
            log.info("呼叫AGV是否成功"+booleanResult.getCode());
            log.info("任务号:"+taskId);
            log.info("agv任务类型:"+agvTaskType);
            log.info("点位:"+points);
            if (booleanResult.getCode()==HttpStatus.SUCCESS.getCode()){
                businDataTask.setTaskStatus("1");
                //生成入库单
                Result<String> stringResult = iPutInOutStorageService.exeTaskPutinStorage(exeBo);
                //生成入库单成功
                if (stringResult.getCode() == HttpStatus.SUCCESS.getCode()) {
                    businDataTask.setTransId(stringResult.getData());
                } else {
                    businDataTask.setTaskStatus(TaskStatusEnum.err.getValue());
                    businDataTask.setExceptionMsg("生成入库单失败");
                }
                iBusinDataTaskService.updateById(businDataTask);
            }
        }
        else {
            //AGV搬运到冲孔区后，需要处理治具
            if (TaskTypeEnum.abnormal_delivery.getValue().equals(taskType)
                    || TaskTypeEnum.replenish_out.getValue().equals(taskType)) {
                // this.subtractStockDetail(dtlAddBos,DataTask);
            }else if ("3".equals(taskType)) {
                Result<Boolean> booleanResult = iBusinEnptyContainerService.emptyContainerFlowDir(bo.getPointNo(), bo.getContainerId(), agvno,null);
                if (booleanResult.getCode() == HttpStatus.SUCCESS.getCode()) {
                    //更改冲孔任务表状态为冲孔中
                    BasePunchRecord basePunchRecord = iBasePunchRecordService.getOne(new LambdaQueryWrapper<BasePunchRecord>()
                            .eq(BasePunchRecord::getTaskCode, bo.getTaskCode())
                            .last("limit 1"));
                    basePunchRecord.setIsState("1");
                    iBasePunchRecordService.updateById(basePunchRecord);
                }
            }
            else if ("0".equals(taskType)) {
                //平库取货
                BusinBillHeadBodyQueryBo bodyQueryBo = new BusinBillHeadBodyQueryBo();
                Long taskId = DataTask.getId();
                bodyQueryBo.setTaskId(taskId);
                //获取要入库的物料信息
                List<BusinBillHeadbodyInVo> bodyInOutDatas = iBusinBillheadService.getBillHeadBodyInOutData(bodyQueryBo);
                if (bodyInOutDatas == null) {
                    return Result.err().msg("没有要处理的库存信息");
                }
                Long locationCode = 0L;
                String batch = "";
                Long containerCode = 0L;
                Long storageCode = 0L;
                int isPunching = 0;
                int isRepair = 0;
                List<Map<String, String>> goods = new ArrayList();
                for (BusinBillHeadbodyInVo bodyInOutData : bodyInOutDatas) {
                    locationCode = bodyInOutData.getLocationCode();
                    storageCode = bodyInOutData.getStorageCode();
                    batch = bodyInOutData.getBatch();
                    isRepair += Integer.valueOf(bodyInOutData.getIsRepair());
                    isPunching += Integer.valueOf(bodyInOutData.getIsPunching());
                    containerCode = bodyInOutData.getContainerCode();
                    Map goodsMap = new HashMap();
                    goodsMap.put("goodsNo", bodyInOutData.getGoodsNo());
                    goodsMap.put("qrCode", bodyInOutData.getQrCode());
                    goods.add(goodsMap);
                }
                List<BaseBarcodesIn> barcodesIns = new ArrayList<>();
                //添加库存明细
                for (Map<String, String> map : goods) {
                    SysStockDetail sysStockDetail = new SysStockDetail();
//                sysStockDetail.setStorageId(storageCode);
                    sysStockDetail.setContainerCode(DataTask.getContainerId());
                    sysStockDetail.setQty(BigDecimal.valueOf(goods.size()));
                    sysStockDetail.setBatch(batch);
                    if (StrUtil.isNotBlank(map.get("goodsNo"))) {
                        sysStockDetail.setGoodsNo(map.get("goodsNo"));
                    }
                    if (StrUtil.isNotBlank(map.get("qrCode"))) {
                        sysStockDetail.setQrCode(map.get("qrCode"));
                        // TODO 测试注释  要打开
                        //更改入库条码状态
                        BaseBarcodesIn baseBarcodesIn = iBaseBarcodesInService.getOne(new LambdaQueryWrapper<BaseBarcodesIn>()
                                .eq(BaseBarcodesIn::getQrCode, map.get("qrCode"))
                        );
                        baseBarcodesIn.setInStatus("4");
                        baseBarcodesIn.setInDate(DateUtils.getDate());
                        barcodesIns.add(baseBarcodesIn);
                    }
                    sysStockDetailMapper.insert(sysStockDetail);
                }
                //更新条码状态为已入库,状态为4
                iBaseBarcodesInService.saveOrUpdateBatch(barcodesIns);

                //添加库存管理表
                Long PinKuArea = Long.valueOf(sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.PinKu_area));
                SysStockQueryBo stockQueryBo = new SysStockQueryBo();
                stockQueryBo.setStorageId(storageCode);
                stockQueryBo.setAreaId(PinKuArea);
                List<SysStockVo> sysStockVoList = iSysStockService.queryList(stockQueryBo);
                SysStock sysStock = null;
                for (Map<String, String> map : goods) {
                    if (sysStockVoList.size() > 0) {
                        sysStock = iSysStockService.getById(sysStockVoList.get(0).getId());
                        sysStock.setStorageId(storageCode);
                        sysStock.setGoodsNo(map.get("goodsNo"));
                        BigDecimal oldQty = sysStock.getQty() != null ? sysStock.getQty() : BigDecimal.valueOf(0);
                        sysStock.setQty(oldQty.add(BigDecimal.valueOf(goods.size())));
                        sysStockMapper.updateById(sysStock);
                    } else {
                        sysStock = new SysStock();
                        sysStock.setStorageId(storageCode);
                        sysStock.setAreaId(PinKuArea);
                        sysStock.setGoodsNo(map.get("goodsNo"));
                        sysStock.setQty(BigDecimal.valueOf(goods.size()));
                        sysStockMapper.insert(sysStock);
                    }
                }

                //回填入库状态，已完成入库
                LambdaQueryWrapper<BusinBillhead> lqw = Wrappers.lambdaQuery();
                lqw.eq(StrUtil.isNotBlank(taskId.toString()), BusinBillhead::getTaskCode, taskId);
                BusinBillhead one = iBusinBillheadService.getOne(lqw);
                one.setAuditFlg("1");
                //将任务状态改为已完成
                BusinDataTask businDataTask = iBusinDataTaskService.getById(taskId);
                businDataTask.setTaskStatus(TaskStatusEnum.finished.getValue());
                iBusinDataTaskService.updateById(businDataTask);
                iBusinBillheadService.updateById(one);
                //调用空治具流向
                iBusinEnptyContainerService.emptyContainerFlowDir(businDataTask.getTaskPath(), businDataTask.getContainerId(), businDataTask.getAgvNo(),null);
            }else {
              /*  if ("4".equals(taskType)||"5".equals(taskType)) {
                    //如果是出库任务扣减库存
                  //  this.subtractStockDetail(dtlAddBos,DataTask);
                }*/
                //平库扣减库存
                if ("14".equals(taskType)){
                    FltsubtractStockDetail(dtlAddBos,DataTask);
                }
                //取货完成，空治具还在码头，呼叫AGV
                //获取其他异常区的最终点位
                String point = DataTask.getTaskPath();
                String  agvtype = String.valueOf(RCSTaskTypeEnum.A_TO_B_GOODS_MOVE.getValue());
                //将点位传入判断空治具的流向
                if (!"4".equals(taskType)&&!"5".equals(taskType)) {
                    log.info("调用空治具流向接口传入agv号为空任务号为:"+DataTask.getId());
                    log.info("传入的起点为:"+point);
                    iBusinEnptyContainerService.emptyContainerFlowDir(point, bo.getContainerId(), null, agvtype);
                }else{
                    log.info("调用空治具流向接口传入agv号为"+agvno+"任务号为:"+DataTask.getId());
                    log.info("传入的起点为:"+point);
                    if (ObjectUtils.isNotEmpty(redisTemplate.opsForValue().get("xzz:" + DataTask.getId()))
                            && redisTemplate.opsForValue().get("xzz:" + DataTask.getId()).toString().equals(agvno)){
                        log.info("任务号为:"+DataTask.getId()+"agv号为"+agvno+"小组装已经释放，不允许重复释放");
                        return Result.ok();
                    }
                    if (ObjectUtils.isEmpty(bo.getContainerId())){
                        bo.setContainerId(0L);
                    }
                    iBusinEnptyContainerService.emptyContainerFlowDir(point, bo.getContainerId(), agvno, null);
                    redisTemplate.opsForValue().set("xzz:"+DataTask.getId(),agvno);
                    // 创建任务
                    //TODO 平库释放后直接去下挂逻辑,后续不需要可以删掉
//                    BusinDataTask task = new BusinDataTask();
//                    task.setTaskCode("T_" + DateUtils.dateTimeNow());
//                    task.setTaskPath("KW16");
//                    task.setTaskStatus(TaskStatusEnum.wait_put.getValue());
//                    task.setTaskType(TaskTypeEnum.mechainical.getValue());
//                    task.setIsDown(String.valueOf(RCSTaskTypeEnum.TO_B_AND_PUT1.getValue()));
//                    task.setBatch(DateUtils.dateTimeNow("yyyy-MM-dd"));
//                    task.setContainerId(DataTask.getContainerId()== null ? 0 :DataTask.getContainerId());
//                    task.setPlcId(30L);
//                    task.setAgvNo(agvno);
//
//                    HashMap<Object, Object> map = new HashMap<>();
//                    map.put("1",point);
//                    map.put("2","KW16");
//                    map.put("3","KW17");
//                    task.setPoints(JsonUtil.toJSONString(map));
//                    iBusinDataTaskService.insertBusinTask(task);
//                    Long taskId = task.getId();
//
//                    RcsCreateTaskDto rcsCreateTaskDto = new RcsCreateTaskDto();
//                    rcsCreateTaskDto.setTaskId(taskId.toString());
//                    rcsCreateTaskDto.setTaskType(RCSTaskTypeEnum.TO_B_AND_PUT1.getValue());
//                    rcsCreateTaskDto.setMapId(1);
//                    rcsCreateTaskDto.setRobotId(agvno);
//
//                    RcsIdList startId = new RcsIdList();
//                    RcsIdList endId = new RcsIdList();
//                    RcsIdList endId1 = new RcsIdList();
//                    List<RcsIdList> idList = new ArrayList<>();
//                    startId.setId(point);
//                    idList.add(startId);
//                    endId.setId("KW16");
//                    idList.add(endId);
//                    endId1.setId("KW17");
//                    idList.add(endId1);
//
//                    rcsCreateTaskDto.setTargets(idList);
//                    Result rcsCreateTask = rcsUtil.rcsCreateTask(rcsCreateTaskDto);
//                    if (rcsCreateTask.getCode() == HttpStatus.SUCCESS.getCode()){
//                        task.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
//                        iBusinDataTaskService.updateById(task);
//                        //新增空治具投放记录
//                        BusinDpscontainerRecord dpscontainerRecord = new BusinDpscontainerRecord();
//                        dpscontainerRecord.setBranchId(SecurityUtils.getCurrentBranchId());
//                        dpscontainerRecord.setContainerId(DataTask.getContainerId()==null? 0 : DataTask.getContainerId());
//                        dpscontainerRecord.setIsState("0");
//                        dpscontainerRecord.setTaskCode(taskId);
//                        dpscontainerRecord.setPointNo("KW16");
//                        dpscontainerRecord.setCreateTime(DateUtils.getNowDate());
//                        businDpsContainerRecordMapper.insert(dpscontainerRecord);
//                    }
//                    log.error(rcsCreateTask.getMsg());
//                    log.error(task.toString());
                }
            }
        }
        if ("4".equals(taskType)||"14".equals(taskType)) {
            //根据过点时间，回填出库队列中的状态为已出库
            BusinDataTaskGoodsVo goodsVo = businDataTaskGoodsVos.get(0);
            if (goodsVo != null) {
                Date traverseDate = goodsVo.getTraverseDate();
                BaseBarcodesOut baseBarcodesOut = iBaseBarcodesOutService.getOne(new LambdaQueryWrapper<BaseBarcodesOut>()
                        .eq(BaseBarcodesOut::getTraverseDate, traverseDate)
                );
                baseBarcodesOut.setOutStatus("3");
                baseBarcodesOut.setOutDate(DateUtils.getDate());
                iBaseBarcodesOutService.updateById(baseBarcodesOut);
            }
        }

        return Result.ok();
    }
    //减库存
    public Boolean subtractStockDetail(List<BusinPickupDtlAddBo> businPickupDtlAddBoList,BusinDataTask businDataTask){
        List<String> qrCode = new ArrayList();
        businPickupDtlAddBoList.stream().forEach(
                e->{
                    qrCode.add(String.valueOf(e.getQrCode()));
                }
        );
        log.info("减少库存的保险杠条码："+JsonUtil.toJSONString(qrCode));
        List<SysStockDetail> sysStockDetailList = iSysStockDetailService.selectsystock(qrCode,businDataTask.getLocationId());
//                iSysStockDetailService.list(new LambdaQueryWrapper<SysStockDetail>()
//                .in(SysStockDetail::getQrCode, StringUtils.isEmpty(qrCode.get(0)) ? "" : qrCode.get(0),StringUtils.isEmpty(qrCode.get(1)) ? "" :qrCode.get(1),StringUtils.isEmpty(qrCode.get(2)) ? "" :qrCode.get(2))
//                //测试用货位id
//                .eq(SysStockDetail::getLocationId,businDataTask.getLocationId())
//                .eq(SysStockDetail::getQty,new BigDecimal("1")));
        List<Long> collect = sysStockDetailList.stream().map(e -> e.getLocationId()).distinct().collect(Collectors.toList());

        sysStockDetailList.stream().forEach(
                e->{
                    e.setQty(e.getQty().subtract(new BigDecimal("1")));
                }
        );

        Long locationId=collect.get(0);
        //更新货位状态
        BaseLocation baseLocation = baseLocationService.getById(locationId);
        baseLocation.setLocationStatus("0");
        baseLocationService.saveOrUpdate(baseLocation);
        log.info("出库库存需要扣减的库存明细："+JsonUtil.toJSONString(sysStockDetailList));

        boolean batch =true;
        //iSysStockDetailService.updateBatchById(sysStockDetailList);
        if (sysStockDetailList !=null && sysStockDetailList.size()>0){
            for (SysStockDetail sysStockDetail : sysStockDetailList) {
                SysStockDetail byId = iSysStockDetailService.getById(sysStockDetail.getId());
                if (byId !=null){
                    batch  = iSysStockDetailService.removeById(sysStockDetail.getId());
                }
            }
        }else {
            batch=false;
        }
        return batch;
    }

    @Override
    public Boolean subtractStockDetailByLocation(BusinDataTask businDataTask) {
        log.info("要扣减库存的货位号："+businDataTask.getLocationId());
        List<SysStockDetail> sysStockDetailList = iSysStockDetailService.selectsystock(null,businDataTask.getLocationId());
        //更新货位状态
        BaseLocation baseLocation = baseLocationService.getById(businDataTask.getLocationId());
        baseLocation.setLocationStatus("0");
        baseLocationService.saveOrUpdate(baseLocation);
        log.info("出库库存需要扣减的库存明细："+JsonUtil.toJSONString(sysStockDetailList));

        boolean batch =true;
        if (sysStockDetailList !=null && sysStockDetailList.size()>0){
            for (SysStockDetail sysStockDetail : sysStockDetailList) {
                SysStockDetail byId = iSysStockDetailService.getById(sysStockDetail.getId());
                if (byId !=null){
                    batch  = iSysStockDetailService.removeById(sysStockDetail.getId());
                }
            }
        }else {
            batch=false;
        }
        return batch;
    }



    //平库扣减库存
    public Boolean FltsubtractStockDetail(List<BusinPickupDtlAddBo> businPickupDtlAddBoList,BusinDataTask businDataTask){
        List qrCode = new ArrayList();
        businPickupDtlAddBoList.stream().forEach(
                e->{
                    qrCode.add(e.getQrCode());
                }
        );
        List<SysStockDetail> sysStockDetailList = iSysStockDetailService.selectsystock(qrCode,businDataTask.getLocationId());

        sysStockDetailList.stream().forEach(
                e->{
                    e.setQty(e.getQty().subtract(new BigDecimal("1")));
                }
        );
        boolean batch = iSysStockDetailService.saveOrUpdateBatch(sysStockDetailList);
        return batch;
    }
    @Override
    public Result returnNullTray() {
        //拿到已完成终点为出库异常接驳点
        String tepairGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.putoutexc_point);
        BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
        pointQueryBo.setGroupNo(tepairGroup);
        BasePointDeviceVo pointDevice = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBo);
        String point=null;
        if (pointDevice==null){
            return Result.err().msg("请维护出库异常点位信息");
        }
        point=pointDevice.getPointNo();

        List<BusinDataTaskVo> businDataTaskVos = businDataTaskMapper.gettaskAbnormal(point);
        BusinDataTaskVo businDataTaskVo = new BusinDataTaskVo();
        if (businDataTaskVos.size() <= 0) {
            return Result.err().msg("当前点位没有车辆");
        }
        businDataTaskVo=businDataTaskVos.get(0);
        //调用空治具流向接口
        iBusinEnptyContainerService.emptyContainerFlowDir(businDataTaskVo.getTaskPath(), businDataTaskVo.getContainerId(), businDataTaskVo.getAgvNo(),null);
        return Result.ok();
    }

    @Override
    public Result AGVNullReach(List<String> taskids) {

        List<String> count=businDataTaskMapper.AGVNullReach(taskids);


        return Result.ok().data(count);
    }
    @Override
    public Result AGVNullReach(String taskids) {

        String tepairGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.putoutexc_point);
        BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
        pointQueryBo.setGroupNo(tepairGroup);
        BasePointDeviceVo pointDevice = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBo);
        String point=null;
        if (pointDevice==null){
            return Result.err().msg("请维护出库异常点位信息");
        }
        point=pointDevice.getPointNo();
        BusinDataTask businDataTask = businDataTaskService.getById(taskids);
        String id = businDataTask.getAssociatedTasksId();
        List<String> count=businDataTaskMapper.AGVNullReach(point);


        return Result.ok().data(count);
    }

    @Override
    public Result QueryPOutDerive() {
        List<BusinDataTask> businDataTaskList = businDataTaskService.list(new LambdaQueryWrapper<BusinDataTask>()
                .eq(BusinDataTask::getTaskStatus,TaskStatusEnum.four_out.getValue())
                .eq(BusinDataTask::getTaskType,TaskTypeEnum.thirteen_out.getValue()));
        List<Long> taskList= new ArrayList<>();
        if (businDataTaskList.size()>0) {
            businDataTaskList.stream().forEach(e -> {
                taskList.add(e.getId());
            });
            List<BaseDeriveTraverseVo> baseDeriveTraverseVoList = new ArrayList<>();
            for (Long taskid : taskList) {
                BigDecimal Qnumber = new BigDecimal("0");
                BigDecimal Hnumber = new BigDecimal("0");
                BaseDeriveTraverseVo baseDeriveTraverseVo = new BaseDeriveTraverseVo();
                List<BusinDataTaskGoods> businDataTaskGoodsList = iBusinDataTaskGoodsService.list(new LambdaQueryWrapper<BusinDataTaskGoods>()
                        .eq(BusinDataTaskGoods::getTaskCode, String.valueOf(taskid)));
                for (BusinDataTaskGoods businDataTaskGoods : businDataTaskGoodsList
                ) {
                    //根据goodsNo查找对应的产品信息
                    BaseGoodsData baseGoodsData = iBaseGoodsDataService.getOne(new LambdaQueryWrapper<BaseGoodsData>()
                            .eq(BaseGoodsData::getGoodsNo, businDataTaskGoods.getGoodsNo()));
                    //根据过点时间查询出库表里的派生和颜色
                    BaseBarcodesOut baseBarcodesOut = iBaseBarcodesOutService.getOne(new LambdaQueryWrapper<BaseBarcodesOut>()
                            .eq(BaseBarcodesOut::getTraverseDate, businDataTaskGoods.getTraverseDate()));

                    List<SysStockDetail> sysStock = iSysStockDetailService.list(new LambdaQueryWrapper<SysStockDetail>()
                            .eq(SysStockDetail::getGoodsNo, businDataTaskGoods.getGoodsNo())
                            .isNull(SysStockDetail::getOutQty)
                            .isNull(SysStockDetail::getLocationId));
                    for (SysStockDetail sysStockDetail:sysStock) {
                        if (baseGoodsData.getLocation().equals("0")) {
                            Qnumber = Qnumber.add(sysStockDetail.getQty());
                        }
                        if (baseGoodsData.getLocation().equals("1")) {
                            Hnumber = Hnumber.add(sysStockDetail.getQty());
                        }
                        baseDeriveTraverseVo.setDerive(baseBarcodesOut.getDerive());
                        baseDeriveTraverseVo.setColor(baseBarcodesOut.getColor());
                        baseDeriveTraverseVo.setVehicheModel(baseGoodsData.getVehicheModel());
                    }
                }
                baseDeriveTraverseVo.setQnumber(Qnumber);
                baseDeriveTraverseVo.setHnumber(Hnumber);
                baseDeriveTraverseVo.setNumber((Hnumber.subtract(Qnumber)).abs());
                baseDeriveTraverseVo.setTaskId(String.valueOf(taskid));
                if (businDataTaskGoodsList.size() >= 3) {
                    baseDeriveTraverseVo.setOverall(true);
                }
                List<Date> collect = businDataTaskGoodsList.stream().map(BusinDataTaskGoods::getTraverseDate).collect(Collectors.toList());
                List<Date> dateList = collect.stream().sorted().collect(Collectors.toList());
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                baseDeriveTraverseVo.setMinDate(simpleDateFormat.format(dateList.get(0)));
                baseDeriveTraverseVo.setMaxDate(simpleDateFormat.format(dateList.get(dateList.size() - 1)));
                baseDeriveTraverseVoList.add(baseDeriveTraverseVo);
            }

            return Result.ok().data(baseDeriveTraverseVoList);
        }
        return  Result.ok();
    }

    @Override
    public Result<Boolean> savePickupRecordByAssemblyLine(String buttonType) {
        BusinPickupAddBo businPickupAddBo = new BusinPickupAddBo();
        AssemblyLineAddBo assemblyLineAddBo;

       /* Map taskidMap = new HashMap(1);
        Map TaskwriteMap = new HashMap(1);

        BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
        pointQueryBo.setDevType("3");
        BaseDevicePlcVo baseDevicePlcVo = baseLocationPlcMapper.selectBaseDevicePlc(pointQueryBo);

        PlcOperate plcOperate =plcInit.getPlcOperateByIp(baseDevicePlcVo.getPlcIp());
        Long plcId = baseDevicePlcVo.getPlcId();
        List<WcsPlcProperty> propertyList = iWcsPlcPropertyService.getWcsPlcPropertyByPlcId(plcId);
        String frontAddress = "";
        String frontType = "";
        String rearAddress = "";
        String rearType = "";

       // 根据plc练级欸属性表查询出对应的前杠放行写入点位和类型
        for (WcsPlcProperty wcsPlcProperty : propertyList) {
            if (buttonType.equals("front") && "23".equals(wcsPlcProperty.getPointType())) {
                frontAddress = wcsPlcProperty.getAddress();
                frontType = wcsPlcProperty.getValueType();
            }
            if (buttonType.equals("after") && "25".equals(wcsPlcProperty.getPointType())) {
                rearAddress = wcsPlcProperty.getAddress();
                rearType = wcsPlcProperty.getValueType();
            }
        }*/


        //按钮类型（共2个）,根据按钮类型获取对应的出库信息
        //前保险杠按钮
        if (buttonType.equals("front")) {
            assemblyLineAddBo = (AssemblyLineAddBo) redisTemplate.opsForValue().get(RedisConstant.redisAssemblyLineFront);
        } else {
            //后保险杠按钮
            assemblyLineAddBo = (AssemblyLineAddBo) redisTemplate.opsForValue().get(RedisConstant.redisAssemblyLineAfter);
        }
//        if (ObjectUtils.isEmpty(assemblyLineAddBo)) {
//            if (buttonType.equals("front")) {
//                TaskwriteMap.put(frontType, "False");
//                taskidMap.put(frontAddress, TaskwriteMap);
//            } else {
//                TaskwriteMap.put(rearType, "False");
//                taskidMap.put(rearAddress, TaskwriteMap);
//            }
//            Boolean aBoolean = plcReadAndWrite.execWrite(plcOperate, JSON.toJSONString(taskidMap));
//            return null;
//        }
        businPickupAddBo.setContainerId(assemblyLineAddBo.getContainerId());
        businPickupAddBo.setPointNo(assemblyLineAddBo.getPointNo());
        businPickupAddBo.setTaskCode(assemblyLineAddBo.getTaskId().toString());
        //根据任务ID获取保险杠明细
        List<BusinPickupDtlAddBo> pickupDtlAddBos = new ArrayList<>();
        List<BusinDataTaskGoodsVo> goodsVos = businDataTaskMapper.selectOutBoundTaskGoods(assemblyLineAddBo.getTaskId());
        for (BusinDataTaskGoodsVo goodsVo : goodsVos) {
            BusinPickupDtlAddBo businPickupDtlAddBo = new BusinPickupDtlAddBo();
            businPickupDtlAddBo.setQrCode(goodsVo.getQrCode());
            pickupDtlAddBos.add(businPickupDtlAddBo);
        }
        businPickupAddBo.setTaskType(assemblyLineAddBo.getTaskType());
        businPickupAddBo.setDtlAddBos(pickupDtlAddBos);

        //取货流程
        //Result<Boolean> pickupRecordesult = this.saveBusinPickupRecord(businPickupAddBo);
        BusinDataTask DataTask = businDataTaskService.getOne(new LambdaQueryWrapper<BusinDataTask>()
                .eq(BusinDataTask::getId, businPickupAddBo.getTaskCode())
                .last("limit 1"));
        String agvno=DataTask.getAgvNo();
        String point = DataTask.getTaskPath();
        log.info("调用空治具流向接口传入agv号为"+agvno+"任务号为:"+DataTask.getId());
        log.info("传入的起点为:"+point);
        if (ObjectUtils.isNotEmpty(redisTemplate.opsForValue().get("xzz:" + DataTask.getId()))
                && redisTemplate.opsForValue().get("xzz:" + DataTask.getId()).toString().equals(agvno)){
            log.info("任务号为:"+DataTask.getId()+"agv号为"+agvno+"小组装已经释放，不允许重复释放");
            return Result.ok();
        }
        if (ObjectUtils.isEmpty(businPickupAddBo.getContainerId())){
            businPickupAddBo.setContainerId(0L);
        }
        iBusinEnptyContainerService.emptyContainerFlowDir(point, businPickupAddBo.getContainerId(), agvno, null);
        redisTemplate.opsForValue().set("xzz:"+DataTask.getId(),agvno);
        DataTask.setTaskStatus("2");
        businDataTaskService.updateById(DataTask);
        String assemblePointType = RedisConstant.assemblePointAfterTaskCount;
        if (buttonType.equals("front")) {
            assemblePointType = RedisConstant.assemblePointBeforeTaskCount;
        }
        if (ObjectUtils.isNotEmpty(redisTemplate.opsForValue().get(assemblePointType))) {
            int temp = Integer.parseInt(redisTemplate.opsForValue().get(assemblePointType).toString());
            if (temp > 0) {
                redisTemplate.opsForValue().set(assemblePointType,  --temp);
            }
        }
        if ("4".equals(DataTask.getTaskType())||"14".equals(DataTask.getTaskType())) {
            //查询任务对应的产品数量
            List<BusinDataTaskGoodsVo> businDataTaskGoodsVos = iBusinDataTaskGoodsService.selectBusinTaskGoodsByTaskCode(DataTask.getId());
            //根据过点时间，回填出库队列中的状态为已出库
            BusinDataTaskGoodsVo goodsVo = businDataTaskGoodsVos.get(0);
            if (goodsVo != null) {
                Date traverseDate = goodsVo.getTraverseDate();
                BaseBarcodesOut baseBarcodesOut = iBaseBarcodesOutService.getOne(new LambdaQueryWrapper<BaseBarcodesOut>()
                        .eq(BaseBarcodesOut::getTraverseDate, traverseDate)
                );
                baseBarcodesOut.setOutStatus("3");
                baseBarcodesOut.setOutDate(DateUtils.getDate());
                iBaseBarcodesOutService.updateById(baseBarcodesOut);
            }
        }
//        if (Result.isOk(pickupRecordesult)){
//            //取货成功
//            //减去任务数
//            // 判断是前杠还是后杠，进行处理 redis 中的任务数
//            //小组装等待点位为一个
//            //String assemblePointType = RedisConstant.assemblePointBeforeTaskCount;
//
//            String assemblePointType = RedisConstant.assemblePointAfterTaskCount;
//            if (buttonType.equals("front")) {
//                assemblePointType = RedisConstant.assemblePointBeforeTaskCount;
//            }
//            if (ObjectUtils.isNotEmpty(redisTemplate.opsForValue().get(assemblePointType))) {
//                int temp = Integer.parseInt(redisTemplate.opsForValue().get(assemblePointType).toString());
//                if (temp > 0) {
//                    redisTemplate.opsForValue().set(assemblePointType,  --temp);
//                }
//            }
//
////            if (buttonType.equals("front")) {
////                redisTemplate.delete(RedisConstant.redisAssemblyLineFront);
////                TaskwriteMap.put(frontType, "False");
////                taskidMap.put(frontAddress, TaskwriteMap);
////            } else {
////                redisTemplate.delete(RedisConstant.redisAssemblyLineAfter);
////                TaskwriteMap.put(rearType, "False");
////                taskidMap.put(rearAddress, TaskwriteMap);
////            }
////
////            Boolean aBoolean = plcReadAndWrite.execWrite(plcOperate, JSON.toJSONString(taskidMap));
////            log.error("出库放行点写入是否成功:" + aBoolean + "写入的相关数据为:" + taskidMap.toString());
//        }
        return  Result.err().msg("出库取货失败");
    }



    public Result<Boolean> callAGV(Long taskId,int taskType,  List<String> points,String agvno){
        AGVMoveBo moveBo = new AGVMoveBo();
        moveBo.setTaskId(taskId);
        moveBo.setTaskType(taskType);
        moveBo.setPoints(points);
        moveBo.setRobotId(agvno);
        Result<Boolean> booleanResult = rcsUtil.moveByAGV(moveBo);
        return booleanResult;
    }


}
