package com.sw.mes.itemclean.clean.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.sw.mes.core.api.system.YbFeignClients;
import com.sw.mes.core.context.BaseContextHandler;
import com.sw.mes.core.dto.CarrierConfigDto;
import com.sw.mes.core.dto.DictionaryItemDto;
import com.sw.mes.core.enums.EnumValuesFactory;
import com.sw.mes.core.enums.ItemCleanEnums;
import com.sw.mes.core.exception.BusinessException;
import com.sw.mes.core.response.Result;
import com.sw.mes.core.response.ResultCode;
import com.sw.mes.core.response.ResultGenerator;
import com.sw.mes.core.utils.StringUtils;
import com.sw.mes.itemclean.clean.domain.*;
import com.sw.mes.itemclean.clean.dto.*;
import com.sw.mes.itemclean.clean.dto.boxNoOperate.BatchNo;
import com.sw.mes.itemclean.clean.dto.boxNoOperate.BoxNoOperate;
import com.sw.mes.itemclean.clean.mapper.MaterialBrokenDownMapper;
import com.sw.mes.itemclean.clean.mapper.MaterialBrokenMapper;
import com.sw.mes.itemclean.clean.mapping.ScanBoxNoMapping;
import com.sw.mes.itemclean.clean.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.beans.BeanUtils;
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.BigInteger;
import java.sql.Struct;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * <p>
 * 破碎 服务实现类
 * </p>
 *
 * @author liuzemin
 * @since 2022-11-10
 */
@Service
@Slf4j
public class MaterialBrokenServiceImpl extends ServiceImpl<MaterialBrokenMapper, MaterialBroken> implements MaterialBrokenService, ScanBoxNoService {

    @Autowired
    private MaterialStoreSignBoxService materialStoreSignBoxService;

    @Autowired
    private MaterialBrokenDetailService materialBrokenDetailService;

    @Autowired
    private MaterialBrokenDownService materialBrokenDownService;

    @Autowired
    private GenerateBusinessNoService generateBusinessNoService;

    @Autowired
    MaterialCleaningService materialCleaningService;

    @Autowired
    CleaningProcessFlowService cleaningProcessFlowService;

    @Autowired
    MaterialBrokenMapper materialBrokenMapper;

    @Autowired
    MaterialBrokenService materialBrokenService;

    @Autowired
    MaterialBrokenDownMapper materialBrokenDownMapper;

    @Autowired
    MaterialApplyOrderService materialApplyOrderService;

    @Autowired
    YbFeignClients ybFeignClients;

    @Autowired
    private MaterialUnpackingService materialUnpackingService;

    @Autowired
    ModelMapper modelMapper;

    @Autowired
    MaterialGroupDetailService materialGroupDetailService;

    @Override
    public BoxPropertyDto scanBoxNo(GeneralScanBoxNoParam param) {
        if (StringUtils.isBlank(param.getBoxNo()) || StringUtils.isBlank(param.getDeviceNo())){
            throw new RuntimeException("设备号与箱号不能为空");
        }

        LambdaQueryWrapper<MaterialStoreSignBox> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MaterialStoreSignBox::getMaterialBoxNo, param.getBoxNo());
        queryWrapper.eq(MaterialStoreSignBox::getPickingStatus, 1);
//        queryWrapper.in(MaterialStoreSignBox::getMaterialType, Arrays.asList(ItemCleanEnums.MaterialType.原生多晶.getKey()
//                                                                            ,ItemCleanEnums.MaterialType.回收料.getKey()
//                                                                            ,ItemCleanEnums.MaterialType.落地料.getKey()
//                                                                            ,ItemCleanEnums.MaterialType.返工料.getKey()
//                                                                            ,ItemCleanEnums.MaterialType.清洗料.getKey()));
        queryWrapper.last("limit 1");
        MaterialStoreSignBox box = materialStoreSignBoxService.getOne(queryWrapper);
        if (box == null) {
            throw new RuntimeException(param.getBoxNo() + "该箱号不存在！");
        }
        if (box.getIsEmptyBox() == 1) {
            throw new RuntimeException(param.getBoxNo() + "该箱号为空箱！");
        }
        if (box.getMaterialType() == ItemCleanEnums.MaterialType.原生多晶.getKey()
                || box.getMaterialType() == ItemCleanEnums.MaterialType.回收料.getKey()
                || box.getMaterialType() == ItemCleanEnums.MaterialType.落地料.getKey()
                || box.getMaterialType() == ItemCleanEnums.MaterialType.返工料.getKey()
                || box.getMaterialType() == ItemCleanEnums.MaterialType.清洗料.getKey()
        ){
            BoxPropertyDto boxPropertyDto = ScanBoxNoMapping.toDto(box);
            BrokeBoxPropertyDto brokeBoxPropertyDto = new BrokeBoxPropertyDto(); //新的破碎扫箱子返回对象
            BeanUtils.copyProperties(boxPropertyDto, brokeBoxPropertyDto);

            checkIsNewBatch(box.getProductBatchNo(), param.getDeviceNo(), brokeBoxPropertyDto); //检验新批次

            return brokeBoxPropertyDto;
        }else {
            throw new RuntimeException(param.getScanName()+":当前箱号"+param.getBoxNo()+"属于"+ItemCleanEnums.MaterialType.getText(box.getMaterialType()));
        }
    }

    //判断扫的批次号,在当前设备未完结批次中是否是新的
    private void checkIsNewBatch(String productBatchNo, String deviceNo, BrokeBoxPropertyDto brokeBoxPropertyDto) {
        MaterialBroken materialBroken = getByBatchNoAndDevice(productBatchNo, deviceNo);
        if (materialBroken != null) {
            brokeBoxPropertyDto.setIsNewBatch(0);
        }else {
            List<MaterialBroken> materialBrokensByDevice = getByDevice(deviceNo);
            if (materialBrokensByDevice.size() == 0){
                brokeBoxPropertyDto.setIsNewBatch(2);
            }else {
                brokeBoxPropertyDto.setIsNewBatch(1);
            }
        }
    }

    /**
     * 获取当前设备正在上下料信息
     * @param deviceNo
     * @return
     */
    @Override
    public MaterialBroken getCurrentBrokenUpInfo(String deviceNo) {
        LambdaQueryWrapper<MaterialBroken> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MaterialBroken::getDeviceNo, deviceNo);
        queryWrapper.eq(MaterialBroken::getBatchEnd, 0);
        queryWrapper.orderByAsc(MaterialBroken::getId);
        queryWrapper.last("limit 1");
        return getOne(queryWrapper);
    }

    /**
     * 破碎上料
     * @param dto
     */
  /*  @Override
    @Transactional(rollbackFor = Throwable.class)
    public void materialBrokenUp(MaterialBrokenUpDto dto) {
        //获取清洗任务MaterialBroken
        MaterialBroken materialBroken = getMaterialBroken(dto);
        saveOrUpdate(materialBroken);

        //保存扫描的箱子至MaterialBrokenDetail
        MaterialBrokenDetail materialBrokenDetail = buildMaterialBrokenDetail(dto);
        materialBrokenDetail.setBrokenId(materialBroken.getId());
        materialBrokenDetailService.saveOrUpdate(materialBrokenDetail);

        //从MaterialStoreSign逻辑删除扫描的箱子
        materialStoreSignBoxService.discountBox(Arrays.asList(dto.getBoxInfo().getMaterialBoxNo()));
    }
*/

    /**
     * 新版破碎上料
     *
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public MaterialBroken materialBrokenUp(MaterialBrokenUpDto dto) {
        BoxInfoDto boxInfo = dto.getBoxInfo();
        if (StringUtils.isBlank(boxInfo.getMaterialCode())) {
            throw new BusinessException("物料编码为空:" + boxInfo.getMaterialCode());
        }
        //1 判断上料箱来源并查询相关信息:分选表,或者是清洗表;更新对应载具物料重量信息;过站
        if (ItemCleanEnums.MaterialHasGone.分选.getKey() == boxInfo.getSource()) {
            //领料工序的箱子直接到破碎也是一箱整体破碎
            //1.1 分选表更新
            MaterialUnpacking unUseInfoByBoxNo = materialUnpackingService.getUnUseInfoByBoxNo(boxInfo.getBoxNo());
            if (null == unUseInfoByBoxNo) {
                throw new BusinessException("箱号" + boxInfo.getBoxNo() + "的分选物料已经被使用!");
            }
            unUseInfoByBoxNo.setUpdateUser(BaseContextHandler.getUsername());
            unUseInfoByBoxNo.setUpdateTime(LocalDateTime.now());
            unUseInfoByBoxNo.setUsedWeight(unUseInfoByBoxNo.getWeight());
            unUseInfoByBoxNo.setUnusedWeight(BigDecimal.ZERO);
            unUseInfoByBoxNo.setUseStatus(ItemCleanEnums.MaterialFxUseStatus.已清空.getKey());
            materialUnpackingService.updateById(unUseInfoByBoxNo);

            //1.2 过站(老批次,箱号出站;新批次,箱号进入下一站点)
            cleaningProcessFlowService.outStation(unUseInfoByBoxNo.getFxProductBatchNo(), unUseInfoByBoxNo.getFxProductBatchNo(), unUseInfoByBoxNo.getWeight(), unUseInfoByBoxNo.getUnusedWeight(), unUseInfoByBoxNo.getUsedWeight(), "", EnumValuesFactory.CleaningWipStorageCode.领料.getValue(), "", unUseInfoByBoxNo.getBoxNo(), EnumValuesFactory.CleaningWipStorageCode.领料.getValue(), EnumValuesFactory.CleaningWipStorageStatus.工序出站.getKey());
            cleaningProcessFlowService.inStation(unUseInfoByBoxNo.getFxProductBatchNo(), unUseInfoByBoxNo.getFxProductBatchNo(), unUseInfoByBoxNo.getWeight(), unUseInfoByBoxNo.getWeight(), BigDecimal.ZERO, dto.getDeviceNo(), EnumValuesFactory.CleaningWipStorageCode.破碎.getValue(), "", boxInfo.getBoxNo(), EnumValuesFactory.CleaningWipStorageCode.破碎.getValue(), EnumValuesFactory.CleaningWipStorageStatus.工序进站.getKey());

        } else if (ItemCleanEnums.MaterialHasGone.清洗.getKey() == boxInfo.getSource()) {
            //1.1 清洗下料
            MaterialCleaning cleaning = materialCleaningService.materialCleaningPackagingByBoxNo(boxInfo.getBoxNo());
            //1.2 清洗物料更新
            LambdaUpdateWrapper<MaterialCleaning> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(MaterialCleaning::getStatus, ItemCleanEnums.MaterialCleanStatus.待破碎.getKey())
                    .set(MaterialCleaning::getUpdateTime, LocalDateTime.now())
                    .set(MaterialCleaning::getUpdateUser, BaseContextHandler.getUsername())
                    .eq(MaterialCleaning::getId, boxInfo.getId());
            materialCleaningService.update(updateWrapper);

            //1.3 过站
            cleaningProcessFlowService.outStation(cleaning.getProductBatchNo(), cleaning.getProductBatchNo(), cleaning.getWeight(), BigDecimal.ZERO, cleaning.getWeight(), dto.getDeviceNo(), EnumValuesFactory.CleaningWipStorageCode.清洗.getValue(), "", boxInfo.getBoxNo(), EnumValuesFactory.CleaningWipStorageCode.清洗.getValue(), EnumValuesFactory.CleaningWipStorageStatus.工序出站.getKey());
            cleaningProcessFlowService.inStation(cleaning.getProductBatchNo(), cleaning.getProductBatchNo(), cleaning.getWeight(), BigDecimal.ZERO, cleaning.getWeight(), dto.getDeviceNo(), EnumValuesFactory.CleaningWipStorageCode.破碎.getValue(), "", boxInfo.getBoxNo(), EnumValuesFactory.CleaningWipStorageCode.破碎.getValue(), EnumValuesFactory.CleaningWipStorageStatus.工序进站.getKey());
        }
        //2 新增破碎上料信息

        MaterialBroken materialBroken = new MaterialBroken();
        materialBroken.setWeight(boxInfo.getWeight());
        materialBroken.setUnusedWeight(boxInfo.getWeight());
        materialBroken.setUsedWeight(BigDecimal.ZERO);
        materialBroken.setMaterialCode(boxInfo.getMaterialCode());
        materialBroken.setMaterialName(boxInfo.getMaterialName());
        materialBroken.setMaterialLevel(boxInfo.getMaterialLevel());
        materialBroken.setMaterialModel(boxInfo.getMaterialModel());
        materialBroken.setMaterialGear(boxInfo.getMaterialGear());
        materialBroken.setProductBatchNo(boxInfo.getCurrentProductBatchNo());
        materialBroken.setStation(dto.getStation());
        materialBroken.setBatchEnd(0);
        materialBroken.setStatus(ItemCleanEnums.MaterialBrokenUseStatus.未使用.getKey());
        materialBroken.setBoxNo(boxInfo.getBoxNo());
        materialBroken.setDeviceNo(dto.getDeviceNo());
        materialBroken.setCreateUser(BaseContextHandler.getUsername());
        materialBroken.setCreateTime(LocalDateTime.now());
        materialBroken.setUpdateUser(BaseContextHandler.getUsername());
        materialBroken.setUpdateTime(LocalDateTime.now());
        materialBroken.setUpRemark(dto.getRemark());
        saveOrUpdate(materialBroken);
        return materialBroken;
    }

    private MaterialBrokenDetail buildMaterialBrokenDetail(MaterialBrokenUpDto dto) {
        BoxInfoDto boxInfo = dto.getBoxInfo();
        MaterialStoreSignBox materialStoreSignBox = materialStoreSignBoxService.getByBoxNo(boxInfo.getMaterialBoxNo());
        if (materialStoreSignBox == null) {
            throw new RuntimeException("箱号"+boxInfo.getMaterialBoxNo()+"已上料或不存在");
        }

        MaterialBrokenDetail materialBrokenDetail = new MaterialBrokenDetail();
        materialBrokenDetail.setMaterialBoxNo(boxInfo.getMaterialBoxNo());
        materialBrokenDetail.setWeight(boxInfo.getWeight());
        materialBrokenDetail.setMaterialCode(boxInfo.getMaterialCode());
        materialBrokenDetail.setMaterialName(boxInfo.getMaterialName());
        materialBrokenDetail.setMaterialLevel(boxInfo.getMaterialLevel());
        materialBrokenDetail.setMaterialModel(boxInfo.getMaterialModel());
        materialBrokenDetail.setMaterialGear(boxInfo.getMaterialGear());
        materialBrokenDetail.setProductBatchNo(boxInfo.getProductBatchNo());
        materialBrokenDetail.setStation(dto.getStation());
        materialBrokenDetail.setCreateUser(BaseContextHandler.getUsername());
        materialBrokenDetail.setCreateTime(LocalDateTime.now());
        materialBrokenDetail.setUpdateUser(BaseContextHandler.getUsername());
        materialBrokenDetail.setUpdateTime(LocalDateTime.now());

        return materialBrokenDetail;
    }


    private MaterialBroken getMaterialBroken(MaterialBrokenUpDto dto) {
        MaterialBroken materialBroken;
        if (dto.getBoxInfo() != null){
            //获取批次号破碎任务
            materialBroken = getByBatchNoAndDevice(dto.getBoxInfo().getProductBatchNo(), dto.getDeviceNo());

            if (materialBroken != null) {
                BigDecimal nowWeight = Optional.of(materialBroken).map(MaterialBroken::getWeight).orElse(new BigDecimal("0"));
                BigDecimal totalWeight = nowWeight.add(dto.getBoxInfo().getWeight());
                materialBroken.setWeight(totalWeight);
                materialBroken.setUpdateUser(BaseContextHandler.getUsername());
                materialBroken.setUpdateTime(LocalDateTime.now());
            }else {
                BoxInfoDto boxInfo = dto.getBoxInfo();
                materialBroken = new MaterialBroken();
                materialBroken.setWeight(boxInfo.getWeight());
                materialBroken.setMaterialCode(boxInfo.getMaterialCode());
                materialBroken.setMaterialName(boxInfo.getMaterialName());
                materialBroken.setMaterialLevel(boxInfo.getMaterialLevel());
                materialBroken.setMaterialModel(boxInfo.getMaterialModel());
                materialBroken.setMaterialGear(boxInfo.getMaterialGear());
                materialBroken.setProductBatchNo(boxInfo.getProductBatchNo());
                materialBroken.setStation(dto.getStation());
                materialBroken.setBatchEnd(0);
                materialBroken.setDeviceNo(dto.getDeviceNo());
                materialBroken.setCreateUser(BaseContextHandler.getUsername());
                materialBroken.setCreateTime(LocalDateTime.now());
                materialBroken.setUpdateUser(BaseContextHandler.getUsername());
                materialBroken.setUpdateTime(LocalDateTime.now());
            }
            return materialBroken;
        }else {
            throw new RuntimeException("上料信息缺失！");
        }
    }

    @Override
    public MaterialBroken getByBatchNoAndDevice(String batchNo, String deviceNo) {
        LambdaQueryWrapper<MaterialBroken> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MaterialBroken::getProductBatchNo, batchNo);
        queryWrapper.eq(MaterialBroken::getDeviceNo, deviceNo);
        queryWrapper.eq(MaterialBroken::getBatchEnd, 0);
        queryWrapper.last("limit 1");
        return getOne(queryWrapper);
    }

    @Override
    public List<MaterialBroken> getByDevice(String deviceNo) {
        LambdaQueryWrapper<MaterialBroken> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MaterialBroken::getDeviceNo, deviceNo);
        queryWrapper.eq(MaterialBroken::getBatchEnd, 0);
        return getBaseMapper().selectList(queryWrapper);
    }

    //todo:临时方案
/*
    @Override
    public MaterialStoreSignBox materialBrokenToPackaging(BrokenToPackDto dto) {
        // MaterialApplyOrder materialApplyOrder = materialApplyOrderService.getById(dto.getId());
        //保存下料记录至MaterialBrokenDetail

        MaterialBrokenDown materialBrokenDown = buildMaterialToBrokenDown(dto);
        materialBrokenDownService.saveOrUpdate(materialBrokenDown);

        //保存打签成箱表至MaterialStoreSignBox
        MaterialStoreSignBox materialStoreSignBox = buildToMaterialStoreSignBox(materialBrokenDown, dto);
        materialStoreSignBoxService.saveOrUpdate(materialStoreSignBox);
        return materialStoreSignBox;
    }
*/

    /**
     * 新版破碎下料-小箱成箱
     * MaterialBrokenDown不再使用
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public MaterialGroupDetail materialBrokenToPackaging(BrokenToPackDto dto) {
        Integer brokenId = dto.getBrokenId();
        BigDecimal weight = dto.getWeight();
        String boxNo = dto.getBoxNo();
        //1 校验
        if (StringUtils.isBlank(dto.getMaterialCode())) {
            throw new BusinessException("物料编码为空:" + dto.getMaterialCode());
        }
        // 1.1 校验未组托小箱
        MaterialGroupDetail detail = materialGroupDetailService.getGroupDetailInfoByMaterialBoxNo(dto.getMaterialBoxNo());
        if (detail != null) {
            throw new BusinessException("该箱盒" + dto.getMaterialBoxNo() + "存在未组托数据,暂时不可使用");
        }
        //1.2 校验重量是否满足
        MaterialBroken materialBroken = materialBrokenService.getById(brokenId);
        BigDecimal unusedWeight = materialBroken.getUnusedWeight();
        BigDecimal usedWeight = materialBroken.getUsedWeight();
        if (unusedWeight.compareTo(weight) < 0) {
            throw new BusinessException("该箱:" + boxNo + "破碎物料重量不足!");
        }
        //1.3 更新破碎状态以及重量
        BigDecimal subtract = unusedWeight.subtract(weight);
        BigDecimal add = usedWeight.add(weight);
        materialBroken.setStatus(ItemCleanEnums.MaterialBrokenUseStatus.已使用.getKey());
        if (subtract.compareTo(BigDecimal.ZERO) == 0) {
            materialBroken.setStatus(ItemCleanEnums.MaterialBrokenUseStatus.已清空.getKey());
        }
        materialBroken.setUnusedWeight(subtract);
        materialBroken.setUsedWeight(add);
        materialBroken.setUpdateTime(LocalDateTime.now());
        materialBroken.setUpdateUser(dto.getUpdateUser());
        materialBroken.setDownRemark(dto.getDownRemark());
        //2.1 生成小箱记录,组托明细(未组托)
        MaterialGroupDetail materialGroupDetail = createMaterialGroupDetail(dto);
        //2.2 更新破碎记录
        materialBrokenService.saveOrUpdate(materialBroken);
        // 3 过站(老批次,箱号出站;新批次,箱号进入下一站点)
        cleaningProcessFlowService.outStation(materialBroken.getProductBatchNo(), materialBroken.getProductBatchNo(), dto.getWeight(), BigDecimal.ZERO, dto.getWeight(), dto.getDeviceNo(), EnumValuesFactory.CleaningWipStorageCode.破碎.getValue(), "", "", EnumValuesFactory.CleaningWipStorageCode.破碎.getValue(), EnumValuesFactory.CleaningWipStorageStatus.工序出站.getKey());
        cleaningProcessFlowService.inStation(materialGroupDetail.getMaterialBoxNo(), materialGroupDetail.getProductBatchNo(), materialGroupDetail.getWeight(), materialGroupDetail.getWeight(), BigDecimal.ZERO, dto.getDeviceNo(), EnumValuesFactory.CleaningWipStorageCode.出库.getValue(), "", materialGroupDetail.getMaterialBoxNo(), EnumValuesFactory.CleaningWipStorageCode.破碎.getValue(), EnumValuesFactory.CleaningWipStorageStatus.工序待进站.getKey());

        return materialGroupDetail;
    }

    /**
     * 构建组托详情
     * @param dto
     */
    private MaterialGroupDetail createMaterialGroupDetail(BrokenToPackDto dto) {
        MaterialGroupDetail materialGroupDetail = new MaterialGroupDetail();
        //赋值工单号
        MaterialUnpacking unpacking = materialUnpackingService.getFxProductBatchNo(dto.getProductBatchNo());
        if (null != unpacking) {
            materialGroupDetail.setAufnr(unpacking.getAufnr());
        } else {
            throw new BusinessException(dto.getProductBatchNo() + "分选记录不存在!");
        }
        materialGroupDetail.setMaterialBoxNo(dto.getMaterialBoxNo());
        materialGroupDetail.setWeight(dto.getWeight());
        materialGroupDetail.setMaterialCode(dto.getMaterialCode());
        materialGroupDetail.setMaterialName(dto.getMaterialName());
        materialGroupDetail.setMaterialLevel(dto.getMaterialLevel());
        materialGroupDetail.setMaterialModel(dto.getMaterialModel());
        materialGroupDetail.setMaterialGear(dto.getMaterialGear());
        materialGroupDetail.setProductBatchNo(dto.getProductBatchNo());
        materialGroupDetail.setCreateUser(BaseContextHandler.getUsername());
        materialGroupDetail.setCreateTime(LocalDateTime.now());
        materialGroupDetail.setUpdateUser(BaseContextHandler.getUsername());
        materialGroupDetail.setUpdateTime(LocalDateTime.now());
        materialGroupDetail.setStatus(ItemCleanEnums.MaterialGroupDetailStatus.未组托.getKey());
        materialGroupDetail.setBrokenId(dto.getBrokenId());
        materialGroupDetail.setSuppliesGrain(dto.getSuppliesGrain());
        materialGroupDetail.setRemark(dto.getDetailRemark());
        materialGroupDetailService.save(materialGroupDetail);
        return materialGroupDetail;
    }

    //批处理临时方案
    @Override
    public List<MaterialStoreSignBox> materialBrokenToPackagings(BrokenToPackDto dto) {
        //保存下料记录至MaterialBrokenDetail
        List<MaterialBrokenDown> materialBrokenDowns = new ArrayList<>();
        List<MaterialStoreSignBox> materialStoreSignBoxs = new ArrayList<>();
        for (int i = 0; i < dto.getBoxNum(); i++) {
            MaterialBrokenDown materialBrokenDown = buildMaterialToBrokenDown(dto);
            MaterialStoreSignBox materialStoreSignBox = buildToMaterialStoreSignBox(materialBrokenDown, dto);
            materialBrokenDowns.add(materialBrokenDown);
            materialStoreSignBoxs.add(materialStoreSignBox);
        }
        materialBrokenDownService.saveOrUpdateBatch(materialBrokenDowns);
        materialStoreSignBoxService.saveOrUpdateBatch(materialStoreSignBoxs);
        return materialStoreSignBoxs;
    }

    @Override
    public MaterialBroken getByBatchNo(String batchNo) {
        LambdaQueryWrapper<MaterialBroken> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MaterialBroken::getProductBatchNo, batchNo);
        queryWrapper.eq(MaterialBroken::getBatchEnd, 0);
        queryWrapper.last("limit 1");
        return getOne(queryWrapper);
    }

    /**
     * 破碎批次完结
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void materialBrokenEnd(BrokenDownDto dto) {
        //批次完结也打个箱
        materialBrokenPackaging(dto);

        MaterialBroken materialBroken = getById(dto.getId());
//        if (materialBroken.getBatchEnd() == 0){
            materialBroken.setBatchEnd(1);
//        }else {
//            materialBroken.setBatchEnd(0);
//        }
        materialBroken.setUpdateUser(BaseContextHandler.getUsername());
        materialBroken.setUpdateTime(LocalDateTime.now());
        saveOrUpdate(materialBroken);
    }

    /**
     * 破碎下料，打签成箱
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void materialBrokenPackaging(BrokenDownDto dto) {
        MaterialBroken materialBroken = getById(dto.getId());
        if (materialBroken.getBatchEnd() == 1){
            throw new RuntimeException("当前批次"+materialBroken.getProductBatchNo()+"已批次完结，无法再打签成箱！");
        }

        //保存下料记录至MaterialBrokenDetail
        MaterialBrokenDown materialBrokenDown = buildMaterialBrokenDown(materialBroken,dto);
        materialBrokenDownService.saveOrUpdate(materialBrokenDown);

        //保存打签成箱表至MaterialStoreSignBox
        MaterialStoreSignBox materialStoreSignBox = buildMaterialStoreSignBox(materialBrokenDown,dto);
        materialStoreSignBoxService.saveOrUpdate(materialStoreSignBox);
    }

    private MaterialStoreSignBox buildMaterialStoreSignBox(MaterialBrokenDown materialBrokenDown, BrokenDownDto dto) {
        MaterialStoreSignBox materialStoreSignBox = new MaterialStoreSignBox();
        materialStoreSignBox.setWeight(dto.getWeight());
        materialStoreSignBox.setMaterialBoxNo(materialBrokenDown.getMaterialBoxNo());
        materialStoreSignBox.setProductBatchNo(materialBrokenDown.getProductBatchNo());
        materialStoreSignBox.setMaterialCode(materialBrokenDown.getMaterialCode());
        materialStoreSignBox.setMaterialName(materialBrokenDown.getMaterialName());
        materialStoreSignBox.setMaterialLevel(materialBrokenDown.getMaterialLevel());
        materialStoreSignBox.setMaterialModel(materialBrokenDown.getMaterialModel());
        materialStoreSignBox.setMaterialGear(materialBrokenDown.getMaterialGear());
        materialStoreSignBox.setMaterialType(ItemCleanEnums.MaterialType.破碎料.getKey());
        materialStoreSignBox.setPickingStatus(1);
        materialStoreSignBox.setCreateUser(BaseContextHandler.getUsername());
        materialStoreSignBox.setCreateTime(LocalDateTime.now());
        materialStoreSignBox.setUpdateUser(BaseContextHandler.getUsername());
        materialStoreSignBox.setUpdateTime(LocalDateTime.now());
        return materialStoreSignBox;
    }

    private MaterialBrokenDown buildMaterialBrokenDown(MaterialBroken materialBroken, BrokenDownDto dto) {
        MaterialBrokenDown materialBrokenDown = new MaterialBrokenDown();
        materialBrokenDown.setWeight(dto.getWeight());
        materialBrokenDown.setProductBatchNo(materialBroken.getProductBatchNo());
        materialBrokenDown.setMaterialBoxNo(generateBusinessNoService.generateBoxNo(new BoxNoOperate(ItemCleanEnums.BoxNoType.默认, new BatchNo(materialBroken.getProductBatchNo()))));
        materialBrokenDown.setMaterialCode(materialBroken.getMaterialCode());
        materialBrokenDown.setMaterialName(materialBroken.getMaterialName());
        materialBrokenDown.setMaterialLevel(materialBroken.getMaterialLevel());
        materialBrokenDown.setMaterialModel(materialBroken.getMaterialModel());
        materialBrokenDown.setMaterialGear(materialBroken.getMaterialGear());
        materialBrokenDown.setBrokenId(materialBroken.getId());
        materialBrokenDown.setDownUser(dto.getDownUser());
        materialBrokenDown.setDownTime(LocalDateTime.now());
        materialBrokenDown.setCreateUser(BaseContextHandler.getUsername());
        materialBrokenDown.setCreateTime(LocalDateTime.now());
        materialBrokenDown.setUpdateUser(BaseContextHandler.getUsername());
        materialBrokenDown.setUpdateTime(LocalDateTime.now());
        return materialBrokenDown;
    }

    /**
     * todo:临时方案
     *
     * @param dto
     * @return
     */
    private MaterialBrokenDown buildMaterialToBrokenDown(BrokenToPackDto dto) {
        MaterialBrokenDown materialBrokenDown = new MaterialBrokenDown();
        materialBrokenDown.setWeight(dto.getWeight());
        materialBrokenDown.setProductBatchNo(dto.getProductBatchNo());
        materialBrokenDown.setMaterialBoxNo(generateBusinessNoService.generateBoxNo(new BoxNoOperate(ItemCleanEnums.BoxNoType.默认, new BatchNo(dto.getProductBatchNo()))));
        materialBrokenDown.setMaterialCode(dto.getMaterialCode());
        materialBrokenDown.setMaterialName(dto.getMaterialName());
        materialBrokenDown.setMaterialLevel(dto.getMaterialLevel());
        materialBrokenDown.setMaterialModel(dto.getMaterialModel());
        materialBrokenDown.setMaterialGear(dto.getMaterialGear());
        materialBrokenDown.setDownUser(dto.getDownUser());
        materialBrokenDown.setDownTime(LocalDateTime.now());
        materialBrokenDown.setCreateUser(dto.getCreateUser());
        materialBrokenDown.setCreateTime(LocalDateTime.now());
        materialBrokenDown.setUpdateUser(dto.getUpdateUser());
        materialBrokenDown.setUpdateTime(LocalDateTime.now());
        materialBrokenDown.setRemark(dto.getRemark());
        materialBrokenDown.setDeviceNo(dto.getDeviceNo());
        return materialBrokenDown;
    }

    /**
     * todo:临时方案
     *
     * @param materialBrokenDown
     * @param dto
     * @return
     */
    private MaterialStoreSignBox buildToMaterialStoreSignBox(MaterialBrokenDown materialBrokenDown, BrokenToPackDto dto) {
        MaterialStoreSignBox materialStoreSignBox = new MaterialStoreSignBox();
        materialStoreSignBox.setWeight(dto.getWeight());
        materialStoreSignBox.setMaterialBoxNo(materialBrokenDown.getMaterialBoxNo());
        materialStoreSignBox.setProductBatchNo(materialBrokenDown.getProductBatchNo());
        materialStoreSignBox.setMaterialCode(materialBrokenDown.getMaterialCode());
        materialStoreSignBox.setMaterialName(materialBrokenDown.getMaterialName());
        materialStoreSignBox.setMaterialLevel(materialBrokenDown.getMaterialLevel());
        materialStoreSignBox.setMaterialModel(materialBrokenDown.getMaterialModel());
        materialStoreSignBox.setMaterialGear(materialBrokenDown.getMaterialGear());
        materialStoreSignBox.setMaterialType(ItemCleanEnums.MaterialType.破碎料.getKey());
        materialStoreSignBox.setPickingStatus(1);
        materialStoreSignBox.setCreateUser(materialBrokenDown.getDownUser());
        materialStoreSignBox.setCreateTime(LocalDateTime.now());
        materialStoreSignBox.setUpdateUser(BaseContextHandler.getUsername());
        materialStoreSignBox.setUpdateTime(LocalDateTime.now());
        materialStoreSignBox.setRemark(dto.getRemark());
        return materialStoreSignBox;
    }

    /**
     * 计算破碎机台上下料差值
     * @param batchNo
     * @return
     */
    @Override
    public BigDecimal getSumWeightByBatchNo(String batchNo,String deviceNo) {
        String sumUpWeight = materialBrokenMapper.getSumWeightByBatchNo(batchNo,deviceNo);
        String sumDownWeight = materialBrokenDownMapper.getSumWeightByBatchNo(batchNo,deviceNo);
        BigDecimal subtract = new BigDecimal(StringUtils.isEmpty(sumUpWeight) ? "0" : sumUpWeight).subtract(new BigDecimal(StringUtils.isEmpty(sumDownWeight) ? "0" : sumDownWeight));
        if (subtract.compareTo(BigDecimal.ZERO) < 0) {
            throw new BusinessException("破碎机台物料余量计算异常!");
        }
        return subtract;
    }

    @Override
    public BoxInfoDto getInfoByBoxNo(String boxNo) {
        // 1  可能是 清洗下料 或者是 直接分选后破碎上料;也就是可能是花篮号,也可能是分选后的箱号
        //1.1 通过pp号以及分选去向查询分选表数据,查找到数据,则是直接分选后破碎;
        //1.2 否则再查清洗表(去向是破碎的pp号不可能同时存在分选以及清洗表中)
        BoxInfoDto boxInfoDto = new BoxInfoDto();
        //查询分选破碎数据
        MaterialUnpacking unUseInfoByBoxNo = materialUnpackingService.getUnUseInfoByBoxNo(boxNo);
        if (null == unUseInfoByBoxNo) {
            //查询清洗上料数据
            MaterialCleaning materialCleaning = materialCleaningService.getByBoxNo(boxNo);
            if (null == materialCleaning) {
                throw new BusinessException("该箱号中没有可以破碎的物料");
            }
            boxInfoDto = fromDto(materialCleaning);
            boxInfoDto.setCurrentProductBatchNo(materialCleaning.getCleanProductBatchNo());
            boxInfoDto.setStatus(materialCleaning.getStatus());
            boxInfoDto.setSource(ItemCleanEnums.MaterialHasGone.清洗.getKey());
            boxInfoDto.setUsedWeight(BigDecimal.ZERO);
            boxInfoDto.setUnusedWeight(materialCleaning.getWeight());
            boxInfoDto.setTotalWeight(materialCleaning.getWeight() == null ? BigDecimal.ZERO : materialCleaning.getWeight().add(new BigDecimal(StringUtils.isEmpty(materialCleaning.getBoxWeight()) ? "0" : materialCleaning.getBoxWeight())));

        } else {
            boxInfoDto = fromDto(unUseInfoByBoxNo);
            boxInfoDto.setSource(ItemCleanEnums.MaterialHasGone.分选.getKey());
            boxInfoDto.setCurrentProductBatchNo(unUseInfoByBoxNo.getFxProductBatchNo());
        }
        return boxInfoDto;
    }

    @Override
    public MaterialBroken getBrokenInfoByBoxNo(String boxNo) {
        LambdaQueryWrapper<MaterialBroken> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MaterialBroken::getBoxNo, boxNo);
        queryWrapper.in(MaterialBroken::getStatus, ItemCleanEnums.MaterialBrokenUseStatus.未使用.getKey(), ItemCleanEnums.MaterialBrokenUseStatus.已使用.getKey());
        queryWrapper.eq(MaterialBroken::getDelFlag, ItemCleanEnums.MaterialDelFlag.未删除.getKey());
        queryWrapper.last("limit 1");
        return getOne(queryWrapper);
    }

    @Override
    public IPage<MaterialBrokenUpAndDownDto> queryList(IPage<MaterialBrokenUpAndDownDto> iPage, BrokeUpAndDownParamQuery query) {
        return materialBrokenMapper.queryList(iPage, query);
    }

    @Override
    public List<MaterialBrokenUpAndDownDto> queryListByParam(BrokeUpAndDownParamQuery query) {
        return materialBrokenMapper.queryList(query);
    }

    public BoxInfoDto fromDto(MaterialCleaning dto) {
        return modelMapper.map(dto, BoxInfoDto.class);
    }

    public BoxInfoDto fromDto(MaterialUnpacking dto) {
        return modelMapper.map(dto, BoxInfoDto.class);
    }
}
