package com.prolog.cs.biz.outbound.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.codingapi.tx.annotation.TxTransaction;
import com.prolog.common.RestMsgHelper;
import com.prolog.cs.basic.item.model.vo.ItemMstVO2;
import com.prolog.cs.basic.item.model.vo.WaveItemInfoVO;
import com.prolog.cs.basic.warehouse.model.vo.WarehouseLocatorBasicInfo;
import com.prolog.cs.biz.outbound.dao.*;
import com.prolog.cs.biz.outbound.model.PickTaskD;
import com.prolog.cs.biz.outbound.model.PickTaskH;
import com.prolog.cs.biz.outbound.model.WmsMoveTaskRef;
import com.prolog.cs.biz.outbound.model.dto.*;
import com.prolog.cs.biz.outbound.model.entity.MoveTaskDO;
import com.prolog.cs.biz.outbound.model.entity.WaveBillDDO;
import com.prolog.cs.biz.outbound.model.entity.WaveBillDO;
import com.prolog.cs.biz.outbound.model.entity.WaveStorageDO;
import com.prolog.cs.biz.outbound.resource.ItemClient;
import com.prolog.cs.biz.outbound.resource.WarehouseResource;
import com.prolog.cs.biz.outbound.service.MoveTaskService;
import com.prolog.cs.biz.outbound.utils.ItemUtils;
import com.prolog.framework.authority.core.dto.UserDTO;
import com.prolog.framework.authority.user.UserTemplate;
import com.prolog.framework.bz.common.print.PrintData;
import com.prolog.framework.bz.common.print.ReportData;
import com.prolog.framework.bz.core.model.ModelUtils;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.FieldSelector;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.utils.MapUtils;
import com.prolog.framework.utils.ObjectUtils;
import com.prolog.framework.utils.SnowFlakeUtils;
import com.prolog.upcloud.base.inventory.vo.*;
import org.apache.commons.collections4.map.HashedMap;
import org.apache.commons.compress.utils.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MoveTaskServiceImpl implements MoveTaskService {

    @Autowired
    private MoveTaskMapper moveTaskMapper;

    @Autowired
    private WaveBillMapper billMapper;

    @Autowired
    private WaveBillDMapper billDMapper;

    @Autowired
    private WaveStorageMapper storageMapper;

    @Autowired
    private PickTaskDMapper pickTaskDMapper;

    @Autowired
    private PickTaskHMapper pickTaskHMapper;

    @Autowired
    private PickTaskServiceImpl pickTaskService;

    @Autowired
    UserTemplate userTemplate;

    @Autowired
    private WmsMoveTaskRefMapper wmsMoveTaskRefMapper;

    // 添加仓库的feign接口 - by Huanglh 2022-01-19
    @Autowired
    private WarehouseResource warehouseResource;

    @Autowired
    private ItemClient itemClient;

    @Value("${prolog.dao.keyGenerator.snowFlake.dataCenterId:5}")
    private long dataCenterId;

    @Value("${prolog.dao.keyGenerator.snowFlake.machineId:13}")
    private long machineId;

    private static Logger log = LoggerFactory.getLogger(MoveTaskServiceImpl.class);

    @Override
    public RestMessage<Boolean> updateStatus(List<MoveTaskUpdateDTO> moveTaskUpdateDTOS) {
        for (MoveTaskUpdateDTO moveTaskDto : moveTaskUpdateDTOS) {
            String moveTaskId = moveTaskDto.getMoveTaskId();
            String status = moveTaskDto.getStatus();
            moveTaskMapper.updateMapById(moveTaskId, MapUtils.put("status", status).getMap(), MoveTaskDO.class);
        }

        return RestMessage.doSuccess(Boolean.TRUE);
    }

    @Override
    @TxTransaction
    @Transactional
    public Boolean addMoveTask(List<MoveTaskDODTO> moveTaskDODTOS) {
        return addMoveTaskNoTx(moveTaskDODTOS,null);
    }

    public Boolean addMoveTaskNoTx(List<MoveTaskDODTO> moveTaskDODTOS,List<WmsMoveTaskRef> wmsMoveTaskRefList) {
        log.info("addMoveTask,moveTaskDODTOS:{},wmsMoveTaskRefList:{}", JSON.toJSONString(moveTaskDODTOS), JSON.toJSONString(wmsMoveTaskRefList));
        if (CollUtil.isEmpty(moveTaskDODTOS) && CollUtil.isEmpty(wmsMoveTaskRefList)) {
            return true;
        }

        UserDTO userDTO = userTemplate.getUserDTO();
        // 根据货位id获取货位所在库房是否是功能库房 - by Huanglh 2022-01-20
        // key-货位id，value-是否是功能库房(0 不是,1 是)
        Map<String, String> isFunctionRoomMap = new HashedMap<>();
        List<String> locatorIds = moveTaskDODTOS.stream().map(MoveTaskDODTO::getSrcWarehouseLocatorId).collect(Collectors.toList());
        RestMessage<Map<String, String>> restMsg = warehouseResource.getIsFunctionRoomByLocatorId(locatorIds);
        if (ObjectUtils.isNull(restMsg) || !restMsg.isSuccess()) {
            log.error("调用接口获取货位所在库房是否是功能库房失败");
        } else {
            isFunctionRoomMap = restMsg.getData();
        }
        // 创建订单信息
        Date now = new Date();
        RestMessage<List<WarehouseLocatorBasicInfo>> locationBasicInfos = null;
        if(CollectionUtil.isNotEmpty(moveTaskDODTOS)){
            locationBasicInfos = warehouseResource.getLocationBasicInfos(locatorIds.toArray(new String[]{}));
            if (locationBasicInfos == null || !locationBasicInfos.isSuccess() || CollUtil.isEmpty(locationBasicInfos.getData())){
                throw new BizException("生成补货任务失败，原因=获取货位信息失败！");
            }
        }
        List<WmsMoveTaskRef> moveTaskRefs = Lists.newArrayList();
        for (MoveTaskDODTO moveTaskDODTO : moveTaskDODTOS) {
            String billDId = moveTaskDODTO.getDetailId();
            WaveBillDDO billDDODb = billDMapper.findById(billDId, WaveBillDDO.class);
            if (billDDODb != null) {
                continue;
            }
            String enterpriseId = userDTO==null?moveTaskDODTO.getEnterpriseId():userDTO.getEnterpriseId();
            String warehouseId = moveTaskDODTO.getWarehouseId();
            String billId = moveTaskDODTO.getHeaderId();
            WaveBillDO billDODb = billMapper.findById(billId, WaveBillDO.class);
            if (billDODb == null) {
                WaveBillDO billDO = new WaveBillDO();
                billDO.setConsignorId(moveTaskDODTO.getCargoOwnerId());
                billDO.setId(billId);
                billDO.setIsMerged(0);
                billDO.setSrcCode(billId);
                billDO.setCode(billId);
                billDO.setBillGroupId(billId);
                billDO.setWarehouseId(warehouseId);
                billDO.setType("20"); // 补货出库单
                if (userDTO != null) {
                    ModelUtils.setBaseInfo(billDO, ModelUtils.OpType.INSERT, userDTO);
                } else {
                    billDO.setGmtCreate(now);
                }
                billMapper.save(billDO);
            }
            // 创建订单明细信息
            WaveBillDDO billDDO = new WaveBillDDO();
            billDDO.setBillId(billId);
            billDDO.setManufacturerLotNum(moveTaskDODTO.getManufacturerLotNum());
            billDDO.setCaseConversionRate(moveTaskDODTO.getConversionRate());
            billDDO.setIsCaseOrPiece(moveTaskDODTO.getIsCaseOrPiece());
            billDDO.setId(billDId);
            billDDO.setItemId(moveTaskDODTO.getItemId());
            billDDO.setItemCode(moveTaskDODTO.getItemCode());
            billDDO.setVolume(moveTaskDODTO.getVolume());
            ItemMstVO2 itemsInfo1 = ItemUtils.getItemsInfo(moveTaskDODTO.getItemId(),enterpriseId);
            billDDO.setManufacturer(itemsInfo1.getManufacturerName());
            billDDO.setItemSpecs(itemsInfo1.getSpecification());
            billDDO.setIsCaseOrPiece(itemsInfo1.getIsCaseOrPiece());
            billDDO.setItemName(itemsInfo1.getItemName());
            if (userDTO != null) {
                ModelUtils.setBaseInfo(billDDO, ModelUtils.OpType.INSERT, userDTO);
            } else {
                billDDO.setGmtCreate(now);
            }
            billDMapper.save(billDDO);
            // 创建补货表
            MoveTaskDO moveTaskDO = new MoveTaskDO();
            BeanUtils.copyProperties(moveTaskDODTO, moveTaskDO);
            moveTaskDO.setStatus(moveTaskDODTO.getMoveType().equals("5")?"1":"0");
            WaveStorageDO waveStorageDO = new WaveStorageDO();
            if (userDTO != null) {
                ModelUtils.setBaseInfo(moveTaskDO, ModelUtils.OpType.INSERT, userDTO);
            } else {
                moveTaskDO.setGmtCreate(now);
            }
            String moveTaskId = String.valueOf(SnowFlakeUtils.getId(dataCenterId,machineId));
            moveTaskDO.setMoveTaskId(moveTaskId);
            moveTaskDO.setBatchNum(moveTaskDODTO.getBatchNum());
            moveTaskDO.setBillId(billId);
            moveTaskDO.setBillDId(billDId);
            moveTaskDO.setMoveType(moveTaskDODTO.getMoveType());
            moveTaskMapper.save(moveTaskDO);
            // 创建库存预占表
            String bldgName = moveTaskDO.getBldgName();
            waveStorageDO.setId(String.valueOf(SnowFlakeUtils.getId()));
            waveStorageDO.setBldgName(bldgName);
            waveStorageDO.setBldgId(moveTaskDODTO.getBldgId());
            waveStorageDO.setBatchId(moveTaskDODTO.getBatchId());
            waveStorageDO.setBatchNum(moveTaskDODTO.getBatchNum());
            waveStorageDO.setFloorNum(moveTaskDODTO.getSrcFloor());
            waveStorageDO.setProductionDate(moveTaskDODTO.getProductionDate());
            waveStorageDO.setExpiredDate(moveTaskDODTO.getExpiredDate());
            String manufacturerLotNum = moveTaskDODTO.getManufacturerLotNum();
            waveStorageDO.setManufactureLotNum(manufacturerLotNum);
            waveStorageDO.setType(1);
            waveStorageDO.setWarehouseId(warehouseId);
            String srcWarehouseLocatorNum = moveTaskDODTO.getSrcWarehouseLocatorNum();
            waveStorageDO.setLocatorCode(srcWarehouseLocatorNum);
            waveStorageDO.setLocatorId(moveTaskDODTO.getSrcWarehouseLocatorId());
            // 设置是否是功能库房 - by Huanglh 2022-01-20
            if (isFunctionRoomMap.containsKey(moveTaskDODTO.getSrcWarehouseLocatorId())) {
                waveStorageDO.setIsFunctionRoom(isFunctionRoomMap.get(moveTaskDODTO.getSrcWarehouseLocatorId()));
            }
            if (null != moveTaskDODTO.getSrcWarehouseAreaCategory() && moveTaskDODTO.getSrcWarehouseAreaCategory().contains("AGVZ")) {
                waveStorageDO.setContainerCode(moveTaskDODTO.getContainerCode());
            } else {
                waveStorageDO.setContainerCode("N/A");
            }
            waveStorageDO.setLocatorType(moveTaskDODTO.getSrcWarehouseLocatorType());
            waveStorageDO.setAreaCategory(moveTaskDODTO.getSrcWarehouseAreaCategory());
            waveStorageDO.setWarehouseAreaCode(moveTaskDODTO.getSrcWarehouseAreaNum());
            waveStorageDO.setExpiredDateShow(moveTaskDODTO.getBatchExpiredDateShow());
            waveStorageDO.setProductionDateShow(moveTaskDODTO.getBatchProductionDateShow());
            WarehouseLocatorBasicInfo locatorBasicInfo = locationBasicInfos.getData().stream().filter(var -> var.getWarehouseLocatorId().equals(moveTaskDODTO.getSrcWarehouseLocatorId())).findFirst().orElse(null);
            if (locatorBasicInfo == null){
                throw new BizException("生成补货任务失败，原因=获取货位信息失败！");
            }
            String pickModel = locatorBasicInfo.getPickMode();
            if (StrUtil.isEmpty(pickModel)) {
                pickModel = moveTaskMapper.getPickModel(waveStorageDO.getWarehouseAreaCode(), warehouseId);
            }
            waveStorageDO.setPickModel(pickModel);
            // waveStorageDO.setType(2);
            waveStorageDO.setStatus("0");
            BigDecimal qty = moveTaskDODTO.getQty();
            waveStorageDO.setQty(qty);
            BigDecimal volume = moveTaskDODTO.getVolume();
            if (volume != null) {
                waveStorageDO.setVolume(qty.multiply(volume));
            } else {
                log.error("补货商品 volume 是空");
            }
            // 建立关联关系
            waveStorageDO.setBillId(billId);
            waveStorageDO.setBillDId(billDId);
            waveStorageDO.setMoveTaskId(moveTaskId);
            waveStorageDO.setWeight(BigDecimal.ZERO);
            waveStorageDO.setItemId(moveTaskDODTO.getItemId());
            if (userDTO != null) {
                ModelUtils.setBaseInfo(waveStorageDO, ModelUtils.OpType.INSERT, userDTO);
            } else {
                waveStorageDO.setGmtCreate(now);
            }
            storageMapper.save(waveStorageDO);

            String pickTaskId = String.valueOf(SnowFlakeUtils.getId(dataCenterId,machineId));
            String pickTaskDId = String.valueOf(SnowFlakeUtils.getId(dataCenterId,machineId));
            PickTaskD d = new PickTaskD();
            d.setPickTaskDId(pickTaskDId);
            d.setPickTaskId(pickTaskId);
            d.setWaveStorageId(waveStorageDO.getId());
            d.setWarehouseId(warehouseId);
            d.setQty(waveStorageDO.getQty());
            d.setEnterpriseId(enterpriseId);
            d.setPrintCount(0);
            d.setPickTaskType(0);
            d.setFlowStatus("1");
            d.setContainerCode(moveTaskDODTO.getContainerCode());
            d.setDetailId(moveTaskDODTO.getDetailId());
            if (moveTaskDO.getMoveType().equals("5")){
                if (userDTO != null) {
                    d.setPickerName(userDTO.getNickname());
                    d.setPickerNo(userDTO.getUserBizModel().getEmployeeNo());
                    d.setPickerId(userDTO.getId());
                }
                d.setPickQty(d.getQty());
            }

            //增加冗余字段
            WaveBillDO waveBillDO = billMapper.findById(waveStorageDO.getBillId(),WaveBillDO.class);
            WaveBillDDO waveBillDDO = billDMapper.findById(waveStorageDO.getBillDId(), WaveBillDDO.class);
            d.setSrcId(waveBillDO.getSrcId());
            d.setSrcLineId(waveBillDDO.getSrcLineId());
            d.setSrcCode(waveBillDO.getSrcCode());
            d.setBillId(waveStorageDO.getBillId());
            d.setBillDId(waveStorageDO.getBillDId());
            d.setItemId(waveStorageDO.getItemId());
            d.setBatchId(waveStorageDO.getBatchId());
            d.setLocatorId(waveStorageDO.getLocatorId());
            d.setWarehouseAreaCode(waveStorageDO.getWarehouseAreaCode());
            d.setPickModel(waveStorageDO.getPickModel());

            if (userDTO != null) {
                ModelUtils.setBaseInfo(d, ModelUtils.OpType.INSERT, userDTO);
            } else {
                d.setGmtCreate(now);
            }

            PickTaskH h = new PickTaskH();
            h.setPickTaskId(pickTaskId);
            // 需要辨识出是否是功能库房的补货任务 - by Huanglh 2022-01-20
            String isFunctionRoom = isFunctionRoomMap.containsKey(moveTaskDODTO.getSrcWarehouseLocatorId())? isFunctionRoomMap.get(moveTaskDODTO.getSrcWarehouseLocatorId()) : "0";
            if ("1".equals(isFunctionRoom)) {
                h.setPickTaskType(2); // 任务类型（0-整件/1-散件/2-功能库房/3-整单）
            } else {
                h.setPickTaskType(0); // 任务类型（0-整件/1-散件/2-功能库房/3-整单）
            }
            h.setEnterpriseId(enterpriseId);
            h.setWarehouseId(warehouseId);
            h.setStatus(moveTaskDODTO.getMoveType().equals("5")?"10":"0");
            h.setWarehouseAreaCode(waveStorageDO.getWarehouseAreaCode());
            h.setBldgId(waveStorageDO.getBldgId());
            h.setBldgName(waveStorageDO.getBldgName());
            h.setType(waveStorageDO.getType());
            h.setBillGroupId(billId);
            h.setBillId(billId);
            if (userDTO != null) {
                ModelUtils.setBaseInfo(h, ModelUtils.OpType.INSERT, userDTO);
            } else {
                h.setGmtCreate(now);
            }
            try {
                pickTaskHMapper.save(h);
            } catch (Exception e) {
                pickTaskId = pickTaskId+0;
                h.setPickTaskId(pickTaskId);
                d.setPickTaskId(pickTaskId);
                pickTaskHMapper.save(h);
            }
            pickTaskDMapper.save(d);

            if (CollUtil.isNotEmpty(wmsMoveTaskRefList)) {
                WmsMoveTaskRef moveTaskRef = wmsMoveTaskRefList.stream().filter(t -> t.getRefLineBillId().equalsIgnoreCase(moveTaskDO.getDetailId())).findFirst().orElse(null);
                if (moveTaskRef == null) {
                    continue;
                }
                moveTaskRef.setMoveTaskId(moveTaskId);
                moveTaskRefs.add(moveTaskRef);
            }
        }

        if (CollUtil.isNotEmpty(moveTaskRefs)) {
            try {
                wmsMoveTaskRefMapper.saveBatch(moveTaskRefs);
            } catch (Exception e) {
                moveTaskRefs.forEach(x -> {
                    x.setId(x.getId() + 0);
                });
                wmsMoveTaskRefMapper.saveBatch(moveTaskRefs);
            }
        }
        return Boolean.TRUE;
    }

    @Override
    @Transactional
    @TxTransaction
    public RestMessage<Long> instore(MoveTaskStatusSyncDTO syncDTO) {
        log.info("同步出库补货任务状态");
        long result = 0;
        UserDTO user= null;
        if(userTemplate!=null && userTemplate.getUserDTO()!=null){
            user = userTemplate.getUserDTO();
        }
        
        if (!syncDTO.getDetails().isEmpty()) {
            //查询改补货商品对应的agv拣货数据,推送到agv
            if("2".equals(syncDTO.getStatus())){
                List<MoveTaskDO> moveTaskDOList = moveTaskMapper.getList(syncDTO.getDetails());
                if(moveTaskDOList.size()>0){
                    log.info("出库补货任务数据:"+moveTaskDOList.toString());
                    for (MoveTaskDO moveTaskDO : moveTaskDOList) {
                        pickTaskService.sendPickTaskAGV(moveTaskDO.getItemId(),moveTaskDO.getBatchNum(),moveTaskDO.getWarehouseId());
                        List<String> detailIds = new ArrayList<>();
                        detailIds.add(moveTaskDO.getDetailId());
                        //更新补货数据状态为:已上架
                        result = moveTaskMapper.instore(detailIds, syncDTO.getStatus(), user == null ? "定时任务" : user.getId(), user == null ? "定时任务" : user.getUsername());
                    }
                    //对于上架的，判断是否存在关联的出库任务，如果关联的出库任务下所有的补货任务均已完成，则更新状态从-1为0
                    List<PickTaskH> hList = pickTaskHMapper.listHByDetailId(syncDTO.getDetails());
                    if (CollUtil.isNotEmpty(hList)){
                        for (PickTaskH pickTaskH : hList) {
                            //判断是否存在还未上架的补货任务
                            Integer unFinishReplenishTaskCnt = pickTaskHMapper.countReplenishUnFinishTask(pickTaskH.getPickTaskId(), syncDTO.getDetails());
                            if (unFinishReplenishTaskCnt == 0){
                                //不存在还未上架的补货任务则更新状态为0
                                pickTaskHMapper.updateToUnUp(pickTaskH.getPickTaskId());
                            }
                        }
                    }
                }
            }else {
                //更新补货数据状态为:已上架
                result = moveTaskMapper.instore(syncDTO.getDetails(), syncDTO.getStatus(), user == null ? "定时任务" : user.getId(), user == null ? "定时任务" : user.getUsername());
            }
            return RestMessage.doSuccess(result);
        }
        return RestMessage.doSuccess(result);
    }

    @Override
    public PrintData print(MoveTaskPrintQueryDTO moveTaskPrintQueryDTO) {
        UserDTO userDTO = userTemplate.getUserDTO();
        String employeeNo = userDTO.getUserBizModel().getEmployeeNo();
        String username = userDTO.getUsername();
        Set<String> organizations = userDTO.getUserBizModel().getOrganizations();
        String enterpriseName = userDTO.getEnterpriseName();
        PrintData printData = new PrintData();
        List<ReportData> reportDatas = new ArrayList<>();
        printData.setData(reportDatas);
        ReportData reportData = new ReportData();


        Map<String, Object> head = new HashMap<>();
        List<Map<String, Object>> tables = new ArrayList<>();
        reportData.setHead(head);
        reportData.setTable(tables);
        reportDatas.add(reportData);
        MoveTaskPrintHeadVo moveTaskPrintHeadVo = new MoveTaskPrintHeadVo();
        moveTaskPrintHeadVo.setEnterpriseName(enterpriseName);
        moveTaskPrintHeadVo.setDrawer(username);
        moveTaskPrintHeadVo.setWorkerNo(employeeNo);
        moveTaskPrintHeadVo.setSrcBldgCode(moveTaskPrintQueryDTO.getSrcBldgCode());
        moveTaskPrintHeadVo.setDestBldgCode(moveTaskPrintQueryDTO.getDestBldgCode());
        moveTaskPrintHeadVo.setDeptName(moveTaskPrintQueryDTO.getDeptName());
        moveTaskPrintHeadVo.setOpUser(moveTaskPrintQueryDTO.getOutstoreWorkerName());
        moveTaskPrintHeadVo.setBillNo(moveTaskPrintHeadVo.getBillNo());
        head.putAll(BeanMap.create(moveTaskPrintHeadVo));

        List<MoveTaskPrintTableVo> details;

        return null;
    }

    @Transactional
    public void extractedMove(StockWaveResultVO waveResult, List<StockWaveResultDetailVO> successBillsResults) {
        extractedMoveNoTx(waveResult, successBillsResults);
    }

    @Override
    public void changeQty(List<MoveTaskDODTO> moveTaskDODTOS) {
        for (MoveTaskDODTO moveTaskDODTO : moveTaskDODTOS) {
            Criteria criteria = Criteria.forClass(PickTaskD.class);
            Restriction r1 = Restrictions.eq("billDId", moveTaskDODTO.getDetailId());
            criteria.setRestriction(Restrictions.and(r1));
            pickTaskDMapper.updateMapByCriteria(MapUtils.put("qty",moveTaskDODTO.getQty()).getMap(),criteria);

            //更新move_task
            Criteria ct = Criteria.forClass(MoveTaskDO.class);
            Restriction res1 = Restrictions.eq("detailId", moveTaskDODTO.getDetailId());
            ct.setRestriction(Restrictions.and(res1));
            moveTaskMapper.updateMapByCriteria(MapUtils.put("qty",moveTaskDODTO.getQty()).getMap(),ct);
        }
    }

    public void extractedMoveNoTx(StockWaveResultVO waveResult, List<StockWaveResultDetailVO> successBillsResults) {
        List<WmsMoveTaskRef> wmsMoveTaskRefList=new ArrayList<>();
        List<MoveTaskDODTO> moveTaskDODTOList=new ArrayList<>();
        Date gmtCreate = new Date();
        String[] billIds = successBillsResults.stream().filter(sbr -> CollUtil.isNotEmpty(sbr.getItemDetails())).flatMap(sbr -> sbr.getItemDetails().stream()).filter(ids -> CollUtil.isNotEmpty(ids.getRefReplenishes())).flatMap(ids -> ids.getRefReplenishes().stream()).map(StockWaveRefBill::getBillId).distinct().toArray(String[]::new);
        String waveId = waveResult.getWaveId();
        List<WaveBillDO> waveBills = Collections.emptyList();
        if (ArrayUtil.isNotEmpty(billIds)) {
            waveBills = billMapper.findByIds(WaveBillDO.class, billIds, FieldSelector.newInstance().include("waveId","id", "srcCode"));
        }

        List<String> itemIds = successBillsResults.stream().filter(sbr -> CollUtil.isNotEmpty(sbr.getItemDetails())).flatMap(sbr -> sbr.getItemDetails().stream()).map(StockWaveItemDetail::getItemId).distinct().collect(Collectors.toList());
        List<WaveItemInfoVO> items = RestMsgHelper.getData(itemClient.getWaveItemInfo(itemIds));

        for (StockWaveResultDetailVO stockWaveResultDetailVO : successBillsResults) {
            List<StockWaveItemDetail> itemDetails = stockWaveResultDetailVO.getItemDetails();
            if (CollUtil.isEmpty(itemDetails)) {
                continue;
            }

            for (StockWaveItemDetail stockWaveItemDetail : itemDetails) {
                List<StockWaveRefBill> refReplenishes = stockWaveItemDetail.getRefReplenishes();
                if (CollUtil.isEmpty(refReplenishes)) {
                    continue;
                }

                for (StockWaveRefBill refReplenish : refReplenishes) {
                    WmsMoveTaskRef wmsMoveTaskRef = wrapWmsMoveTaskRef(refReplenish, gmtCreate, waveBills, waveId);
                    wmsMoveTaskRefList.add(wmsMoveTaskRef);
                }

                List<StockWaveReplenishTaskVO> replenishTaskList = stockWaveItemDetail.getReplenishTaskList();
                if (CollUtil.isEmpty(replenishTaskList)) {
                    continue;
                }

                for (StockWaveReplenishTaskVO stockWaveReplenishTaskVO : replenishTaskList) {
                    MoveTaskDODTO moveTaskDODTO = wrapMoveTaskDODTO(waveResult, stockWaveReplenishTaskVO, stockWaveResultDetailVO, stockWaveItemDetail, items);
                    moveTaskDODTOList.add(moveTaskDODTO);
                }
            }
        }
        addMoveTaskNoTx(moveTaskDODTOList, wmsMoveTaskRefList);
    }

    private WmsMoveTaskRef wrapWmsMoveTaskRef(StockWaveRefBill refBill, Date gmtCreate, List<WaveBillDO> waveBills, String waveId) {
        WmsMoveTaskRef wmsMoveTaskRef = new WmsMoveTaskRef();
        BeanUtils.copyProperties(refBill, wmsMoveTaskRef);
        String moveTaskId = String.valueOf(SnowFlakeUtils.getId(dataCenterId, machineId));
        wmsMoveTaskRef.setId(moveTaskId);
        wmsMoveTaskRef.setGmtCreate(gmtCreate);
        wmsMoveTaskRef.setMoveBillId(refBill.getRefBillId());//补货单号和明细单号跟库内保持一致
        wmsMoveTaskRef.setWaveId(waveId);

        if (CollUtil.isNotEmpty(waveBills)) {
            waveBills.stream().filter(wb -> wb.getId().equals(refBill.getBillId())).findFirst().ifPresent(wb -> {
                wmsMoveTaskRef.setWaveId(wb.getWaveId());
                wmsMoveTaskRef.setSrcCode(wb.getSrcCode());
            });
        }
        return wmsMoveTaskRef;
    }

    private static MoveTaskDODTO wrapMoveTaskDODTO(StockWaveResultVO waveResult, StockWaveReplenishTaskVO stockWaveReplenishTaskVO, StockWaveResultDetailVO stockWaveResultDetailVO, StockWaveItemDetail stockWaveItemDetail, List<WaveItemInfoVO> items) {
        MoveTaskDODTO moveTaskDODTO = new MoveTaskDODTO();
        BeanUtils.copyProperties(stockWaveReplenishTaskVO, moveTaskDODTO);
        moveTaskDODTO.setBillGroupId(stockWaveResultDetailVO.getBillGroupId());
        moveTaskDODTO.setItemId(stockWaveItemDetail.getItemId());
        moveTaskDODTO.setCargoOwnerId(stockWaveResultDetailVO.getCargoOwnerId());
        moveTaskDODTO.setBldgId(stockWaveReplenishTaskVO.getBuildingId());
        moveTaskDODTO.setItemName(stockWaveItemDetail.getItemName());
        moveTaskDODTO.setMoveType("4");
        moveTaskDODTO.setConversionRate(stockWaveItemDetail.getCaseConversionRate());
        moveTaskDODTO.setEnterpriseId(waveResult.getEnterpriseId());
        moveTaskDODTO.setWarehouseId(waveResult.getWarehouseId());
        moveTaskDODTO.setSrcFloor(stockWaveReplenishTaskVO.getSrcFloorNum());
        moveTaskDODTO.setSrcWarehouseAreaNum(stockWaveReplenishTaskVO.getSrcWarehouseAreaCode());
        moveTaskDODTO.setSrcWarehouseLocatorNum(stockWaveReplenishTaskVO.getSrcWarehouseLocatorCode());
        moveTaskDODTO.setDestFloor(stockWaveReplenishTaskVO.getDestFloorNum());
        moveTaskDODTO.setDestWarehouseAreaId(stockWaveReplenishTaskVO.getDestWarehouseAreaId());
        moveTaskDODTO.setDestWarehouseAreaNum(stockWaveReplenishTaskVO.getDestWarehouseAreaCode());
        moveTaskDODTO.setDestWarehouseLocatorId(stockWaveReplenishTaskVO.getDestWarehouseLocatorId());
        moveTaskDODTO.setDestWarehouseLocatorNum(stockWaveReplenishTaskVO.getDestWarehouseLocatorCode());
        moveTaskDODTO.setExpiredDate(stockWaveReplenishTaskVO.getBatchExpiredDate());
        moveTaskDODTO.setProductionDate(stockWaveReplenishTaskVO.getBatchProductionDate());
        moveTaskDODTO.setQty(stockWaveReplenishTaskVO.getPieceQuantity());
        moveTaskDODTO.setContainerCode(stockWaveReplenishTaskVO.getContainerCode());
        Optional.ofNullable(items).flatMap(its -> its.stream().filter(it -> it.getItemId().equals(stockWaveItemDetail.getItemId())).findFirst()).ifPresent(it -> moveTaskDODTO.setItemCode(it.getItemCode()));
        return moveTaskDODTO;
    }
}
