package com.sw.mes.yb.pad.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.sw.mes.base.factory.init.entity.CrystalMaterialRelation;
import com.sw.mes.base.factory.init.entity.FactoryModel;
import com.sw.mes.base.factory.init.service.CrystalMaterialRelationService;
import com.sw.mes.base.factory.init.service.FactoryModelService;
import com.sw.mes.base.factory.inspect.entity.DefaultCrystalAttrs;
import com.sw.mes.base.factory.inspect.service.DefaultCrystalAttrService;
import com.sw.mes.base.factory.material.entity.MaterialModel;
import com.sw.mes.base.factory.material.service.MaterialModelService;
import com.sw.mes.base.system.entity.DictionaryItem;
import com.sw.mes.base.system.entity.SysLog;
import com.sw.mes.base.system.service.DictionaryItemService;
import com.sw.mes.base.system.service.SysLogService;
import com.sw.mes.core.entity.CrystalLossRecord;
import com.sw.mes.base.workinprocess.dto.CurrentWipStorageStatusDto;
import com.sw.mes.base.workinprocess.entity.WipStorage;
import com.sw.mes.base.workinprocess.service.CrystalLossRecordService;
import com.sw.mes.base.workinprocess.service.WipStorageService;
import com.sw.mes.core.base.BaseServiceImpl;
import com.sw.mes.core.constant.Constants;
import com.sw.mes.core.context.BaseContextHandler;
import com.sw.mes.core.enums.EnumValuesFactory;
import com.sw.mes.core.enums.SectionIndexRangeEnum;
import com.sw.mes.core.enums.SeedMassageEnum;
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.DateUtil;
import com.sw.mes.core.utils.NumberUtil;
import com.sw.mes.dingTalk.service.DingTalkService;
import com.sw.mes.enumvalue.EnumValuesServer;
import com.sw.mes.inspect.dao.YbInspectDataDao;
import com.sw.mes.inspect.dto.YbInspectDataCUDto;
import com.sw.mes.inspect.entity.YbInspectData;
import com.sw.mes.inspect.service.YbInspectDataService;
import com.sw.mes.utils.StringUtils;
import com.sw.mes.yb.mcs.service.PublishRankResultService;
import com.sw.mes.yb.pad.dao.PieceDetailDao;
import com.sw.mes.yb.pad.dao.ProductionPaintingLineDetailDao;
import com.sw.mes.yb.pad.dao.ProductionRecutDao;
import com.sw.mes.yb.pad.dao.SectionNoDetailDao;
import com.sw.mes.yb.pad.dto.ProductionBackCuttingRecordDto;
import com.sw.mes.yb.pad.dto.RecordSegmentNoInfoDto;
import com.sw.mes.yb.pad.dto.RecutInfoDetailInfo;
import com.sw.mes.yb.pad.dto.RecutRuleDto;
import com.sw.mes.yb.pad.entity.*;
import com.sw.mes.yb.pad.service.ProductionPaintingLineDetailService;
import com.sw.mes.yb.pad.service.ProductionPaintingLineService;
import com.sw.mes.yb.pad.service.ProductionRecutService;
import com.sw.mes.yb.pad.service.SectionNoDetailService;
import com.sw.mes.yb.production.entity.LongCrystal;
import com.sw.mes.yb.production.service.LongCrystalService;
import com.sw.mes.yb.turnstore.dao.ProductionBindingTrayDao;
import com.sw.mes.yb.turnstore.entity.ProductionBindingTray;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.beans.BeanUtils;
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 org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional
public class ProductionRecutServiceImpl extends BaseServiceImpl<ProductionBackCuttingRecord> implements ProductionRecutService {
    ProductionRecutDao dao;

    @Autowired
    public void setDao(ProductionRecutDao dao) {
        super.setBaseDao(dao);
        this.dao = dao;
    }

    @Autowired
    ModelMapper modelMapper;
    @Autowired
    private ProductionBindingTrayDao productionBindingTrayDao;

    @Autowired
    private ProductionRecutDao productionRecutDao;

    @Autowired
    private WipStorageService wipStorageService;

    @Autowired
    private PieceDetailDao pieceDetailDao;

    @Autowired
    private ProductionPaintingLineDetailDao productionPaintingLineDetailDao;

    @Autowired
    private SectionNoDetailDao sectionNoDetailDao;

    @Autowired
    private DefaultCrystalAttrService defaultCrystalAttrService;

    @Autowired
    private YbInspectDataDao inspectDataBaseDao;
    @Autowired
    private PublishRankResultService publishRankResultService;

    @Autowired
    private DictionaryItemService dictionaryItemService;

    @Autowired
    private SysLogService sysLogService;

    @Autowired
    private YbInspectDataService ybInspectDataService;

    @Autowired
    private ProductionPaintingLineDetailService productionPaintingLineDetailService;


    @Autowired
    private RedisTemplate redisTemplate;


    @Autowired
    private SectionNoDetailService sectionNoDetailService;


    @Autowired
    private DingTalkService dingTalkService;


    @Autowired
    private CrystalLossRecordService crystalLossRecordService;

    @Autowired
    private CrystalMaterialRelationService crystalMaterialRelationService;

    @Autowired
    private MaterialModelService materialModelService;

    @Autowired
    private LongCrystalService longCrystalService;

    @Autowired
    private ProductionPaintingLineService productionPaintingLineService;

    @Autowired
    private FactoryModelService factoryModelService;


    // 通过托号获取晶段基本信息
    @Override
    public Result<RecordSegmentNoInfoDto> findSegmentNoInfo(String trayNo) {
        // 通过托盘绑定信息 找到对应晶段
        List<ProductionBindingTray> byTrayNo = this.productionBindingTrayDao.findByTrayNo(trayNo);
        if (byTrayNo.size() != 1) {
            return ResultGenerator.fail("此载具找不到唯一晶段信息");
        }
        ProductionBindingTray productionBindingTray = byTrayNo.get(0);
        // 晶段编号,用于记录返切画线生成编号
        return findSegmentNoInfoBySectionNo(productionBindingTray.getCrystalNo());
    }

    @Override
    public List<Map<String,Object>> findInformationBySegmentNo(String segmentNo) {
        String fromMark = segmentNo.substring(SectionIndexRangeEnum.毛棒到截断位数.getBeginIndex(), SectionIndexRangeEnum.毛棒到截断位数.getEndIndex());
        String subSegmentNo = segmentNo;
        if (fromMark.matches("[A-Z]+")) {
            subSegmentNo = segmentNo.substring(SectionIndexRangeEnum.毛棒范围.getBeginIndex(), SectionIndexRangeEnum.毛棒范围.getEndIndex());
        } else {
            subSegmentNo = segmentNo.substring(0, 12);
        }
        return productionRecutDao.findInformationBySegmentNo(subSegmentNo);

    }

    private void judgeCurrentWipStorageStatus(String segmentNo) {
        Result<CurrentWipStorageStatusDto> result = wipStorageService.selectWipStorageResult(segmentNo);
        if (result.getCode() != ResultCode.SUCCESS.getCode()) {
            throw new BusinessException(result.getMessage());
        }
        if (Objects.equals(result.getData().getWipStorageCode(), EnumValuesFactory.WipStorageCode.圆棒检验.getKey()) &&
                result.getData().getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.待进站.getKey()){
            return;
        }

        if (!((Objects.equals(result.getData().getWipStorageCode(), EnumValuesFactory.WipStorageCode.圆棒检验.getKey()) ||
                Objects.equals(result.getData().getWipStorageCode(), EnumValuesFactory.WipStorageCode.粘圆棒.getKey())) &&
                result.getData().getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.已进站.getKey())) {
            throw new BusinessException("只有【" + EnumValuesFactory.WipStorageCode.圆棒检验.getValue() + "，"
                    + EnumValuesFactory.WipStorageCode.粘圆棒.getValue() + "】的【进站】状态才能反切划线");
        }
    }

    @Override
    public Result<LinkedList<RecordSegmentNoInfoDto>> findSegmentNoInfoV2(String trayNo) {
        // 通过托盘绑定信息 找到对应晶段
        List<ProductionBindingTray> byTrayNo = this.productionBindingTrayDao.findByTrayNo(trayNo);
        if (byTrayNo.size() != 1) {
            return ResultGenerator.fail("【" + trayNo + "】载具编号信息不存在");
        }
        String segmentNo = byTrayNo.get(0).getCrystalNo();
        if (StringUtils.isBlank(segmentNo)) {
            return ResultGenerator.fail("此载具，没有绑定晶段信息");
        }
        return findSegmentNoInfoBySectionNoV2(segmentNo);
    }

    @Override
    public Result<RecordSegmentNoInfoDto> findSegmentNoInfoBySectionNo(String sectionNo) {
        // 检验数据提交判断是否在圆棒检验已进站状态
        judgeCurrentWipStorageStatus(sectionNo);

        ProductionBackCuttingRecord bySectionNo = findBySegmentNo(sectionNo);
        if (bySectionNo != null) {
            return ResultGenerator.fail("该单晶已有反切记录!请勿重复操作");
        }

        // 用晶段编号去画线记录明细表找到对应的长度信息
        BigDecimal length = null;
        List<YbInspectData> ybInspectDatas = this.inspectDataBaseDao.findBySectionNo(sectionNo);
        if (ybInspectDatas.size() == 0) {
            return ResultGenerator.fail("该晶段没有检验数据，无法获取长度");
        }
        length = ybInspectDatas.get(0).getActualLength();
        List<SectionNoDetail> sectionNoDetails = sectionNoDetailDao.findBySectionNo(sectionNo);
        if (sectionNoDetails.size() == 0) {
            return ResultGenerator.fail("该晶段信息不存在");
        }
        RecordSegmentNoInfoDto recordSegmentNoInfoDto = new RecordSegmentNoInfoDto();
        recordSegmentNoInfoDto.setSegmentNo(sectionNoDetails.get(0).getSectionNo());
        recordSegmentNoInfoDto.setSegmentId(sectionNoDetails.get(0).getId());
        recordSegmentNoInfoDto.setLength(length);
        return ResultGenerator.success(recordSegmentNoInfoDto);
    }

    @Override
    public Result<LinkedList<RecordSegmentNoInfoDto>> findSegmentNoInfoBySectionNoV2(String segmentNo) {
        // 检验数据提交判断是否在圆棒检验已进站状态
        //wipStorageService.selectWipStorage(segmentNo,EnumValuesFactory.WipStorageCode.圆棒检验.getKey(),true);
        judgeCurrentWipStorageStatus(segmentNo);
        ProductionBackCuttingRecord bySectionNo = findBySegmentNo(segmentNo);
        if (bySectionNo != null) {
            throw new BusinessException("该单晶已有反切记录!请勿重复操作");
        }

        // 用晶段编号去画线记录明细表找到对应的长度信息
        BigDecimal length = null;
        List<YbInspectData> ybInspectDatas = this.inspectDataBaseDao.findBySectionNo(segmentNo);
        if (ybInspectDatas.size() == 0) {
            throw new BusinessException("该晶段没有检验数据，无法获取长度");
        }
        List<SectionNoDetail> sectionNoDetails = sectionNoDetailDao.findBySectionNo(segmentNo);
        if (!segmentNo.startsWith("B") && sectionNoDetails.size() == 0) {
            throw new BusinessException("该晶段信息不存在");
        }
        Set<String> sectionComposes = new LinkedHashSet<>();
        if (StringUtils.isNotBlank(ybInspectDatas.get(0).getSectionCompose())) {
            sectionComposes = new LinkedHashSet<>(Arrays.asList(ybInspectDatas.get(0).getSectionCompose().split(",")));
        }
        LinkedList<RecordSegmentNoInfoDto> recordSegmentNoInfoDtos = new LinkedList<>();
        if (segmentNo.startsWith("B")) {
            //代工数据
            if (sectionComposes.size() > 1) {
                for (String sectionNo : sectionComposes) {
                    if (sectionNo != null) {
                        if (sectionNo.equals((segmentNo))) {
                            recordSegmentNoInfoDtos.add(new RecordSegmentNoInfoDto(
                                    ybInspectDatas.get(0).getSectionNo(),
                                    ybInspectDatas.get(0).getId(),
                                    ybInspectDatas.get(0).getActualLength(), ybInspectDatas.get(0).getSectionCompose()));
                        } else {
                            try {
                                wipStorageService.selectWipStorage(sectionNo, EnumValuesFactory.WipStorageCode.圆棒检验.getKey(), true);
                            } catch (BusinessException e) {
                                throw new BusinessException("【拼棒】" + e.getMessage());
                            }
                            List<YbInspectData> inspectDataBases1 = this.inspectDataBaseDao.findBySectionNo(sectionNo);
                            if (inspectDataBases1.size() == 0) {
                                return ResultGenerator.fail("该晶段没有检验数据，无法获取长度");
                            }
                            List<SectionNoDetail> sectionNoDetails1 = sectionNoDetailDao.findBySectionNo(sectionNo);
                            if (sectionNoDetails1.size() == 0) {
                                return ResultGenerator.fail("该晶段信息不存在");
                            }
                            recordSegmentNoInfoDtos.add(new RecordSegmentNoInfoDto(
                                    sectionNoDetails1.get(0).getSectionNo(),
                                    sectionNoDetails1.get(0).getId(),
                                    inspectDataBases1.get(0).getActualLength(), inspectDataBases1.get(0).getSectionCompose()));
                        }
                    }
                }
            } else {
                recordSegmentNoInfoDtos.add(new RecordSegmentNoInfoDto(
                        ybInspectDatas.get(0).getSectionNo(),
                        ybInspectDatas.get(0).getId(),
                        ybInspectDatas.get(0).getActualLength(), null));


            }
        }else {
            if (sectionComposes.size() > 1) {
                for (String sectionNo : sectionComposes) {
                    if (sectionNo != null) {
                        if (sectionNo.equals((sectionNoDetails.get(0).getSectionNo()))) {
                            recordSegmentNoInfoDtos.add(new RecordSegmentNoInfoDto(
                                    sectionNoDetails.get(0).getSectionNo(),
                                    sectionNoDetails.get(0).getId(),
                                    ybInspectDatas.get(0).getActualLength(), ybInspectDatas.get(0).getSectionCompose()));
                        } else {
                            try {
                                wipStorageService.selectWipStorage(sectionNo, EnumValuesFactory.WipStorageCode.圆棒检验.getKey(), true);
                            } catch (BusinessException e) {
                                throw new BusinessException("【拼棒】" + e.getMessage());
                            }
                            List<YbInspectData> inspectDataBases1 = this.inspectDataBaseDao.findBySectionNo(sectionNo);
                            if (inspectDataBases1.size() == 0) {
                                return ResultGenerator.fail("该晶段没有检验数据，无法获取长度");
                            }
                            List<SectionNoDetail> sectionNoDetails1 = sectionNoDetailDao.findBySectionNo(sectionNo);
                            if (sectionNoDetails1.size() == 0) {
                                return ResultGenerator.fail("该晶段信息不存在");
                            }
                            recordSegmentNoInfoDtos.add(new RecordSegmentNoInfoDto(
                                    sectionNoDetails1.get(0).getSectionNo(),
                                    sectionNoDetails1.get(0).getId(),
                                    inspectDataBases1.get(0).getActualLength(), inspectDataBases1.get(0).getSectionCompose()));
                        }
                    }
                }
            } else {
                recordSegmentNoInfoDtos.add(new RecordSegmentNoInfoDto(
                        sectionNoDetails.get(0).getSectionNo(),
                        sectionNoDetails.get(0).getId(),
                        ybInspectDatas.get(0).getActualLength(), null));


            }
        }
        return ResultGenerator.success(recordSegmentNoInfoDtos);
    }

    @Override
    public Result<LinkedList<RecordSegmentNoInfoDto>> findSegmentNoInfoBySectionNoV2New(String segmentNo) {
        Result<CurrentWipStorageStatusDto> result = wipStorageService.selectWipStorageResult(segmentNo);
        if (result.getCode() != ResultCode.SUCCESS.getCode()) {
            throw new BusinessException(result.getMessage());
        }
        if (Objects.equals(result.getData().getWipStorageCode(), EnumValuesFactory.WipStorageCode.圆棒检验.getKey()) &&
                result.getData().getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.待进站.getKey()){
            ProductionBackCuttingRecord productionBackCuttingRecord = this.findBySegmentNo(segmentNo);
            if (null != productionBackCuttingRecord){
                throw new BusinessException("该单晶已有反切记录!请勿重复操作");
            }
            List<SectionNoDetail> sectionNoDetails = sectionNoDetailDao.findBySectionNo(segmentNo);
            if (CollectionUtils.isEmpty(sectionNoDetails)) {
                throw new BusinessException("该晶段信息不存在");
            }
            SectionNoDetail sectionNoDetail = sectionNoDetails.get(0);
            LinkedList<RecordSegmentNoInfoDto> recordSegmentNoInfoDtos = new LinkedList<>();
            recordSegmentNoInfoDtos.add(new RecordSegmentNoInfoDto(sectionNoDetail.getSectionNo(), sectionNoDetail.getId(), sectionNoDetail.getLength(), null));
            return ResultGenerator.success(recordSegmentNoInfoDtos);
        }else {
            //走之前业务逻辑，不调整
            return this.findSegmentNoInfoBySectionNoV2(segmentNo);
        }
    }


    /**
     * 根据现有反切规则 获取反切后的编号
     *
     * @param productionBackCuttingRecordDtos
     */
    @Override
    public void getSegmentNoV2(List<ProductionBackCuttingRecordDto> productionBackCuttingRecordDtos) {
        for (ProductionBackCuttingRecordDto backCuttingRecordDto : productionBackCuttingRecordDtos) {
            // 原有晶段编号
            String segmentNo = StringUtils.upperCase(StringUtils.trim(backCuttingRecordDto.getSegmentNo()));
            List<SectionNoDetail> sectionNoDetails = sectionNoDetailDao.findBySectionNo(segmentNo);
           /* if (CollectionUtils.isEmpty(sectionNoDetails) || sectionNoDetails.size() == 0) {
                if (segmentNo.startsWith("B")) {
                    SectionNoDetail recutDetail = new SectionNoDetail();
                    recutDetail.setSectionNo(segmentNo);
                    recutDetail.setParentId(0L);
                    YbInspectData ybInspectData = ybInspectDataService.getSectionNo(segmentNo);
                    if (null != ybInspectData) {
                        recutDetail.setCrystalId(ybInspectData.getId());
                        recutDetail.setDopant(ybInspectData.getDopant());
                        recutDetail.setSpecs(ybInspectData.getProductTypeSecond());
                    } else {
                        recutDetail.setCrystalId(0L);
                    }
                    recutDetail.setCreateDate(new Date());
                    recutDetail.setCreateUser(BaseContextHandler.getUsername());
                    recutDetail.setRetCutSegmentNum(0);
                    sectionNoDetailDao.save(recutDetail);
                     sectionNoDetails = sectionNoDetailDao.findBySectionNo(segmentNo);

                }else {
                    throw new BusinessException(backCuttingRecordDto.getSegmentNo() + "晶段编号不存在");
                }
            }*/
            SectionNoDetail sectionNoDetail = sectionNoDetails.get(0);
            segmentNo = sectionNoDetail.getSectionNo();

            if (backCuttingRecordDto.getDetail().size() < 1) {
                throw new BusinessException(backCuttingRecordDto.getSegmentNo() + "切断明细内，至少包含一段晶段");
            }
            List<RecutInfoDetailInfo> detail = backCuttingRecordDto.getDetail();
            //晶段数量
            int segmentCount = 0;
            //头尾样片数量，不合格反切时使用
            int headPieceCount = 0, tailPieceCount = 0;
            boolean isheadPiece = true;
            for (RecutInfoDetailInfo recutInfoDetailInfo : backCuttingRecordDto.getDetail()) {
                if ("晶段".equals(recutInfoDetailInfo.getType())) {
                    segmentCount++;
                    isheadPiece = false;
                }
                if ("样片".equals(recutInfoDetailInfo.getType())) {
                    if (isheadPiece) {
                        headPieceCount++;
                    } else {
                        tailPieceCount++;
                    }
                }
            }

            if (segmentCount > 9) {
                throw new BusinessException("反切段数不能大于10");
            }
            if (segmentCount == 0 && productionBackCuttingRecordDtos.size() == 0) {
                throw new BusinessException("划线明细不能为空");
            }
            if (segmentCount == 0 && (headPieceCount + tailPieceCount) > 0) {
                throw new BusinessException("没有晶段，不允许取样片");
            }
            // 反切规则集合
            int segmentIndex = 1, materialIndex = 1;
            tailPieceCount = 0;
            headPieceCount = 0;
            //最后一段的序号
            int lsatSegmentIndexNo = 1;

            // 获取已经没有用到的segmentCount
            //LinkedList<String> segmentIndexs = getSegmentNoIndex(sectionNoDetail, segmentCount);
            Integer indexSectionNo = 1;
            Date date = new Date();
            // 去除晶段编号最后一位
            for (int i = 0; i < detail.size(); i++) {
                if ("晶段".equals(detail.get(i).getType())) {
//                    segmentNo = segmentNo.substring(0, segmentNo.length() - 1) + segmentIndexs.get(segmentIndex - 1);
                    detail.get(i).getSegmentIndex().setTailPieceNum(0);
                    detail.get(i).getSegmentIndex().setHeadPieceNum(0);
                    detail.get(i).getSegmentIndex().setMaterialNum(0);
                    detail.get(i).setSegmentNo(segmentNo + indexSectionNo);
                    indexSectionNo++;

                    //头样片最大序号赋值
                    detail.get(i).getSegmentIndex().setHeadPieceNum(headPieceCount);
                    headPieceCount = 0;
                    if (segmentIndex != 0) {
                        //尾样片最大序号赋值
                        detail.get(lsatSegmentIndexNo).getSegmentIndex().setTailPieceNum(tailPieceCount);
                    }
                    tailPieceCount = 0;
                    //晶段段数++
                    segmentIndex++;
                    lsatSegmentIndexNo = i;
                } else if ("样片".equals(detail.get(i).getType())) {
                    if (segmentIndex == 1) {
                        detail.get(i).setSegmentNo(this.handleSampleNo(date,segmentNo,1,false));
//                        detail.get(i).setSegmentNo(segmentNo.substring(0, segmentNo.length() - 1) + segmentIndexs.get(segmentIndex - 1) + "TP");
                        headPieceCount++;
                    } else {
                        detail.get(i).setSegmentNo(this.handleSampleNo(date,segmentNo,1,true));
//                        detail.get(i).setSegmentNo(segmentNo + "WP");
                        tailPieceCount++;
                        detail.get(segmentIndex - 1).getSegmentIndex().setTailPieceNum(tailPieceCount);
                    }
                } else if ("回收料".equals(detail.get(i).getType())) {
                    detail.get(i).setSegmentNo(sectionNoDetail.getSectionNo() + "0" + materialIndex);
                    materialIndex++;
                } else {
                    throw new BusinessException("【" + detail.get(i).getType() + "】该类型未处理");
                }
            }
            if (segmentCount == 0) {
                if (backCuttingRecordDto.getDetail().size() > 0) {
                    backCuttingRecordDto.setBackCutType(3);
                } else {
                    if (productionBackCuttingRecordDtos.size() == 1) {
                        throw new BusinessException("划线明细不能为空");
                    } else {
                        backCuttingRecordDto.setBackCutType(2);
                    }
                }
            } else if (segmentCount == 1) {
                backCuttingRecordDto.setBackCutType(0);
            } else {
                backCuttingRecordDto.setBackCutType(1);
            }
            backCuttingRecordDto.setDetail(detail);
        }
    }

    @Override
    public String handleSampleNo(Date date,String segmentNo,Integer sampleCount,Boolean isTailFlag){
        if (StringUtils.isBlank(segmentNo)){
            return null;
        }
        SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd");

        String formatDate = formatter.format(date);
        String years = formatDate.substring(3, 4);
        Integer month = Integer.valueOf(formatDate.substring(5, 7));
        String monthStr = "";
        if (month < 10){
            monthStr = formatDate.substring(6, 7);
        }else if (month == 10){
            monthStr = "A";
        }else if (month == 11){
            monthStr = "B";
        }else if (month == 12){
            monthStr = "C";
        }
        String base = segmentNo.substring(0, 1);
        String dopant = segmentNo.substring(2, 3);
        String workshop = segmentNo.substring(6, 7);
        String day = formatDate.substring(8);

        Integer count = 0;
        Integer index = 1;
        String redisKey = "sampleNo:"+ formatDate;
        if (redisTemplate.hasKey(redisKey)){
            count = Integer.valueOf(redisTemplate.opsForValue().get(redisKey).toString());
        }
        redisTemplate.opsForValue().set(redisKey, count + sampleCount, 24, TimeUnit.HOURS);

        StringBuilder sampleNo = new StringBuilder();
        sampleNo.append(base).append(dopant);
        if (isTailFlag){
            sampleNo.append("T");
        }else {
            sampleNo.append("Y");
        }
        sampleNo.append(years).append(monthStr).append(day).append(workshop).append(String.format("%04d", count + index));

        return sampleNo.toString();
    }


    private LinkedList<String> getSegmentNoIndex(SectionNoDetail sectionNoDetail, int count) {
        LinkedList<String> segmentNoIndexs = new LinkedList<>();
        if (count > 0) {
            SectionNoDetail sectionNoDetailInitial = sectionNoDetailDao.findByCrystalIdAndSegmentNumAndParentId(sectionNoDetail.getCrystalId(), sectionNoDetail.getSegmentNum(), 0L);
            // String segmentNoIndexStr = NumberUtil.object2String(redisUtils.hmGet(sectionNoDetailInitial.getSectionNo(),sectionNoDetail.getSegmentNum()),"");
//            if (StringUtils.isBlank(segmentNoIndexStr)) {
            String indexs = StringUtils.leftPad(Integer.toBinaryString(NumberUtil.Object2Integer(sectionNoDetailInitial.getRetCutSegmentNum(), 0)), 26, "0");
            StringBuilder newIndex = new StringBuilder();
            for (int i = 0; i < indexs.length(); i++) {
                if (i != 24 && segmentNoIndexs.size() < count && "0".equals(indexs.charAt(i) + "")) {
                    segmentNoIndexs.add(Constants.englishArr[i + 1]);
                }
            }
            //redisUtils.hmSet(sectionNoDetailInitial.getSectionNo(),sectionNoDetail.getSegmentNum(),StringUtils.join(segmentNoIndexs,","));
            return segmentNoIndexs;
//            }
        }
        return segmentNoIndexs;
    }

    // 根据现有反切规则 获取反切后的编号
    @Override
    public Result<List<RecutInfoDetailInfo>> getSegmentNo(ProductionBackCuttingRecordDto backCuttingRecordDto) {
        // 原有晶段编号
        String segmentNo = StringUtils.upperCase(StringUtils.trim(backCuttingRecordDto.getSegmentNo()));
        List<SectionNoDetail> sectionNoDetails = sectionNoDetailDao.findBySectionNo(segmentNo);
        if (sectionNoDetails.size() == 0) {
            throw new BusinessException(backCuttingRecordDto.getSegmentNo() + "晶段编号不存在");
        }
        SectionNoDetail sectionNoDetail = sectionNoDetails.get(0);
        segmentNo = sectionNoDetail.getSectionNo();

        if (backCuttingRecordDto.getDetail().size() < 1) {
            throw new BusinessException(backCuttingRecordDto.getSegmentNo() + "切断明细内，至少包含一段晶段");
        }
        List<RecutInfoDetailInfo> detail = backCuttingRecordDto.getDetail();
        //晶段数量
        int segmentCount = 0;
        //头尾样片数量，不合格反切时使用
        int headPieceCount = 0, tailPieceCount = 0;
        boolean isheadPiece = true;
        for (RecutInfoDetailInfo recutInfoDetailInfo : backCuttingRecordDto.getDetail()) {
            if ("晶段".equals(recutInfoDetailInfo.getType())) {
                segmentCount++;
                isheadPiece = false;
            }
            if ("样片".equals(recutInfoDetailInfo.getType())) {
                if (isheadPiece) {
                    headPieceCount++;
                } else {
                    tailPieceCount++;
                }
            }
        }
        if (segmentCount > 9) {
            throw new BusinessException("反切段数不能大于10");
        }
        //分段反切
        if (segmentCount > 1) {
            // 反切规则集合
            int segmentIndex = 1, materialIndex = 1;
            tailPieceCount = 0;
            headPieceCount = 0;
            //最后一段的序号
            int lsatSegmentIndexNo = 1;
//            int segmentIndex = sectionNoDetail.getRetCutSegmentNum(),materialCount = 1,tailPiece = 1;
//            SectionNoDetail sectionNoDetail1;
//            if (sectionNoDetail.getOriginParentId() != 0 && sectionNoDetail.getParentId().longValue() != sectionNoDetail.getOriginParentId()) {
//                sectionNoDetail1 = sectionNoDetailDao.findById(sectionNoDetail.getOriginParentId()).orElse(null);
//                if (sectionNoDetail1 != null) {
//                    segmentIndex = sectionNoDetail1.getRetCutSegmentNum();
//                    sectionNoDetail1.setRetCutSegmentNum(segmentIndex + segmentCount);
//                }
//            } else {
//                sectionNoDetail.setRetCutSegmentNum(segmentIndex + segmentCount);
//            }

            for (int i = 0; i < detail.size(); i++) {
                if ("晶段".equals(detail.get(i).getType())) {
                    detail.get(i).getSegmentIndex().setTailPieceNum(0);
                    detail.get(i).getSegmentIndex().setHeadPieceNum(0);
                    detail.get(i).getSegmentIndex().setMaterialNum(0);
                    detail.get(i).setSegmentNo(segmentNo + "F" + segmentIndex);
                    //头样片最大序号赋值
                    detail.get(i).getSegmentIndex().setHeadPieceNum(headPieceCount);
                    headPieceCount = 0;
                    if (segmentIndex != 0) {
                        //尾样片最大序号赋值
                        detail.get(lsatSegmentIndexNo).getSegmentIndex().setTailPieceNum(tailPieceCount);
                    }
                    tailPieceCount = 0;
                    //晶段段数++
                    segmentIndex++;
                    lsatSegmentIndexNo = i;
                } else if ("样片".equals(detail.get(i).getType())) {
                    if (segmentIndex == 1) {
                        detail.get(i).setSegmentNo(segmentNo + "F" + segmentIndex + "T1");
                        headPieceCount++;
                    } else {
                        detail.get(i).setSegmentNo(segmentNo + "F" + (segmentIndex - 1) + "W1");
                        tailPieceCount++;
                        detail.get(segmentIndex - 1).getSegmentIndex().setTailPieceNum(tailPieceCount);
                    }
                } else if ("回收料".equals(detail.get(i).getType())) {
                    detail.get(i).setSegmentNo(segmentNo + "X" + materialIndex);
                    materialIndex++;
                } else {
                    throw new BusinessException("【" + detail.get(i).getType() + "】该类型未处理");
                }
            }
        }
        // 不合格反切
        else {
            if (headPieceCount > 1) {
                throw new BusinessException("头样片，只能取一片");
            }
            if (tailPieceCount > 1) {
                throw new BusinessException("尾样片，只能取一片");
            }
            SectionNoDetail sectionNoDetailOld = new SectionNoDetail();
            BeanUtils.copyProperties(sectionNoDetail, sectionNoDetailOld);
            if (sectionNoDetails.size() == 0) {
                throw new BusinessException("晶段编号不存在");
            }
            //不合格反切继承，上一次的头尾样片序号
            Integer headPieceIndex = NumberUtil.Object2Integer(sectionNoDetail.getHeadPieceNum(), 0);
            Integer tailPieceIndex = NumberUtil.Object2Integer(sectionNoDetail.getTailPieceNum(), 0);
            Integer materialIndex = NumberUtil.Object2Integer(sectionNoDetail.getMaterialNum(), 0);
            Integer segmentIndex = null;
            boolean isheadPiece1 = true;
            for (int i = 0; i < detail.size(); i++) {
                if ("晶段".equals(detail.get(i).getType())) {
                    detail.get(i).setSegmentNo(segmentNo);
                    isheadPiece1 = false;
                    detail.get(i).getSegmentIndex().setHeadPieceNum(headPieceIndex);
                    segmentIndex = i;
                } else if ("样片".equals(detail.get(i).getType())) {
                    if (isheadPiece1) {
                        detail.get(i).setSegmentNo(segmentNo + "T" + ++headPieceIndex);
                    } else {
                        detail.get(i).setSegmentNo(segmentNo + "W" + ++tailPieceIndex);
                        detail.get(segmentIndex).getSegmentIndex().setTailPieceNum(tailPieceIndex);
                    }
                } else if ("回收料".equals(detail.get(i).getType())) {
                    detail.get(i).setSegmentNo(segmentNo + "X" + ++materialIndex);
                }
            }
            if (segmentIndex != null) {
                detail.get(segmentIndex).getSegmentIndex().setMaterialNum(materialIndex);
            }
        }
        if (segmentCount == 0) {
            if (backCuttingRecordDto.getDetail().size() > 0) {
                backCuttingRecordDto.setBackCutType(3);
            } else {
                throw new BusinessException("划线明细不能为空");
            }
        } else if (segmentCount == 1) {
            backCuttingRecordDto.setBackCutType(0);
        } else {
            backCuttingRecordDto.setBackCutType(1);
        }
        backCuttingRecordDto.setDetail(detail);
        return ResultGenerator.success(detail);
    }

    @Override
    public void createBackCuttingRecord(ProductionBackCuttingRecordDto backCuttingRecordDto, BigDecimal
            weightLossCoefficient
            , DefaultCrystalAttrs defaultCrystalAttrList, boolean isInheritSample) {
        this.createBackCuttingRecord(backCuttingRecordDto, weightLossCoefficient, defaultCrystalAttrList, isInheritSample, false,false);
    }

    // 保存反切画线信息
    @Override
    public void createBackCuttingRecord(ProductionBackCuttingRecordDto backCuttingRecordDto, BigDecimal weightLossCoefficient,
                                        DefaultCrystalAttrs defaultCrystalAttrList, boolean isInheritSample, boolean auto,Boolean waitFlag) {
        // 检验数据提交判断是否在圆棒检验已进站状态
        Result<CurrentWipStorageStatusDto> wipStorage = wipStorageService.selectWipStorageResult(backCuttingRecordDto.getSegmentNo());
        boolean isTrue = (EnumValuesFactory.WipStorageCode.圆棒检验.getKey().equals(wipStorage.getData().getWipStorageCode())
                || EnumValuesFactory.WipStorageCode.粘圆棒.getKey().equals(wipStorage.getData().getWipStorageCode()))
                && wipStorage.getData().getWipStorageStatus() != null
                && EnumValuesFactory.WipStorageStatus.已进站.getKey() == wipStorage.getData().getWipStorageStatus();

        Boolean waitWipStorageStatus = EnumValuesFactory.WipStorageCode.圆棒检验.getKey().equals(wipStorage.getData().getWipStorageCode()) &&
                EnumValuesFactory.WipStorageStatus.待进站.getKey() == wipStorage.getData().getWipStorageStatus();
        if (!isTrue && !(auto && EnumValuesFactory.WipStorageCode.圆棒截断.getKey().equals(wipStorage.getData().getWipStorageCode())
                && EnumValuesFactory.WipStorageStatus.待进站.getKey() == wipStorage.getData().getWipStorageStatus())) {
            if (waitFlag){
                if (!waitWipStorageStatus){
                    throw new RuntimeException("【" + backCuttingRecordDto.getSegmentNo() + "】" + wipStorage.getData().getWipStorageCodeName() + "[" + wipStorage.getData().getWipStorageStatusName() + "]不允许反切划线");
                }
            }else {
                throw new RuntimeException("【" + backCuttingRecordDto.getSegmentNo() + "】" + wipStorage.getData().getWipStorageCodeName() + "[" + wipStorage.getData().getWipStorageStatusName() + "]不允许反切划线");
            }
        }
        if (StringUtils.isBlank(backCuttingRecordDto.getUuid())) {
            backCuttingRecordDto.setUuid(UUID.randomUUID().toString());
        }
        backCuttingRecordDto.setStatus(false);
        List<ProductionPaintingLineDetail> detailList = new ArrayList<>();
        List<SectionNoDetail> sectionNoDetails = this.sectionNoDetailDao.findBySectionNo(backCuttingRecordDto.getSegmentNo());
        if (sectionNoDetails == null || sectionNoDetails.size() == 0) {
            throw new RuntimeException("该圆棒:" + backCuttingRecordDto.getSegmentNo() + "不存在 ,无法返切");
        }

        // 通过圆棒编号去圆棒信息表中找到对应属性信息
        SectionNoDetail sectionNoDetail = sectionNoDetails.get(0);
        ProductionBackCuttingRecord productionBackCuttingRecord = this.fromDto(backCuttingRecordDto);
        productionBackCuttingRecord.setIsInheritSample(isInheritSample);
        Integer segmentId = sectionNoDetail.getId().intValue();
        Long crystalId = sectionNoDetail.getCrystalId();
        // 获取所有画线信息
        List<RecutInfoDetailInfo> data = backCuttingRecordDto.getDetail();
        productionBackCuttingRecord.setSegmentNo(backCuttingRecordDto.getSegmentNo());
        if (StringUtils.isBlank(productionBackCuttingRecord.getUserName())) {
            productionBackCuttingRecord.setUserName(BaseContextHandler.getUsername());
        }
        productionBackCuttingRecord.setLineEndTime(new Date());
        //添加字段，用于最后过站不关联数据
        if (waitWipStorageStatus){
            productionBackCuttingRecord.setInspectionMark(1);
            sectionNoDetail.setInspectionScrap(1);
            sectionNoDetailService.saveOrUpdate(sectionNoDetail);
        }
        if (null != backCuttingRecordDto.getBackcutFlag()){
            if (backCuttingRecordDto.getBackcutFlag() == 0){
               if (null != sectionNoDetail.getFacadeFrequency()){
                   productionBackCuttingRecord.setFacadeFrequency(sectionNoDetail.getFacadeFrequency() + 1);
               }else {
                   productionBackCuttingRecord.setFacadeFrequency(1);
               }
            }else if (backCuttingRecordDto.getBackcutFlag() == 1){
                if (null != sectionNoDetail.getBehaviorFrequency()){
                    productionBackCuttingRecord.setBehaviorFrequency(sectionNoDetail.getBehaviorFrequency() + 1);
                }else {
                    productionBackCuttingRecord.setBehaviorFrequency(1);
                }
            }
        }
        ProductionBackCuttingRecord save = dao.save(productionBackCuttingRecord);
        Long id = save.getId();
        if (data.size() == 0 && StringUtils.isBlank(backCuttingRecordDto.getSectionCompose())) {
            throw new RuntimeException("划线明细不能为空");
        }

        List<String> indexs = new ArrayList<>();
        if (data.size() > 0) {
            // 晶段长度
            BigDecimal barLength = backCuttingRecordDto.getBarLength();

            Integer segmentNum = sectionNoDetail.getSegmentNum();
            Integer retCutSegmentNum = 0;
            for (int i = 0; i < data.size(); i++) {
                RecutInfoDetailInfo datum = data.get(i);
                switch (datum.getType()) {
                    case "样片":
                    case "尾样片":
                        detailList.add(setLineDetail(segmentId, crystalId, id, datum, EnumValuesServer.LineType.样片.getKey(), segmentNum));
                        barLength = barLength.subtract(datum.getLength());
                        break;
                    case "晶段":
                        // 重置样片数据
                        detailList.add(setLineDetail(segmentId, crystalId, id, datum, EnumValuesServer.LineType.晶段.getKey(), segmentNum));
                        indexs.add(datum.getSegmentNo().substring(datum.getSegmentNo().length() - 1));
                        retCutSegmentNum++;
                        break;
                    case "回收料":
                        detailList.add(setLineDetail(segmentId, crystalId, id, datum, EnumValuesServer.LineType.回收料.getKey(), segmentNum));
                        barLength = barLength.subtract(datum.getLength());
                        break;
                    default:
                        throw new BusinessException("分段类型异常");
                }
            }

            productionBackCuttingRecord.setBackLength(barLength);
            // 保存反切后的晶段信息到画线晶段明细表
            this.productionPaintingLineDetailDao.saveAll(detailList);

            SectionNoDetail sectionNoDetailInitial = sectionNoDetailDao.findByCrystalIdAndSegmentNumAndParentId(sectionNoDetail.getCrystalId(), sectionNoDetail.getSegmentNum(), 0);
           /* StringBuilder indexsIndexs = new StringBuilder(StringUtils.leftPad(Integer.toBinaryString(NumberUtil.Object2Integer(sectionNoDetailInitial.getRetCutSegmentNum(), 0)), 26, "0"));
            for (String index : indexs) {
                int i = getIndexFromChar(index);
                if ("0".equals(indexsIndexs.substring(i, i + 1))) {
                    indexsIndexs.replace(i, i + 1, "1");
                } else {
                    throw new BusinessException("请重新生成编号");
                }
            }
            sectionNoDetailInitial.setRetCutSegmentNum(Integer.parseInt(indexsIndexs.toString(), 2));*/
            sectionNoDetailInitial.setRetCutSegmentNum(retCutSegmentNum);
            sectionNoDetailDao.save(sectionNoDetailInitial);
        }

        if (EnumValuesFactory.WipStorageCode.粘圆棒.getKey().equals(wipStorage.getData().getWipStorageCode())) {
            // 进入到截断工序
            wipStorageService.outStation(backCuttingRecordDto.getSegmentNo(), "A", EnumValuesFactory.WipStorageStatus.待进站.getKey());
        } else if (EnumValuesFactory.WipStorageCode.圆棒检验.getKey().equals(wipStorage.getData().getWipStorageCode())) {
            //先进站，在出站
            if (waitWipStorageStatus){
                wipStorageService.inStation(backCuttingRecordDto.getSegmentNo(),null, false);
            }
            // 进入到截断工序
            wipStorageService.outStation(backCuttingRecordDto.getSegmentNo(), "A", null, false);
        }
        //下发晶彩
        this.handleRobotSeedMessage(productionBackCuttingRecord,wipStorage.getData().getWipStorageCodeName(), sectionNoDetail);
        //todo 下发NG(反切)给wms、mcs
        //圆棒评级下发
        if (!"自动匹配".equals(backCuttingRecordDto.getUserName())) {
            List<YbInspectData> inspectList = inspectDataBaseDao.findBySectionNo(backCuttingRecordDto.getSegmentNo());
            if (inspectList != null && inspectList.size() > 0) {
                inspectList.get(0).setIsCutBack(1);
                publishRankResultService.publishRankResult(inspectList.get(0), null, null);
            }
        }
    }

    private void handleRobotSeedMessage(ProductionBackCuttingRecord productionBackCuttingRecord,String wipStorageCodeName,SectionNoDetail sectionNoDetail){
        if (null == productionBackCuttingRecord){
            return;
        }
        StringBuffer content = new StringBuffer();
        content.append(". [MES推送]晶棒损耗:").append("\n");
        content.append(". ").append(productionBackCuttingRecord.getSegmentNo()).append("\n");
        content.append(".时间：").append(DateUtil.formatDate1(productionBackCuttingRecord.getLineEndTime())).append("\n");
        content.append(".单晶损耗").append("\n");
        content.append(".损耗工序：").append("圆棒返切").append("\n");
        content.append(".损耗原因：").append(productionBackCuttingRecord.getCause()).append("\n");
        if (null != productionBackCuttingRecord.getBarLength() && null != productionBackCuttingRecord.getBackLength()){
            content.append(".损耗长度：").append(productionBackCuttingRecord.getBarLength().subtract(productionBackCuttingRecord.getBackLength())).append("\n");
        }
        content.append(".剩余长度：").append(productionBackCuttingRecord.getBackLength()).append("\n");
        content.append(".录入人：").append(productionBackCuttingRecord.getUserName()).append("\n");
        content.append(".备注：").append(StringUtils.isNotBlank(productionBackCuttingRecord.getRemark()) ? productionBackCuttingRecord.getRemark() : "").append("\n");
        ArrayList<String> sceneList = new ArrayList<>();
        ArrayList<String> groupNameList = new ArrayList<>();
        sceneList.add("prod");
        String groupName = "切方长度损耗实时推送群";
        groupNameList.add(groupName);
        String source = "晶棒损耗";
        dingTalkService.robotSeedMessage(String.valueOf(content), groupNameList, source, sceneList, SeedMassageEnum.GROUP);

        //处理损耗记录
        CrystalLossRecord crystalLossRecord = new CrystalLossRecord();
        crystalLossRecord.setSectionNo(productionBackCuttingRecord.getSegmentNo());
        if (null != productionBackCuttingRecord.getBarLength() && null != productionBackCuttingRecord.getBackLength()){
            crystalLossRecord.setLossLength(productionBackCuttingRecord.getBarLength().subtract(productionBackCuttingRecord.getBackLength()));
        }
        crystalLossRecord.setRemainLength(productionBackCuttingRecord.getBackLength());
        crystalLossRecord.setRodLength(productionBackCuttingRecord.getBarLength());
        if (null != sectionNoDetail){
            crystalLossRecord.setCrystalNo(sectionNoDetail.getCrystalNo());
            BigDecimal weightLossCoefficient = null;
            if (StringUtils.isNotBlank(sectionNoDetail.getSpecs())){
                List<DictionaryItem> dictionaryItems = dictionaryItemService.findByThemeValueAndItemName(Constants.WEIGHT_RATIO, sectionNoDetail.getSpecs(), true);
                if (!CollectionUtils.isEmpty(dictionaryItems)) {
                    weightLossCoefficient = NumberUtil.Object2BigDecimal(dictionaryItems.get(0).getValue());
                    if (null != weightLossCoefficient && weightLossCoefficient.compareTo(BigDecimal.ONE) > 0) {
                        if (null != crystalLossRecord.getLossLength()) {
                            crystalLossRecord.setLossWeight(crystalLossRecord.getLossLength().divide(weightLossCoefficient, 3, RoundingMode.HALF_UP));
                        }
                        if (null != crystalLossRecord.getRemainLength()){
                            crystalLossRecord.setRemainWeight(crystalLossRecord.getRemainLength().divide(weightLossCoefficient, 3, RoundingMode.HALF_UP));
                        }
                    }
                }
            }
            CrystalMaterialRelation crystalMaterialRelationJd = crystalMaterialRelationService.findBySectionNo(sectionNoDetail.getCrystalNo());
            if (null != crystalMaterialRelationJd){
                crystalLossRecord.setCutMachine(crystalMaterialRelationJd.getDeviceNo());
                crystalLossRecord.setMaterialCode(crystalMaterialRelationJd.getMaterialCode());
                crystalLossRecord.setOrderNo(crystalMaterialRelationJd.getOrderNo());
                if (null != crystalMaterialRelationJd.getMaterialModelId()){
                    MaterialModel materialModel = materialModelService.get(crystalMaterialRelationJd.getMaterialModelId());
                    if (null != materialModel){
                        crystalLossRecord.setMaterialName(materialModel.getName());
                    }
                }
            }

            LongCrystal longCrystal = longCrystalService.findByCrystalNo(sectionNoDetail.getCrystalNo());
            if (null != longCrystal){
                crystalLossRecord.setArea(longCrystal.getSeries());
                FactoryModel factoryModel = factoryModelService.findByCode(longCrystal.getArea());
                if (null != factoryModel){
                    crystalLossRecord.setWorkshop(factoryModel.getName());
                }
                crystalLossRecord.setSimpleName(longCrystal.getSimpleName());
            }
            //处理圆棒划线数据
            if (StringUtils.isNotBlank(sectionNoDetail.getCrystalNo())){
                ProductionPaintingLine productionPaintingLine = productionPaintingLineService.findByCrystalNo(sectionNoDetail.getCrystalNo());
                if (null != productionPaintingLine){
                    crystalLossRecord.setRodTime(productionPaintingLine.getEndTime());
                    crystalLossRecord.setRodInspector(productionPaintingLine.getUserName());
                }
            }
        }

        crystalLossRecord.setLossProcessName("圆棒返切");
        crystalLossRecord.setMajorCategories(EnumValuesFactory.CrystalLossType.SINGLE_CRYSTAL_LOSS.getValue());

        crystalLossRecord.setLossType(productionBackCuttingRecord.getCause());
        crystalLossRecord.setCreateName(productionBackCuttingRecord.getUserName());

        if (null != productionBackCuttingRecord.getLineEndTime()){
            crystalLossRecord.setCreateTime(productionBackCuttingRecord.getLineEndTime());
        }else {
            crystalLossRecord.setCreateTime(new Date());
        }
        crystalLossRecord.setOperateRemark(productionBackCuttingRecord.getRemark());
        crystalLossRecordService.saveOrUpdate(crystalLossRecord);


    }

    private static int getIndexFromChar(String str) {
        String uid = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z";
        String[] uidArray = uid.split(",");
        for (int i = 0; i < uidArray.length; i++) {
            if (str.equals(uidArray[i])) {
                return i;
            }
        }
        return 0;
    }

    @Override
    public List<SectionNoDetail> savePieceAndSectionNoDetail(ProductionBackCuttingRecord
                                                                     productionBackCuttingRecord, SectionNoDetail sectionNoDetail) {
        List<ProductionPaintingLineDetail> productionPaintingLineDetails = productionPaintingLineDetailDao.findByOperateReversecutDrawId(productionBackCuttingRecord.getId());
        if (productionPaintingLineDetails.size() > 0) {
            BigDecimal weightLossCoefficient = null;
            DefaultCrystalAttrs defaultCrystalAttrList = new DefaultCrystalAttrs();
            try {
                List<DictionaryItem> dictionaryItems = dictionaryItemService.findByThemeValueAndItemName(Constants.WEIGHT_RATIO, sectionNoDetail.getSpecs(), true);
                if (dictionaryItems.size() > 0) {
                    weightLossCoefficient = NumberUtil.Object2BigDecimal(dictionaryItems.get(0).getValue());
                    if (weightLossCoefficient == null || weightLossCoefficient.compareTo(new BigDecimal("1")) < 1) {
                        weightLossCoefficient = null;
                    }
                }
                defaultCrystalAttrList = defaultCrystalAttrService.getDefaultCrystalAttrs(sectionNoDetail.getDopant(), sectionNoDetail.getSpecs(), null);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("获取晶棒属性失败：" + e.getMessage());
            }
            // 晶段集合
            List<SectionNoDetail> segments = new ArrayList<>();
            List<PieceDetail> pieceDetails = new ArrayList<>();
            Date date = new Date();
            for (int i = 0; i < productionPaintingLineDetails.size(); i++) {
                ProductionPaintingLineDetail productionPaintingLineDetail = productionPaintingLineDetails.get(i);

                if (productionPaintingLineDetail.getType() == EnumValuesServer.LineType.样片.getKey()) {
                    PieceDetail pieceDetail = new PieceDetail();
//                    pieceDetail.setType(EnumValuesServer.SampleType.中间片.getKey());
                    pieceDetail.setPieceNo(productionPaintingLineDetail.getNo());
                    pieceDetail.setConductiveType(sectionNoDetail.getConductiveType());
                    pieceDetail.setDopant(sectionNoDetail.getDopant());
                    pieceDetail.setSpecs(sectionNoDetail.getSpecs());
                    pieceDetail.setCrystalId(sectionNoDetail.getCrystalId());
                    pieceDetail.setCrystalNo(sectionNoDetail.getCrystalNo());
                    pieceDetail.setLotNo(sectionNoDetail.getLotNo());
                    pieceDetail.setEquipmentCode(sectionNoDetail.getEquipmentCode());
                    pieceDetail.setProductType(sectionNoDetail.getProductType());
                    pieceDetail.setProductCode(sectionNoDetail.getProductCode());
                    pieceDetail.setProductGrade(sectionNoDetail.getProductGrade());
                    pieceDetail.setSegmentId(sectionNoDetail.getId());
                    pieceDetail.setCreateDate(date);
                    pieceDetail.setBackCut(EnumValuesFactory.ConfirmIdentification.YES.getValue());
                    pieceDetails.add(pieceDetail);
                } else if (productionPaintingLineDetail.getType() == EnumValuesServer.LineType.晶段.getKey() || productionPaintingLineDetail.getType() == EnumValuesServer.LineType.回收料.getKey()) {
                    SectionNoDetail sectionNoDetail1 = new SectionNoDetail();
                    //创建晶段数据
                    sectionNoDetail1.setSectionNo(productionPaintingLineDetail.getNo());
                    sectionNoDetail1.setConductiveType(sectionNoDetail.getConductiveType());
                    sectionNoDetail1.setDopant(sectionNoDetail.getDopant());
                    sectionNoDetail1.setSpecs(sectionNoDetail.getSpecs());
                    sectionNoDetail1.setCrystalNo(sectionNoDetail.getCrystalNo());
                    sectionNoDetail1.setCrystalId(sectionNoDetail.getCrystalId());
                    // 该圆棒父id则是被反切的圆棒id
                    sectionNoDetail1.setParentId(sectionNoDetail.getId());
                    sectionNoDetail1.setLotNo(sectionNoDetail.getLotNo());
                    sectionNoDetail1.setEquipmentCode(sectionNoDetail.getEquipmentCode());
                    sectionNoDetail1.setProductType(sectionNoDetail.getProductType());
                    sectionNoDetail1.setProductCode(sectionNoDetail.getProductCode());
                    sectionNoDetail1.setProductGrade(sectionNoDetail.getProductGrade());
                    sectionNoDetail1.setSegmentNum(sectionNoDetail.getSegmentNum());
                    sectionNoDetail1.setCreateUser(BaseContextHandler.getUsername());
                    sectionNoDetail1.setCreateDate(date);
                    sectionNoDetail1.setLength(productionPaintingLineDetail.getLength());
                    if (weightLossCoefficient != null) {
                        sectionNoDetail1.setWeight(productionPaintingLineDetail.getLength().divide(weightLossCoefficient, 3, RoundingMode.HALF_UP));
                    }
                    sectionNoDetail1.setPieceNoHead(null);
                    sectionNoDetail1.setPieceNoEnd(null);
                    //继承上一段头样片的信息
                    if (productionBackCuttingRecord.getIsInheritSample()) {
                        sectionNoDetail1.setPieceNoHead(sectionNoDetail.getPieceNoHead());
                    }
                    //继承上一段尾巴样片的信息
                    if (productionBackCuttingRecord.getIsInheritSample()) {
                        sectionNoDetail1.setPieceNoEnd(sectionNoDetail.getPieceNoEnd());
                    }
                    if (i - 1 >= 0 && EnumValuesServer.LineType.样片.getKey() == productionPaintingLineDetails.get(i - 1).getType()) {
                        sectionNoDetail1.setPieceNoHead(productionPaintingLineDetails.get(i - 1).getNo());
                        log.info("返切样片头日志监控：{},依赖对象：{}",JSONObject.toJSONString(sectionNoDetail1),JSONObject.toJSONString(productionPaintingLineDetails.get(i - 1)));
                    }
                    if (i + 1 < productionPaintingLineDetails.size() && EnumValuesServer.LineType.样片.getKey() == productionPaintingLineDetails.get(i + 1).getType()) {
                        sectionNoDetail1.setPieceNoEnd(productionPaintingLineDetails.get(i + 1).getNo());
                        log.info("返切样片尾日志监控：{},依赖对象：{}",JSONObject.toJSONString(sectionNoDetail1),JSONObject.toJSONString(productionPaintingLineDetails.get(i + 1)));
                    }
                    sectionNoDetail1.setSegmentNum(sectionNoDetail.getSegmentNum());
                    String type = defaultCrystalAttrService.getDefaultCrystalAttrManyTimes(defaultCrystalAttrList, sectionNoDetail1.getLength());
                    sectionNoDetail1.setSectionType(type);
                    if(productionPaintingLineDetail.getType() == EnumValuesServer.LineType.回收料.getKey()){
                        sectionNoDetail1.setSectionType(EnumValuesServer.LineType.回收料.getValue());
                    }
                    //处理是否为头尾样片依赖单晶
                    if (null == productionBackCuttingRecord.getOxygenCarbonMark()){
                        sectionNoDetail1.setOxygenCarbonMark(sectionNoDetail.getOxygenCarbonMark());
                    }else {
                        sectionNoDetail1.setOxygenCarbonMark(productionBackCuttingRecord.getOxygenCarbonMark());
                    }
                    sectionNoDetail1.setSectionPosiotion(sectionNoDetail.getSectionPosiotion());
                    // 添加处理
                    sectionNoDetail1.setReductionCrystal(productionBackCuttingRecord.getInspectionMark());
                    sectionNoDetail1.setFacadeFrequency(productionBackCuttingRecord.getFacadeFrequency());
                    sectionNoDetail1.setBehaviorFrequency(productionBackCuttingRecord.getBehaviorFrequency());
                    segments.add(sectionNoDetail1);
                }
            }
            // 保存晶段信息
            if (segments.size() > 0) {
                sectionNoDetailDao.saveAll(segments);
            }
            if (pieceDetails.size() > 0) {
                // 插入样片信息表
                this.pieceDetailDao.saveAll(pieceDetails);
            }
            return segments;
        }
        return null;
    }

    private ProductionPaintingLineDetail setLineDetail(Integer segmentId, Long crystalId, Long
            id, RecutInfoDetailInfo datum, int type, Integer segmentNum) {
        ProductionPaintingLineDetail detail1 = new ProductionPaintingLineDetail();
        detail1.setCreateTime(new Date());
        detail1.setOperateReversecutDrawId(id);
        detail1.setCrystalId(crystalId);
        detail1.setType(type);// 头样片
        detail1.setNo(datum.getSegmentNo());
        detail1.setLength(datum.getLength());
        detail1.setRemark(datum.getRemark());
        detail1.setSequence(datum.getIndex());
        detail1.setReason(datum.getReason());
        // 父级晶段
        detail1.setParentId(segmentId);
        // 反切画线
        detail1.setIsCut(0);
        // 圆棒
        detail1.setCrystalType(0);
        detail1.setSegmentNum(segmentNum);
//        detail1.setSegmentIndex(datum.getSegmentIndex());
        return detail1;
    }

    @Override
    public void deleteBackInfoDetail(Long reversecutDrawId) {
        ProductionBackCuttingRecord productionBackCuttingRecord = get(reversecutDrawId);
        if (productionBackCuttingRecord != null) {
        	
        	if(StringUtils.isNotBlank(productionBackCuttingRecord.getLogType()) && productionBackCuttingRecord.getLogType().equals("JDFQ")) {
        		//JINKO 新加逻辑 截断反切删除
        		//删除圆棒反切记录 加回划线裂纹长度
        		ProductionPaintingLineDetail lineDetail = productionPaintingLineDetailService.getDetailByNo(productionBackCuttingRecord.getSegmentNo());
        		int length = lineDetail.getLength().intValue()+lineDetail.getCrackLength().intValue();
        		lineDetail.setLength(new BigDecimal(length));
        		productionPaintingLineDetailService.saveOrUpdate(lineDetail);
        		delete(reversecutDrawId);
        	}else {
        		//正常逻辑
	            if (productionBackCuttingRecord.getStatus()) {
	                throw new BusinessException(productionBackCuttingRecord.getSegmentNo() + "该反切划线记录执行切断，不能删除");
	            }
	            if (productionBackCuttingRecord.getSectionCompose() != null && productionBackCuttingRecord.getUuid() != null) {
	                List<ProductionBackCuttingRecord> productionBackCuttingRecordList = dao.findByUuid(productionBackCuttingRecord.getUuid());
	                for (ProductionBackCuttingRecord productionBackCuttingRecord1 : productionBackCuttingRecordList) {
	                    deleteProductionBackCuttingRecord(productionBackCuttingRecord1);
	                }
	            } else {
	                deleteProductionBackCuttingRecord(productionBackCuttingRecord);
	            }
        	}
        }
    }

    @Override
    public List<ProductionBackCuttingRecord> findByUuid(String uuid) {
        return dao.findByUuid(uuid);
    }

    private void deleteProductionBackCuttingRecord(ProductionBackCuttingRecord productionBackCuttingRecord) {
        List<SectionNoDetail> sectionNoDetails = sectionNoDetailDao.findBySectionNo(productionBackCuttingRecord.getSegmentNo());
        if (sectionNoDetails.size() == 0) {
            throw new BusinessException("晶段数据不存在");
        }
        //添加判断，在检验站的不进行退站和查询操作
        List<WipStorage> wipStorageList = wipStorageService.findByProcessingByOrderCode(productionBackCuttingRecord.getSegmentNo());
        if (!CollectionUtils.isEmpty(wipStorageList)){
            WipStorage wipStorage = wipStorageList.get(0);
            if (!StringUtils.equals(wipStorage.getProcessName(),EnumValuesFactory.WipStorageCode.圆棒检验.getValue())){
                wipStorageService.selectWipStorage(productionBackCuttingRecord.getSegmentNo(), EnumValuesFactory.WipStorageCode.圆棒截断.getKey(), false);
                wipStorageService.exitStation(productionBackCuttingRecord.getSegmentNo());
            }
        }

        delete(productionBackCuttingRecord.getId());

        // 旧的数据处理逻辑
        // 2022-09-22 更改
        // 样片，晶段的信息在截断后产生，所以新的数据不用删除这信息
        List<String> segmentNoIndexs = new ArrayList<>();
        if (productionBackCuttingRecord.getIsInheritSample() == null) {
            List<String> segmentNos = this.productionPaintingLineDetailDao.findByOperateRecutDrawId(productionBackCuttingRecord.getId());
            this.productionPaintingLineDetailDao.deleteByOperateRecutDrawId(productionBackCuttingRecord.getId());
            if (segmentNos != null && segmentNos.size() > 0) {
                this.sectionNoDetailDao.deleteBySectionNoIn(segmentNos);
            }
            // 删除样片表信息
            List<PieceDetail> PieceNos = this.pieceDetailDao.findByPieceNo(segmentNos);
            if (PieceNos != null && PieceNos.size() > 0) {
                this.pieceDetailDao.deleteInBatch(PieceNos);
            }
        }
        List<ProductionPaintingLineDetail> productionPaintingLineDetails = productionPaintingLineDetailDao.findByOperateReversecutDrawId(productionBackCuttingRecord.getId());
        resetRetCutSegmentNum(sectionNoDetails, segmentNoIndexs, productionPaintingLineDetails);
    }

    /**
     * 重置最大序号
     * @param sectionNoDetails
     * @param segmentNoIndexs
     */
    public void resetRetCutSegmentNum(List<SectionNoDetail> sectionNoDetails, List<String> segmentNoIndexs, List<ProductionPaintingLineDetail> productionPaintingLineDetails) {
        for (ProductionPaintingLineDetail productionPaintingLineDetail : productionPaintingLineDetails) {
            if (productionPaintingLineDetail.getType() == EnumValuesServer.LineType.晶段.getKey()) {
                segmentNoIndexs.add(productionPaintingLineDetail.getNo().substring(productionPaintingLineDetail.getNo().length() - 1));
            }
        }
        SectionNoDetail sectionNoDetail = sectionNoDetails.get(0);
        SectionNoDetail sectionNoDetailInitial = sectionNoDetailDao.findByCrystalIdAndSegmentNumAndParentId(sectionNoDetail.getCrystalId(), sectionNoDetail.getSegmentNum(), 0);
        StringBuilder indexsIndexs = new StringBuilder(StringUtils.leftPad(Integer.toBinaryString(NumberUtil.Object2Integer(sectionNoDetailInitial.getRetCutSegmentNum(), 0)), 26, "0"));
        for (String index : segmentNoIndexs) {
            int i = getIndexFromChar(index);
            if ("1".equals(indexsIndexs.substring(i, i + 1))) {
                indexsIndexs.replace(i, i + 1, "0");
            }
        }
        sectionNoDetailInitial.setRetCutSegmentNum(Integer.parseInt(indexsIndexs.toString(), 2));
        sectionNoDetailDao.save(sectionNoDetailInitial);
    }


    @Override
    public ProductionBackCuttingRecord findBySegmentNo(String crystalNo) {
        List<ProductionBackCuttingRecord> productionBackCuttingRecordList = dao.findBySegmentNoAndStatusOrderByIdDesc(crystalNo, false);
        if (productionBackCuttingRecordList.size() > 0) {
            return productionBackCuttingRecordList.get(0);
        }
        return null;
    }

    @Override
    public List<ProductionBackCuttingRecord> findAllBySegmentNo(String crystalNo) {
        return dao.findBySegmentNoAndStatusOrderByIdDesc(crystalNo, false);
    }

    @Override
    public List<ProductionBackCuttingRecord> findAllBySegmentNo1(String crystalNo) {
        return dao.findBySegmentNo(crystalNo);
    }

    @Override
    public ProductionBackCuttingRecord findTopBySegmentNoOrderByIdDesc(String code) {
        return dao.findTopBySegmentNoOrderByIdDesc(code);
    }

    @Override
    public ProductionBackCuttingRecord findTopBySegmentNoAndStatusOrderByIdDesc(String code, boolean status) {
        List<ProductionBackCuttingRecord> productionBackCuttingRecordList = dao.findBySegmentNoAndStatusOrderByIdDesc(code, false);
        if (productionBackCuttingRecordList.size() > 0) {
            return productionBackCuttingRecordList.get(0);
        }
        return null;
    }

    @Override
    public ProductionBackCuttingRecord findOneBySegmentNoAndStatusOrderByIdDesc(String code, boolean status) {
        List<ProductionBackCuttingRecord> productionBackCuttingRecordList = dao.findBySegmentNoAndStatusOrderByIdDesc(code, status);
        if (productionBackCuttingRecordList.size() > 0) {
            return productionBackCuttingRecordList.get(0);
        }
        return null;
    }

    @Override
    public void createBackCuttingRecordV2
            (List<ProductionBackCuttingRecordDto> productionBackCuttingRecordDtos, BigDecimal
                    weightLossCoefficient, DefaultCrystalAttrs defaultCrystalAttrList, boolean isInheritSample) {
        AtomicInteger count = new AtomicInteger();
        productionBackCuttingRecordDtos.forEach(productionBackCuttingRecordDto -> {
            count.addAndGet(productionBackCuttingRecordDto.getDetail().size());
        });
        if (count.intValue() == 0 && StringUtils.isBlank(productionBackCuttingRecordDtos.get(0).getPositions())) {
            throw new BusinessException("无意义的划线");
        }
        List<String> positionsArr = new LinkedList<>();
        if (StringUtils.isNotBlank(productionBackCuttingRecordDtos.get(0).getPositions())) {
            positionsArr = Arrays.asList(productionBackCuttingRecordDtos.get(0).getPositions().split(","));
        }
        //加上拼缝切开的刀数
        for (String positions : positionsArr) {
            ProductionBackCuttingRecordDto productionBackCuttingRecordDto = productionBackCuttingRecordDtos.get(Integer.parseInt(positions) - 1);
            if (productionBackCuttingRecordDto.getDetail().size() != 0 && productionBackCuttingRecordDto.getDetail().get(productionBackCuttingRecordDto.getDetail().size() - 1).getType().equals(EnumValuesServer.LineType.回收料.getKey() + "")) {
                productionBackCuttingRecordDto.setKnifeNum(NumberUtil.Object2Integer(productionBackCuttingRecordDto.getKnifeNum(), 0) + 1);
            } else {
                productionBackCuttingRecordDto.setKnifeNum(NumberUtil.Object2Integer(productionBackCuttingRecordDto.getKnifeNum(), 0) + 2);
            }
            if (!(productionBackCuttingRecordDtos.get(Integer.parseInt(positions)).getDetail().size() != 0
                    && productionBackCuttingRecordDtos.get(Integer.parseInt(positions)).getDetail().get(0).getType().equals(EnumValuesServer.LineType.回收料.getKey() + ""))) {
                productionBackCuttingRecordDtos.get(Integer.parseInt(positions)).setKnifeNum(NumberUtil.Object2Integer(productionBackCuttingRecordDtos.get(Integer.parseInt(positions)).getKnifeNum(), 0) + 1);
            }
        }
        // 先将所有验证提前做完，再去执行保存这些消耗性能的操作
        int index = 1;
        for (ProductionBackCuttingRecordDto productionBackCuttingRecordDto : productionBackCuttingRecordDtos) {
            int segmentCount = 0;
            for (RecutInfoDetailInfo recutInfoDetailInfo : productionBackCuttingRecordDto.getDetail()) {
                if ("晶段".equals(recutInfoDetailInfo.getType())) {
                    segmentCount++;
                }
            }
            if (segmentCount == 0) {
                if (productionBackCuttingRecordDto.getDetail().size() > 0) {
                    productionBackCuttingRecordDto.setBackCutType(3);
                } else {
                    if (productionBackCuttingRecordDtos.size() == 1) {
                        throw new BusinessException("划线明细不能为空");
                    } else {
                        productionBackCuttingRecordDto.setBackCutType(2);
                    }
                }
            } else if (segmentCount == 1) {
                productionBackCuttingRecordDto.setBackCutType(0);
            } else {
                productionBackCuttingRecordDto.setBackCutType(1);
            }
            if (productionBackCuttingRecordDtos.size() > 1) {
                // 当前反切明细中
                boolean isTrueTail = productionBackCuttingRecordDto.getDetail().size() > 0 &&
                        !"晶段".equals(productionBackCuttingRecordDto.getDetail().get(productionBackCuttingRecordDto.getDetail().size() - 1).getType())
                        && index < productionBackCuttingRecordDtos.size();
                boolean isTrueHead = productionBackCuttingRecordDto.getDetail().size() > 0 &&
                        !"晶段".equals(productionBackCuttingRecordDto.getDetail().get(0).getType()) && index > 1;
                if (isTrueTail && !positionsArr.contains(index + "")) {
                    throw new BusinessException("【拼缝" + index + "】未切，不允许在" + productionBackCuttingRecordDto.getSegmentNo() + "的尾端切回收料与样片");
                }
                if (isTrueHead && !positionsArr.contains((index - 1) + "")) {
                    throw new BusinessException("【拼缝" + (index - 1) + "】未切，不允许在" + productionBackCuttingRecordDto.getSegmentNo() + "的头端切回收料与样片");
                }
                // 当单晶为分段反切时
                if (productionBackCuttingRecordDto.getBackCutType() == 1 && productionBackCuttingRecordDtos.size() > 1) {
                    // 如果第一段时，并且wei
                    if (index == 1 && !positionsArr.contains(index + "")) {
                        throw new BusinessException(productionBackCuttingRecordDto.getSegmentNo() + "为分段反切产生了新晶段，需要切开【拼缝" + index + "】");
                    }
                    if (index > 1 && productionBackCuttingRecordDtos.size() > index && !positionsArr.contains(index + "") && !positionsArr.contains((index - 1) + "")) {
                        throw new BusinessException(productionBackCuttingRecordDto.getSegmentNo() + "为分段反切产生了新晶段，需要切开【拼缝" + index + "】，【拼缝" + (index - 1) + "】");
                    }
                    if (index > 1 && productionBackCuttingRecordDtos.size() == index && !positionsArr.contains((index - 1) + "")) {
                        throw new BusinessException(productionBackCuttingRecordDto.getSegmentNo() + "为分段反切产生了新晶段，需要切开【拼缝" + (index - 1) + "】");
                    }
                }
                index++;
            }
        }
        //执行保存
        String uuid = UUID.randomUUID().toString();
        for (ProductionBackCuttingRecordDto productionBackCuttingRecordDto : productionBackCuttingRecordDtos) {
            productionBackCuttingRecordDto.setUuid(uuid);
            createBackCuttingRecord(productionBackCuttingRecordDto, weightLossCoefficient, defaultCrystalAttrList, isInheritSample);
        }
    }

    @Override
    public void createBackCuttingRecordV2New(List<ProductionBackCuttingRecordDto> productionBackCuttingRecordDtos, BigDecimal weightLossCoefficient, DefaultCrystalAttrs defaultCrystalAttrList, boolean isInheritSample) {
        AtomicInteger count = new AtomicInteger();
        productionBackCuttingRecordDtos.forEach(productionBackCuttingRecordDto -> count.addAndGet(productionBackCuttingRecordDto.getDetail().size()));
        if (count.intValue() == 0) {
            throw new BusinessException("无意义的划线");
        }
        //执行保存
        String uuid = UUID.randomUUID().toString();
        for (ProductionBackCuttingRecordDto productionBackCuttingRecordDto : productionBackCuttingRecordDtos) {
            productionBackCuttingRecordDto.setUuid(uuid);
            this.createBackCuttingRecord(productionBackCuttingRecordDto, weightLossCoefficient, defaultCrystalAttrList, isInheritSample, false,true);
        }

    }

    @Override
    public void autoCreateAppearanceCut(JSONObject text, BigDecimal weightLossCoefficient, DefaultCrystalAttrs defaultCrystalAttrList, SectionNoDetail sectionNoDetail, boolean isInheritSample) {

        List<ProductionBackCuttingRecordDto> productionBackCuttingRecordDtos = new ArrayList<>();
        //创建外观返切明细
        ProductionBackCuttingRecordDto appearanceCutDetail = createAppearanceCutDetail(text);
        productionBackCuttingRecordDtos.add(appearanceCutDetail);
        //生成外观反切编号
        getSegmentNoV2(productionBackCuttingRecordDtos);
        //创建划线
        createBackCuttingRecordV2(productionBackCuttingRecordDtos, weightLossCoefficient, defaultCrystalAttrList, isInheritSample);
    }

    public ProductionBackCuttingRecordDto createAppearanceCutDetail(JSONObject text){
        ProductionBackCuttingRecordDto productionBackCuttingRecordDto = new ProductionBackCuttingRecordDto();
        JSONObject params = text.getJSONObject("params");
        String sectionNo = params.getString("sectionNo");
        Result<LinkedList<RecordSegmentNoInfoDto>> segmentNoInfoBySectionNoV2 = findSegmentNoInfoBySectionNoV2(sectionNo);
        LinkedList<RecordSegmentNoInfoDto> data = segmentNoInfoBySectionNoV2.getData();
        productionBackCuttingRecordDto.setUserName("MCS");
        productionBackCuttingRecordDto.setLineStartTime(new Date());
        //晶棒长度
        if(!CollectionUtils.isEmpty(data)){
            RecordSegmentNoInfoDto recordSegmentNoInfoDto = data.get(0);
            productionBackCuttingRecordDto.setBarLength(recordSegmentNoInfoDto.getLength());

            productionBackCuttingRecordDto.setSegmentNo(sectionNo);
            productionBackCuttingRecordDto.setSegmentId(recordSegmentNoInfoDto.getSegmentId());
        }
        //获取反切原因
        String cutCause = getCutCause(params, productionBackCuttingRecordDto);

        //返切刀数
        productionBackCuttingRecordDto.setKnifeNum(Constants.NUMBER_OF_CUTS);
        //需切开的拼缝
        productionBackCuttingRecordDto.setPositions(null);

        //返切明细
        List<RecutInfoDetailInfo> detail = createDetail(params, cutCause, Constants.NUMBER_OF_CUTS);
        productionBackCuttingRecordDto.setDetail(detail);

        //上传外观异常数据---用于评级
        YbInspectDataCUDto ybInspectDataCUDto = new YbInspectDataCUDto();
        if(cutCause.equals("yinlie")){
            ybInspectDataCUDto.setCheckReback(Constants.CRACK);
        } else {
            ybInspectDataCUDto.setCheckReback(Constants.DISLOCATION);
        }
        ybInspectDataCUDto.setSectionNo(sectionNo);
//        ybInspectDataCUDto.setDistortion(new BigDecimal(0));
//        ybInspectDataCUDto.setCollapseLine(new BigDecimal(0));
//        ybInspectDataCUDto.setEdgeBark(new BigDecimal(0));
        ybInspectDataService.saveYbInspectData(ybInspectDataCUDto);

        return productionBackCuttingRecordDto;
    }

    public  List<RecutInfoDetailInfo> createDetail(JSONObject params, String cutCause, Integer num){
        List<RecutInfoDetailInfo> detail = new ArrayList<>();
        for (int i = num; i >= 0; i--) {
            RecutInfoDetailInfo recutInfoDetailInfo = new RecutInfoDetailInfo();
            recutInfoDetailInfo.setIndex(i);
            recutInfoDetailInfo.setSegmentNo(null);

            if(i != 0){
                recutInfoDetailInfo.setType(Constants.REC_MATERIALS);
                recutInfoDetailInfo.setLength(new BigDecimal((int)Math.floor(params.getDoubleValue(cutCause) + 0.5)));
            } else {
                recutInfoDetailInfo.setType(Constants.CRYSTAL_SEGMENT);
                int length = (int)Math.floor(params.getDoubleValue("length") + 0.5);
                recutInfoDetailInfo.setLength(new BigDecimal(length - (int)Math.floor(params.getDoubleValue(cutCause) + 0.5)));
            }
            detail.add(recutInfoDetailInfo);
        }
        return detail;
    }

    public String getCutCause(JSONObject text, ProductionBackCuttingRecordDto productionBackCuttingRecordDto){

//        Integer yinlie = text.getInteger("yinlie");
//        Integer weicuo = text.getInteger("weicuo");

        int yinlie = (int)Math.floor(text.getDoubleValue("yinlie") + 0.5);
        int weicuo = (int)Math.floor(text.getDoubleValue("weicuo") + 0.5);

        if(yinlie > weicuo){
            productionBackCuttingRecordDto.setCause(Constants.CRACK);
            return "yinlie";
        } else {
            productionBackCuttingRecordDto.setCause(Constants.DISLOCATION);
            return "weicuo";
        }
    }

    public ProductionBackCuttingRecord fromDto(ProductionBackCuttingRecordDto dto) {
        return modelMapper.map(dto, ProductionBackCuttingRecord.class);
    }

    @Override
    public Result<String> execProductionBackCuttingRecord(YbInspectData ybInspectData) {
        SysLog sysLog = new SysLog();
        sysLog.setCreateTime(new Date());
        sysLog.setCreateUserName(BaseContextHandler.getUsername());
        sysLog.setCreateUserId(BaseContextHandler.getUserID());
        sysLog.setName(ybInspectData.getSectionNo() + "反切划线：" + ybInspectData.getProductLevel() + "/" + ybInspectData.getGradeData());
        try {
            // 检验数据提交判断是否在圆棒检验已进站状态
            String dataRule = ybInspectData.getGradeData();
            Result<CurrentWipStorageStatusDto> wipStorage = wipStorageService.selectWipStorageResult(ybInspectData.getSectionNo());
            // 当前在截断待进站，圆棒检验进站状态才执行反切
            boolean isOkCut = (EnumValuesFactory.WipStorageCode.圆棒截断.getKey().equals(wipStorage.getData().getWipStorageCode())
                    && wipStorage.getData().getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.待进站.getKey())
                    || (EnumValuesFactory.WipStorageCode.圆棒检验.getKey().equals(wipStorage.getData().getWipStorageCode())
                    && wipStorage.getData().getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.已进站.getKey());
            if (isOkCut) {
                // 当前在截断待进站，删除自动划线数据
                List<ProductionBackCuttingRecord> productionBackCuttingRecords = findAllBySegmentNo(ybInspectData.getSectionNo());
                if (productionBackCuttingRecords.size() > 0) {
                    for (ProductionBackCuttingRecord productionBackCuttingRecord : productionBackCuttingRecords) {
                        deleteProductionBackCuttingRecord(productionBackCuttingRecord);
                    }
                }
                Result<CurrentWipStorageStatusDto> wipStorage1 = wipStorageService.selectWipStorageResult(ybInspectData.getSectionNo());
                if (EnumValuesFactory.WipStorageCode.圆棒截断.getKey().equals(wipStorage1.getData().getWipStorageCode()) && (StringUtils.isBlank(dataRule) || "null".equals(dataRule))) {

                    wipStorageService.outStation(ybInspectData.getSectionNo(), "A", null, false);
                    //wipStorageService.exitStation(ybInspectData.getSectionNo());
                }

                if (StringUtils.isNotBlank(dataRule) && !"null".equals(dataRule)) {
                    // 返切的晶段在评级时，不取样片时，样片的数据需要继承返切前的数据,重新保存评级
                    ProductionBackCuttingRecordDto recutDto = new ProductionBackCuttingRecordDto();

                    this.handleOxygenCarbonMark(recutDto,ybInspectData);
                    // 画线开始时间
                    recutDto.setLineStartTime(new Date());
                    recutDto.setUserName("自动匹配");
                    recutDto.setCause(ybInspectData.getProductLevel());
                    BigDecimal length = ybInspectData.getActualLength();
                    // 用晶段编号去画线记录明细表找到对应的长度信息
                    recutDto.setBarLength(length);
                    if (dataRule.contains("Y")) {
                        // 是否取样片
                        recutDto.setIsTakeSample(1L);
                    }
                    // 解析返切规则数据
                    List<RecutInfoDetailInfo> recutRule = getRecutRule(dataRule, length);
                    List<RecutInfoDetailInfo> sortList = recutRule.stream().sorted(Comparator.comparing(RecutInfoDetailInfo::getIndex)).collect(Collectors.toList());
                    // 返切刀数
                    recutDto.setKnifeNum(sortList.size() - 1);

                    // 生成新晶段编号,集合 用来保存画线数据
                    ProductionBackCuttingRecordDto productionBackCuttingRecordDto = new ProductionBackCuttingRecordDto();
                    productionBackCuttingRecordDto.setSegmentNo(ybInspectData.getSectionNo());
                    productionBackCuttingRecordDto.setDetail(sortList);
                    ArrayList<ProductionBackCuttingRecordDto> productionBackCuttingRecordDtos = new ArrayList<>();
                    productionBackCuttingRecordDtos.add(productionBackCuttingRecordDto);
                    getSegmentNoV2(productionBackCuttingRecordDtos);
                    // 保存自动画线信息
                    recutDto.setLineEndTime(new Date());
                    recutDto.setSegmentNo(ybInspectData.getSectionNo());
                    recutDto.setDetail(productionBackCuttingRecordDto.getDetail());
                    recutDto.setBackCutType(productionBackCuttingRecordDto.getBackCutType());

                    BigDecimal weightLossCoefficient = null;
                    DefaultCrystalAttrs defaultCrystalAttrList = new DefaultCrystalAttrs();
                    try {
                        List<DictionaryItem> dictionaryItems = dictionaryItemService.findByThemeValueAndItemName(Constants.WEIGHT_RATIO, ybInspectData.getProductTypeSecond(), true);
                        if (dictionaryItems.size() > 0) {
                            weightLossCoefficient = NumberUtil.Object2BigDecimal(dictionaryItems.get(0).getValue());
                            if (weightLossCoefficient == null || weightLossCoefficient.compareTo(new BigDecimal("1")) < 1) {
                                weightLossCoefficient = null;
                            }
                        }
                        defaultCrystalAttrList = defaultCrystalAttrService.getDefaultCrystalAttrs(ybInspectData.getDopant(), ybInspectData.getProductTypeSecond(), null);
                    } catch (Exception e) {
                        log.error("e：", e);
                    }
                    createBackCuttingRecord(recutDto, weightLossCoefficient, defaultCrystalAttrList, "反切".equals(ybInspectData.getGradeType()), true,false);
                    sysLog.setContent("当前在" + wipStorage.getData().getWipStorageCode() + "的" + EnumValuesFactory.WipStorageStatus.getText(wipStorage.getData().getWipStorageStatus())
                            + "状态，反切划线信息生成成功，反切数据为：" + dataRule);
                } else {
                    sysLog.setContent("当前在" + wipStorage.getData().getWipStorageCode() + "的" + EnumValuesFactory.WipStorageStatus.getText(wipStorage.getData().getWipStorageStatus())
                            + "状态，无需生产反切划线信息，反切数据为：" + dataRule);
                }
            } else {
                sysLog.setContent("当前在" + wipStorage.getData().getWipStorageCode() + "的" + EnumValuesFactory.WipStorageStatus.getText(wipStorage.getData().getWipStorageStatus())
                        + "状态，不生成划线记录");
            }
        } catch (Exception e) {
            sysLog.setContent("反切划线信息生成失败" + e.getMessage());
            log.error("反切划线信息生成失败：", e);
//            throw new BusinessException("反切划线信息生成失败，" + e.getMessage());
            return ResultGenerator.fail("反切划线信息生成失败，" + e.getMessage());
        }
        sysLogService.save(sysLog);
        return ResultGenerator.success("操作成功");
    }

    @Override
    public ProductionBackCuttingRecord findBySectionNo(String segmentNo) {
        return dao.findBySectionNo(segmentNo);
    }

    private void handleOxygenCarbonMark(ProductionBackCuttingRecordDto productionBackCuttingRecordDto,YbInspectData ybInspectData){
        if (null == productionBackCuttingRecordDto || null == ybInspectData || StringUtils.isBlank(ybInspectData.getSectionNo())){
            return;
        }
        String sectionNo = ybInspectData.getSectionNo();
        //默认检验字段值，前一段为回收料时，并且本段氧碳为0时该段为头段依赖
        productionBackCuttingRecordDto.setOxygenCarbonMark(ybInspectData.getOxygenCarbonMark());
        if (!sectionNo.endsWith("T") && !sectionNo.endsWith("A")){
            if (StringUtils.isBlank(ybInspectData.getCrystalNo())){
                return;
            }
            if (null != ybInspectData.getPiecewiseNum()){
                //先查询头段是否未回收料
                YbInspectData ybInspectDataHead = ybInspectDataService.findBySectionNo(ybInspectData.getCrystalNo() + "T");
                if (null != ybInspectDataHead && StringUtils.equals(ybInspectDataHead.getGradeType(),"回收料")){
                    SectionNoDetail sectionPosiotionSectionNoDetail = sectionNoDetailDao.findByCrystalNoAndSectionPosiotion(ybInspectData.getCrystalNo(), ybInspectData.getPiecewiseNum() - 1);
                    if (null != sectionPosiotionSectionNoDetail){
                        YbInspectData bySectionNo = ybInspectDataService.findBySectionNo(sectionPosiotionSectionNoDetail.getSectionNo());
                        if (null != bySectionNo && StringUtils.equals(bySectionNo.getGradeType(),"回收料") &&
                                null != bySectionNo.getOxygenCarbonMark() && bySectionNo.getOxygenCarbonMark() >= 1){
                            productionBackCuttingRecordDto.setOxygenCarbonMark(EnumValuesFactory.OxygenCarbonMarkStatus.HEAD_DEPEND.getKey());
                        }
                    }
                }
            }
        }
    }


    // 解析圆棒自动返切规则数据
    public List<RecutInfoDetailInfo> getRecutRule(String dataRule, BigDecimal totalLength) {
        List<RecutInfoDetailInfo> lines = new ArrayList<>();
        //BigDecimal totalLength = NumberUtil.Object2BigDecimal("320");
        // String a = "H:180,Y:30,J:X";

        // String b = "H:180,Y:X,J:X";

        //  String c = "H:X,Y:X,J:X"; 返切格式

        String[] split = dataRule.split(",");
        List<String> ruleList = Arrays.asList(split);
        LinkedList<RecutRuleDto> linkedList = new LinkedList<>();

        try {
            for (int i = 0; i < ruleList.size(); i++) {

                // 规则排序 ,将X的数据信息放到集合末尾,用作平均数余数计算
                if (ruleList.get(i).contains("X")) {
                    RecutRuleDto recutRuleDto = new RecutRuleDto();
                    recutRuleDto.setIndex(i + 1);
                    recutRuleDto.setRuleData(ruleList.get(i));
                    linkedList.addLast(recutRuleDto);
                } else {
                    RecutRuleDto recutRuleDto = new RecutRuleDto();
                    recutRuleDto.setIndex(i + 1);
                    recutRuleDto.setRuleData(ruleList.get(i));
                    linkedList.addFirst(recutRuleDto);
                }

            }
        } catch (Exception e) {
            throw new RuntimeException("自动画线返切规则解析出错");
        }
        int size = linkedList.size();

        // 被除平均数
        BigDecimal average = new BigDecimal(Integer.valueOf(size).toString());

        // 计算出来每一段信息相加
        BigDecimal sumLength = null;

        BigDecimal pieceLength = new BigDecimal("0.00");

        try {
            for (int i = 0; i < linkedList.size(); i++) {

                RecutInfoDetailInfo recutInfoDetailInfo = new RecutInfoDetailInfo();
                if (linkedList.get(i).getRuleData().contains(EnumValuesServer.RecutYbRule.回收料.getValue())) {
                    recutInfoDetailInfo.setType(EnumValuesServer.RecutYbRule.回收料.getKey());
                    String[] split1 = linkedList.get(i).getRuleData().split(":");
                    for (String s : split1) {
                        if (s.equals("H")) {
                            continue;
                        }
                        if (!s.equals("X")) {
                            recutInfoDetailInfo.setLength(new BigDecimal(s));
                            recutInfoDetailInfo.setIndex(linkedList.get(i).getIndex());
                            sumLength = pieceLength.add(new BigDecimal(s));
                            totalLength = totalLength.subtract(sumLength);
                            // 不做平均数计算也要减1 防止后续为X 数据不准确
                            average = average.subtract(new BigDecimal("1"));
                        } else {
                            recutInfoDetailInfo.setLength(totalLength.divide(average, 2, BigDecimal.ROUND_HALF_UP));
                            recutInfoDetailInfo.setIndex(linkedList.get(i).getIndex());
                            totalLength = totalLength.subtract(totalLength.divide(average, 2, BigDecimal.ROUND_HALF_UP));
                            //平均数减1
                            average = average.subtract(new BigDecimal("1"));
                            // sumLength = pieceLength.add(new BigDecimal(s));
                        }

                    }
                }

                if (linkedList.get(i).getRuleData().contains(EnumValuesServer.RecutYbRule.样片.getValue())) {
                    recutInfoDetailInfo.setType(EnumValuesServer.RecutYbRule.样片.getKey());
                    String[] split1 = linkedList.get(i).getRuleData().split(":");
                    for (String s : split1) {
                        if (s.equals("Y")) {
                            continue;
                        }
                        if (!s.equals("X")) {
                            recutInfoDetailInfo.setLength(new BigDecimal(s));
                            recutInfoDetailInfo.setIndex(linkedList.get(i).getIndex());
                            sumLength = pieceLength.add(new BigDecimal(s));
                            totalLength = totalLength.subtract(sumLength);
                            // 不做平均数计算也要减1防止后续为X 数据不准确
                            average = average.subtract(new BigDecimal("1"));
                        } else {
                            recutInfoDetailInfo.setLength(new BigDecimal(totalLength.divide(average, 2, BigDecimal.ROUND_HALF_UP).toString()));
                            recutInfoDetailInfo.setIndex(linkedList.get(i).getIndex());
                            totalLength = totalLength.subtract(new BigDecimal(totalLength.divide(average, 2, BigDecimal.ROUND_HALF_UP).toString()));
                            //平均数减1
                            average = average.subtract(new BigDecimal("1"));
                        }
                    }
                }

                if (linkedList.get(i).getRuleData().contains(EnumValuesServer.RecutYbRule.晶段.getValue())) {
                    recutInfoDetailInfo.setType(EnumValuesServer.RecutYbRule.晶段.getKey());
                    String[] split1 = linkedList.get(i).getRuleData().split(":");
                    for (String s : split1) {
                        if (s.equals("J")) {
                            continue;
                        }
                        if (!s.equals("X")) {
                            recutInfoDetailInfo.setLength(new BigDecimal(s));
                            recutInfoDetailInfo.setIndex(linkedList.get(i).getIndex());
                            sumLength = pieceLength.add(new BigDecimal(s));
                            // 不做平均数计算也要减1防止后续为X 数据不准确
                            average = average.subtract(new BigDecimal("1"));
                            totalLength = totalLength.subtract(sumLength);
                        } else {

                            recutInfoDetailInfo.setLength(new BigDecimal(totalLength.divide(average, 2, BigDecimal.ROUND_HALF_UP).toString()));
                            recutInfoDetailInfo.setIndex(linkedList.get(i).getIndex());
                            totalLength = totalLength.subtract(new BigDecimal(totalLength.divide(average, 2, BigDecimal.ROUND_HALF_UP).toString()));
                            //平均数减1
                            average = average.subtract(new BigDecimal("1"));
                        }

                    }
                }

                System.out.println(recutInfoDetailInfo.toString());
                lines.add(recutInfoDetailInfo);

            }
        } catch (Exception e) {
            throw new RuntimeException("自动画线圆棒返切规则解析出错");
        }
        return lines;
    }


}
