package com.prolog.upcloud.base.wh.operate.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.codingapi.tx.annotation.TxTransaction;
import com.prolog.cs.basic.item.model.vo.ItemBaseInfoVO;
import com.prolog.cs.biz.inbound.dto.CargoChangeIn;
import com.prolog.cs.biz.inbound.dto.CargoChangeInDetails;
import com.prolog.cs.biz.inbound.dto.rqc.RqcLinesDTO;
import com.prolog.cs.biz.inbound.dto.rqc.WmsInRqcSampleDTO;
import com.prolog.cs.biz.outbound.model.vo.CargoOwnerChangeVO;
import com.prolog.cs.biz.outbound.model.vo.WaveStorageVO;
import com.prolog.framework.authority.core.dto.UserDTO;
import com.prolog.framework.authority.user.UserTemplate;
import com.prolog.framework.bz.core.collection.ValidList;
import com.prolog.framework.bz.core.model.ModelUtils;
import com.prolog.framework.cache.utils.JsonUtil;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.RestrictionBuilder;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.framework.utils.MapUtils;
import com.prolog.upcloud.base.inventory.vo.*;
import com.prolog.upcloud.base.wh.operate.dao.OmsCnsConversionMapper;
import com.prolog.upcloud.base.wh.operate.dao.WmsCargoChangeDetailMapper;
import com.prolog.upcloud.base.wh.operate.dao.WmsCargoChangeMapper;
import com.prolog.upcloud.base.wh.operate.dao.WmsCargoChangeResultMapper;
import com.prolog.upcloud.base.wh.operate.enums.CargoChangeStatus;
import com.prolog.upcloud.base.wh.operate.enums.WmsMoveBillType;
import com.prolog.upcloud.base.wh.operate.model.OmsCnsConversion;
import com.prolog.upcloud.base.wh.operate.model.WmsCargoChange;
import com.prolog.upcloud.base.wh.operate.model.WmsCargoChangeDetail;
import com.prolog.upcloud.base.wh.operate.model.WmsCargoChangeResult;
import com.prolog.upcloud.base.wh.operate.resource.InBoundClient;
import com.prolog.upcloud.base.wh.operate.resource.ItemResource;
import com.prolog.upcloud.base.wh.operate.resource.OutBoundClient;
import com.prolog.upcloud.base.wh.operate.resource.StockResource;
import com.prolog.upcloud.base.wh.operate.service.CargoChangeService;
import com.prolog.upcloud.base.wh.operate.service.MoveService;
import com.prolog.upcloud.base.wh.operate.utils.BeanConvertUtils;
import com.prolog.upcloud.base.wh.operate.utils.StringUtils;
import com.prolog.upcloud.base.wh.operate.vo.*;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author wujunjie
 */
@Log4j2
@Service
public class CargoChangeServiceImpl implements CargoChangeService {
    private final OmsCnsConversionMapper cnsConversionMapper;
    private final WmsCargoChangeMapper cargoChangeMapper;
    private final WmsCargoChangeDetailMapper cargoChangeDetailMapper;
    private final WmsCargoChangeResultMapper changeResultMapper;

    @Autowired
    private MoveService moveService;

    private final InBoundClient inBoundClient;
    private final OutBoundClient outBoundClient;
    private final StockResource stockResource;
    private final ItemResource itemResource;

    private final UserTemplate userTemplate;

    public CargoChangeServiceImpl(OmsCnsConversionMapper cnsConversionMapper, WmsCargoChangeMapper cargoChangeMapper, WmsCargoChangeDetailMapper wmsCargoChangeDetailMapper, WmsCargoChangeResultMapper changeResultMapper, InBoundClient inBoundClient, OutBoundClient outBoundClient, StockResource stockResource, ItemResource itemResource, UserTemplate userTemplate) {
        this.cnsConversionMapper = cnsConversionMapper;
        this.cargoChangeMapper = cargoChangeMapper;
        this.cargoChangeDetailMapper = wmsCargoChangeDetailMapper;
        this.changeResultMapper = changeResultMapper;
        this.inBoundClient = inBoundClient;
        this.outBoundClient = outBoundClient;
        this.stockResource = stockResource;
        this.itemResource = itemResource;
        this.userTemplate = userTemplate;
    }

    @Override
    public Page<OmsCnsConversionListVO> getSourceHeaderList(String warehouseId) {
        return PageUtils.getPage(cnsConversionMapper.getSourceHeaderList(warehouseId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeSourceList(String[] billnos) {
        UserDTO user = userTemplate.getUserDTO();
        for (String billno : billnos) {

            Criteria changeCriteria = Criteria.forClass(WmsCargoChange.class);
            changeCriteria.restrictionBuilder()
                    .eq("refBillNo", billno)
                    .eq("enterpriseId", user.getEnterpriseId());
            changeCriteria.buildRestriction();
            List<WmsCargoChange> cargoChanges = cargoChangeMapper.findByCriteria(changeCriteria);
            if (CollectionUtil.isNotEmpty(cargoChanges)) {
                throw new BizException("禁止重复提取转换单!");
            }

            Criteria criteria = Criteria.forClass(OmsCnsConversion.class);
            criteria.restrictionBuilder().eq("billno", billno);
            criteria.buildRestriction();
            List<OmsCnsConversion> conversions = cnsConversionMapper.findByCriteria(criteria);
            if (CollectionUtil.isEmpty(conversions)) {
                continue;
            }

            String[] itemIds = Stream.concat(conversions.stream().map(OmsCnsConversion::getSourceitemid),
                    conversions.stream().map(OmsCnsConversion::getTargetitemid)).distinct().toArray(String[]::new);
            RestMessage<List<ItemBaseInfoVO>> itemResult = itemResource.getItemBaseList(itemIds);
            if (!itemResult.isSuccess() || CollectionUtil.isEmpty(itemResult.getData())) {
                throw new BizException("获取商品信息失败, 请稍后再试");
            }

            List<ItemBaseInfoVO> itemInfos = itemResult.getData();

            //主表信息
            OmsCnsConversion omsCnsConversion = CollectionUtil.getFirst(conversions);
            WmsCargoChange cargoChange = new WmsCargoChange();
            cargoChange.setRefBillNo(billno);
            cargoChange.setWarehouseId(omsCnsConversion.getBranchid());
            cargoChange.setWarehouseCode(omsCnsConversion.getBranchcode());
            cargoChange.setWarehouseName(omsCnsConversion.getBranchname());
            cargoChange.setPoBillId(omsCnsConversion.getPoBillId());
            cargoChange.setPoBillNo(omsCnsConversion.getPoBillNo());
            cargoChange.setOrderBillId(omsCnsConversion.getOrderBillId());
            cargoChange.setOrderBillNo(omsCnsConversion.getOrderBillNo());
            cargoChange.setSrcCargoOwnerId(omsCnsConversion.getSourceconsignorid());
            cargoChange.setSrcCargoOwnerName(omsCnsConversion.getSourceconsignorname());
            cargoChange.setDestCargoOwnerId(omsCnsConversion.getTargetconsignorid());
            cargoChange.setDestCargoOwnerName(omsCnsConversion.getTargetconsignorname());
            cargoChange.setStatus(CargoChangeStatus.WAITING.getStatus());
            cargoChange.setSourceType("ERP");
            cargoChange.setBillDate(DateUtil.beginOfDay(omsCnsConversion.getBillDate()));
            cargoChange.setRemark(omsCnsConversion.getRemark());
            ModelUtils.setBaseInfo(cargoChange, ModelUtils.OpType.INSERT, user);
            cargoChangeMapper.save(cargoChange);
            //子表信息
            List<WmsCargoChangeDetail> details = new ArrayList<>();
            for (OmsCnsConversion conversion : conversions) {
                ItemBaseInfoVO srcItem = itemInfos.stream().filter(x -> x.getItemId().equals(conversion.getSourceitemid())).findFirst().orElse(null);
                if (srcItem == null) {
                    throw new BizException("商品[" + conversion.getSourceitemname() + "]信息获取失败");
                }
                ItemBaseInfoVO destItem = itemInfos.stream().filter(x -> x.getItemId().equals(conversion.getTargetitemid())).findFirst().orElse(null);
                if (destItem == null) {
                    throw new BizException("商品[" + conversion.getTargetitemname() + "]信息获取失败");
                }
                if (!srcItem.getIsCaseOrPiece().equals(destItem.getIsCaseOrPiece())) {
                    throw new BizException("源商品[" + conversion.getSourceitemname() + "]存储属性不一致,请检查商品信息");
                }
                if (srcItem.getCaseConversionRate().compareTo(destItem.getCaseConversionRate()) != 0) {
                    throw new BizException("源商品[" + conversion.getSourceitemname() + "]件包装不一致,请检查商品信息");
                }
                if (conversion.getQty().divideAndRemainder(srcItem.getCaseConversionRate())[1].compareTo(BigDecimal.ZERO) != 0) {
                    throw new BizException("源商品[" + conversion.getSourceitemname() + "]转换数量与件包装不一致");
                }
                WmsCargoChangeDetail detail = new WmsCargoChangeDetail();
                detail.setHeaderId(cargoChange.getHeaderId());
                detail.setRefBillId(conversion.getBillid());
                detail.setSrcItemId(conversion.getSourceitemid());
                detail.setSrcItemName(conversion.getSourceitemname());
                detail.setDestItemId(conversion.getTargetitemid());
                detail.setDestItemName(conversion.getTargetitemname());
                detail.setManufacturerLotNum(conversion.getLotno());
                detail.setQuantity(conversion.getQty());
                detail.setEnterpriseId(cargoChange.getEnterpriseId());
                details.add(detail);
            }
            cargoChangeDetailMapper.saveBatch(details);
        }
    }

    @Override
    @TxTransaction
    @Transactional(rollbackFor = Exception.class)
    public void change(List<WmsCargoChange> paramsVO) {
        UserDTO user = userTemplate.getUserDTO();
        Criteria criteria = Criteria.forClass(WmsCargoChange.class);
        String[] headerIds = paramsVO.stream().map(t -> t.getHeaderId()).toArray(String[]::new);
        criteria.restrictionBuilder().eq("enterpriseId", user.getEnterpriseId()).in("headerId", headerIds);
        criteria.buildRestriction();
        //执行库存货权变更
        List<WmsCargoChange> cargoChanges = cargoChangeMapper.findByCriteria(criteria);

        //检查是否存在已转换单据
        String errorChangeNoList = cargoChanges.stream().filter(x -> !x.getStatus().equals(CargoChangeStatus.WAITING.getStatus())).map(WmsCargoChange::getRefBillNo).collect(Collectors.joining(","));
        if (StrUtil.isNotBlank(errorChangeNoList)) {
            throw new BizException("转换单[" + errorChangeNoList + "]已执行转换!");
        }

        ValidList<InvStockChange> stockChanges = new ValidList<>();
        for (WmsCargoChange cargoChange : paramsVO) {
            InvStockChange stockChange = new InvStockChange();
            String headerId = cargoChange.getHeaderId();
            stockChange.setHeaderId(headerId);
            stockChange.setRefBillNo(cargoChange.getRefBillNo());
            stockChange.setWarehouseId(cargoChange.getWarehouseId());
            stockChange.setSrcCargoOwnerId(cargoChange.getSrcCargoOwnerId());
            stockChange.setEnterpriseId(cargoChange.getEnterpriseId());
            stockChange.setDestCargoOwnerId(cargoChange.getDestCargoOwnerId());
            stockChange.setPoBillId(cargoChange.getPoBillId());
            stockChange.setPoBillNo(cargoChange.getPoBillNo());
            stockChange.setOrderBillId(cargoChange.getOrderBillId());
            stockChange.setOrderBillNo(cargoChange.getOrderBillNo());
            cargoChangeMapper.updateMapById(headerId, MapUtils.put("rqcResult", cargoChange.getRqcResult()).getMap(), WmsCargoChange.class);
            for (WmsCargoChangeDetail detail : cargoChange.getDetailList()) {
                String srcItemName = detail.getSrcItemName();
                BigDecimal quantity = detail.getQuantity();
                BigDecimal qcOddCaseQty = detail.getQcOddCaseQty();
                BigDecimal qcOddPieceQty = detail.getQcOddPieceQty();
                BigDecimal qcOddCaseActQty = detail.getQcOddCaseActQty();
                BigDecimal qcOddPieceActQty = detail.getQcOddPieceActQty();
                if(qcOddCaseQty!=null && qcOddCaseActQty!=null && qcOddCaseActQty.compareTo(qcOddCaseActQty)<0){
                    throw new BizException("商品[" + srcItemName + "]抽检数量"+qcOddCaseActQty+"不能小于建议抽检数量"+qcOddCaseQty);
                }
                if(qcOddPieceQty!=null && qcOddPieceActQty!=null && qcOddPieceQty.compareTo(qcOddPieceActQty)<0){
                    throw new BizException("商品[" + srcItemName + "]抽检数量"+qcOddPieceActQty+"不能小于建议抽检数量"+qcOddPieceQty);
                }
                if(qcOddCaseActQty!=null && qcOddPieceActQty!=null && qcOddCaseActQty.compareTo(BigDecimal.ZERO)==0 &&
                        qcOddCaseActQty.compareTo(BigDecimal.ZERO)==0){
                    throw new BizException("商品[" + srcItemName + "]抽检数量不能为零");
                }
                BigDecimal qcQty = detail.getQcQty();
                if(quantity !=null && qcQty!=null && quantity.compareTo(qcQty)<0){
                    throw new BizException("商品[" + srcItemName + "]验收数量"+ qcQty +"不能大于建议订单数量"+quantity);
                }

                cargoChangeDetailMapper.updateMapById(detail.getDetailId(),
                        MapUtils.put("qcOddCaseQty", qcOddCaseQty).put("qcOddPieceQty", qcOddPieceQty).
                                put("qcOddCaseActQty", qcOddCaseActQty).put("qcOddPieceActQty", qcOddPieceActQty)
                                .put("qcQty", qcQty).getMap(), WmsCargoChangeDetail.class);
            }
            List<InvStockChangeDetail> stockChangeDetails = new ArrayList<>();
            List<WmsCargoChangeDetail> details = cargoChangeDetailMapper.findByMap(MapUtils.put("headerId", headerId).getMap(),
                    WmsCargoChangeDetail.class);

            String[] itemIds = details.stream().map(WmsCargoChangeDetail::getSrcItemId).distinct().toArray(String[]::new);
            RestMessage<List<ItemBaseInfoVO>> itemResult = itemResource.getItemBaseList(itemIds);
            if (!itemResult.isSuccess() || CollectionUtil.isEmpty(itemResult.getData())) {
                throw new BizException("获取商品信息失败, 请稍后再试");
            }

            List<ItemBaseInfoVO> itemInfos = itemResult.getData();
            for (WmsCargoChangeDetail detail : details) {
                String srcItemName = detail.getSrcItemName();
                if (StringUtils.isBlank(detail.getManufacturerLotNum())) {
                    throw new BizException("商品[" + srcItemName + "]批号不能为空, 请检查!");
                }
                ItemBaseInfoVO srcItem = itemInfos.stream().filter(x -> x.getItemId().equals(detail.getSrcItemId())).findFirst().orElse(null);
                if (srcItem == null) {
                    throw new BizException("商品[" + srcItemName + "]信息获取失败");
                }
                InvStockChangeDetail stockChangeDetail = new InvStockChangeDetail();
                stockChangeDetail.setDetailId(detail.getDetailId());
                stockChangeDetail.setRefBillId(detail.getRefBillId());
                stockChangeDetail.setSrcItemId(detail.getSrcItemId());
                stockChangeDetail.setDestItemId(detail.getDestItemId());
                stockChangeDetail.setManufacturerLotNum(detail.getManufacturerLotNum());
                BigDecimal quantity = detail.getQuantity();
                stockChangeDetail.setQuantity(quantity);
                stockChangeDetail.setIsCaseOrPiece(srcItem.getIsCaseOrPiece());

                stockChangeDetails.add(stockChangeDetail);
            }
            stockChange.setDetails(stockChangeDetails);

            stockChanges.add(stockChange);
        }

        log.info("发送库存变更请求===>{}", JsonUtil.toJson(stockChanges));

        RestMessage<List<StockChangeResultVO>> changeResult = stockResource.change(stockChanges);
        if (!changeResult.isSuccess()) {
            throw new BizException("库存货权变更失败!" + changeResult.getMessage());
        }

        List<StockChangeResultVO> changeResultList = changeResult.getData();

        List<WmsCargoChangeResult> changeResults = BeanConvertUtils.convertListTo(changeResultList, WmsCargoChangeResult::new, (s, t) -> {
            t.setEnterpriseId(user.getEnterpriseId());
            t.setGmtCreate(DateUtil.date());
        });

        changeResultMapper.saveBatch(changeResults);

        //转移非整托库存
        List<WmsCargoChangeResult> moveChangeResults = changeResults.stream().filter(x -> "N".equals(x.getIsWhole())).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(moveChangeResults)) {
            //移库
            moveDestCargoStock(moveChangeResults, criteria);
        } else {
            //直接完成
            changeCargoComplete(CollectionUtil.newHashSet(headerIds));
        }
    }

    /**
     * 根据货主转换结果产生移库任务
     *
     * @param changeResults 货主转换结果
     */
    private void moveDestCargoStock(List<WmsCargoChangeResult> changeResults, Criteria criteria) {
        UserDTO user = userTemplate.getUserDTO();

        List<MoveBillCreateVO> billCreate = changeResults.stream().map(s -> {
            MoveBillCreateVO t = new MoveBillCreateVO();
            t.setWarehouseId(s.getWarehouseId());
            t.setCargoOwnerId(s.getDestCargoOwnerId());
            t.setWarehouseWorkerId(user.getId());
            t.setOutLocatorId(s.getSrcLocatorId());
            t.setInLocatorId(s.getDestLocatorId());
            t.setBatchId(s.getDestBatchId());
            t.setOddPieceQuantity(s.getQuantity());
            t.setCaseQuantity(BigDecimal.ZERO);
            t.setInStockStatus(s.getStockStatus());
            t.setOutStockStatus(s.getStockStatus());
            t.setBillId(s.getHeaderId());
            t.setBillNo(s.getHeaderId());
            t.setLineId(s.getDetailId());
            t.setComments("货主转换");
            return t;
        }).collect(Collectors.toList());

        log.info("发送移库请求===>{}", JsonUtil.toJson(billCreate));

        moveService.createMoveBill(billCreate, WmsMoveBillType.SC);

        //修改转换单状态
        cargoChangeMapper.updateMapByCriteria(MapUtils.put("status", CargoChangeStatus.UN_COMPLETED.getStatus()).getMap(), criteria);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeCargoComplete(Set<String> headerIds) {

        log.info("收到移库完成请求, 修改转换单状态!===>{}", JsonUtil.toJson(headerIds));

        Criteria criteria = Criteria.forClass(WmsCargoChangeResult.class);
        RestrictionBuilder updateBuilder = criteria.restrictionBuilder();
        updateBuilder.in("headerId", headerIds.toArray());
        criteria.buildRestriction();

        List<WmsCargoChangeResult> changeResults = changeResultMapper.findByCriteria(criteria);
        if (CollectionUtil.isEmpty(changeResults)) {
            return;
        }

        Map<String, List<WmsCargoChangeResult>> resultMap = changeResults.stream().collect(Collectors.groupingBy(WmsCargoChangeResult::getHeaderId));
        //执行出库
        List<CargoOwnerChangeVO> changeOuts = resultMap.values().stream().map(wmsCargoChangeResults -> {
            CargoOwnerChangeVO changeIn = new CargoOwnerChangeVO();
            WmsCargoChangeResult changeResult = CollectionUtil.get(wmsCargoChangeResults, 0);
            changeIn.setOmsBillId(changeResult.getOrderBillId());
            changeIn.setOmsBillNo(changeResult.getOrderBillNo());
            changeIn.setWarehouseId(changeResult.getWarehouseId());
            changeIn.setCargoOwnerId(changeResult.getSrcCargoOwnerId());

            List<WaveStorageVO> details = new ArrayList<>();
            for (WmsCargoChangeResult result : wmsCargoChangeResults) {
                WaveStorageVO detail = new WaveStorageVO();
                detail.setBatchId(result.getSrcBatchId());
                detail.setQty(result.getQuantity());
                detail.setLocatorId(result.getSrcLocatorId());
                details.add(detail);
            }
            changeIn.setList(details);
            return changeIn;
        }).collect(Collectors.toList());

        log.info("发送出库请求===>{}", JsonUtil.toJson(changeOuts));

        RestMessage outResult = outBoundClient.cargoOwnerChange(changeOuts);
        if (!outResult.isSuccess()) {
            throw new BizException("出库失败!" + outResult.getMessage());
        }

        //执行入库
        List<CargoChangeIn> changeIns = resultMap.values().stream().map(wmsCargoChangeResults -> {
            CargoChangeIn changeIn = new CargoChangeIn();
            WmsCargoChangeResult resultVO = CollectionUtil.get(wmsCargoChangeResults, 0);
            changeIn.setPoBillId(resultVO.getPoBillId());
            changeIn.setPoBillNo(resultVO.getPoBillNo());
            changeIn.setRefBillId(resultVO.getHeaderId());
            changeIn.setRefBillNo(resultVO.getHeaderId());
            changeIn.setWarehouseId(resultVO.getWarehouseId());
            changeIn.setDestCargoOwnerId(resultVO.getDestCargoOwnerId());

            List<CargoChangeInDetails> details = new ArrayList<>();
            for (WmsCargoChangeResult result : wmsCargoChangeResults) {
                CargoChangeInDetails detail = new CargoChangeInDetails();
                detail.setBatchId(result.getDestBatchId());
                detail.setQuantity(result.getQuantity());
                detail.setWhLocatorId(result.getDestLocatorId());
                details.add(detail);
            }
            changeIn.setDetails(details);
            return changeIn;
        }).collect(Collectors.toList());

        log.info("发送入库请求===>{}", JsonUtil.toJson(changeIns));

        RestMessage inResult = inBoundClient.cargoChangeIn(changeIns);
        if (!inResult.isSuccess()) {
            throw new BizException("入库失败!" + inResult.getMessage());
        }

        Criteria updateCriteria = Criteria.forClass(WmsCargoChange.class);
        updateCriteria.restrictionBuilder().in("headerId", headerIds.toArray());
        updateCriteria.buildRestriction();
        //更新转换单状态为已完成
        cargoChangeMapper.updateMapByCriteria(MapUtils.put("status", CargoChangeStatus.COMPLETED.getStatus()).getMap(), updateCriteria);

        String[] lineIds = changeResults.stream().map(WmsCargoChangeResult::getDetailId).toArray(String[]::new);

        InvStockCheckMove invStockMove = new InvStockCheckMove();
        invStockMove.setLineBillIds(lineIds);
        invStockMove.setMoveFlag(2);

        log.info("发送库存确认请求===>{}", JsonUtil.toJson(invStockMove));

        //确认转换
        RestMessage checkResult = stockResource.changeStockCheck(invStockMove);
        if (!checkResult.isSuccess()) {
            throw new BizException("货主转换库存失败!" + checkResult.getMessage());
        }
    }

    @Override
    public void cancel(String[] headerIds) {
        UserDTO user = userTemplate.getUserDTO();
        Criteria criteria = Criteria.forClass(WmsCargoChangeDetail.class);
        criteria.restrictionBuilder().in("headerId", headerIds)
                .eq("enterpriseId", user.getEnterpriseId());
        criteria.buildRestriction();
        List<WmsCargoChangeDetail> details = cargoChangeDetailMapper.findByCriteria(criteria);
        String[] detailIds = details.stream().map(WmsCargoChangeDetail::getDetailId).distinct().toArray(String[]::new);
        InvStockCancel cancel = new InvStockCancel();
        cancel.setLineBillIds(detailIds);

        //更新转换状态
        cargoChangeMapper.updateMapByCriteria(MapUtils.put("status", CargoChangeStatus.CANCEL.getStatus()).getMap(), criteria);

        stockResource.changeCancel(cancel);
    }

    @Override
    public Page<WmsCargoChangeListVO> getCargoChangeList(CargoChangeQueryVO queryVO) {
        Criteria criteria = Criteria.forClass(WmsCargoChange.class);
        RestrictionBuilder builder = criteria.restrictionBuilder();
        if (StrUtil.isNotBlank(queryVO.getWarehouseId())) {
            builder.eq("warehouseId", queryVO.getWarehouseId());
        }
        if (StrUtil.isNotBlank(queryVO.getPoBillNo())) {
            builder.eq("poBillNo", queryVO.getPoBillNo());
        }
        if (StrUtil.isNotBlank(queryVO.getOrderBillNo())) {
            builder.eq("orderBillNo", queryVO.getOrderBillNo());
        }
        if (StrUtil.isNotBlank(queryVO.getSrcCargoOwnerId())) {
            builder.eq("srcCargoOwnerId", queryVO.getSrcCargoOwnerId());
        }
        if (StrUtil.isNotBlank(queryVO.getDestCargoOwnerId())) {
            builder.eq("destCargoOwnerId", queryVO.getDestCargoOwnerId());
        }
        if (StrUtil.isNotBlank(queryVO.getStatus())) {
            builder.eq("status", queryVO.getStatus());
        }
        if (StrUtil.isNotBlank(queryVO.getSourceType())) {
            builder.eq("sourceType", queryVO.getSourceType());
        }
        if (ObjectUtil.isNotNull(queryVO.getBillDate())) {
            builder.eq("billDate", DateUtil.beginOfDay(queryVO.getBillDate()));
        }
        criteria.buildRestriction();
        Page<WmsCargoChange> cargoChanges = PageUtils.getPage(cargoChangeMapper.findByCriteria(criteria));
        return BeanConvertUtils.convertPageTo(cargoChanges, WmsCargoChangeListVO::new, (s, t) -> {
            CargoChangeStatus status = CargoChangeStatus.get(s.getStatus());
            t.setStatusName(status.getName());
        });
    }

    @Override
    public Page<WmsCargoChangeDetailListVO> getCargoChangeDetailList(String headerId) {
        Criteria criteria = Criteria.forClass(WmsCargoChangeDetail.class);
        criteria.restrictionBuilder().eq("headerId", headerId);
        criteria.buildRestriction();
        WmsCargoChange WmsCargoChange=cargoChangeMapper.findById(headerId,WmsCargoChange.class);
        Page<WmsCargoChangeDetail> details = PageUtils.getPage(cargoChangeDetailMapper.findByCriteria(criteria));

        List<WmsCargoChangeDetail> detailsList = details.getList();
        if(detailsList==null || detailsList.size()==0 || detailsList.get(0).getQcOddCaseActQty()!=null){
            return BeanConvertUtils.convertPageTo(details, WmsCargoChangeDetailListVO::new, null);
        }
        String[] itemIds = detailsList.stream().map(WmsCargoChangeDetail::getDestItemId).distinct().toArray(String[]::new);;
        RestMessage<List<ItemBaseInfoVO>> itemResult = itemResource.getItemBaseList(itemIds);
        if (itemResult.isSuccess() && !CollectionUtil.isEmpty(itemResult.getData())) {
            List<ItemBaseInfoVO> itemInfos = itemResult.getData();
            List<RqcLinesDTO> rqcLinesDTOList=new ArrayList<>();
            for (int i = 0; i < details.getList().size(); i++) {
                RqcLinesDTO rqcLinesDTO = new RqcLinesDTO();
                WmsCargoChangeDetail wmsCargoChangeDetail=detailsList.get(i);
                String destItemId = wmsCargoChangeDetail.getDestItemId();
                rqcLinesDTO.setWarehouseId(WmsCargoChange.getWarehouseId());
                rqcLinesDTO.setRcvLineId(wmsCargoChangeDetail.getDetailId());
                rqcLinesDTO.setRcvType("1");
                rqcLinesDTO.setItemId(destItemId);
                ItemBaseInfoVO ItemBaseInfoVO=itemInfos.stream().
                        filter(t->t.getItemId().equals(destItemId)).findFirst().orElse(null);
                if(ItemBaseInfoVO==null){
                    continue;
                }
                rqcLinesDTO.setCategoryId(ItemBaseInfoVO.getItemCategoryCode());
                BigDecimal conversionRate = ItemBaseInfoVO.getCaseConversionRate();
                if(conversionRate ==null || conversionRate.equals(BigDecimal.ZERO)){
                    continue;
                }
                BigDecimal quantity = wmsCargoChangeDetail.getQuantity();
                BigDecimal caseQty = quantity.divide(conversionRate, 0, RoundingMode.DOWN); // 整件
                BigDecimal multiply = caseQty.multiply(conversionRate);
                BigDecimal oddPieceQty = quantity.subtract(multiply); // 零散
                rqcLinesDTO.setPieceQty(oddPieceQty);
                rqcLinesDTO.setOddCaseQty(caseQty);
                rqcLinesDTOList.add(rqcLinesDTO);
            }
            log.info("发送入库请求===>{}", JsonUtil.toJson(rqcLinesDTOList));
            RestMessage<List<WmsInRqcSampleDTO>> inResult = inBoundClient.getPreList(rqcLinesDTOList);
            if(inResult!=null && inResult.isSuccess() &&
                    inResult.getData()!=null && inResult.getData().size()==detailsList.size()){
                for (int i = 0; i < inResult.getData().size(); i++) {
                    WmsCargoChangeDetail wmsCargoChangeDetail=detailsList.get(i);
                    WmsInRqcSampleDTO wmsInRqcSampleDTO = inResult.getData().get(i);
                    wmsCargoChangeDetail.setQcOddCaseQty(wmsInRqcSampleDTO.getQcOddCaseQty());
                    wmsCargoChangeDetail.setQcOddPieceQty(wmsInRqcSampleDTO.getQcOddPieceQty());
                    wmsCargoChangeDetail.setQcOddCaseActQty(wmsInRqcSampleDTO.getQcOddCaseActQty());
                    wmsCargoChangeDetail.setQcOddPieceActQty(wmsInRqcSampleDTO.getQcOddPieceActQty());
                    wmsCargoChangeDetail.setQcQty(wmsCargoChangeDetail.getQuantity());
                }
            }
        }
        return BeanConvertUtils.convertPageTo(details, WmsCargoChangeDetailListVO::new, null);
    }
}
