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


import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import com.sw.mes.core.enums.SectionIndexRangeEnum;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sw.mes.base.factory.inspect.service.DefaultCrystalAttrService;
import com.sw.mes.base.system.entity.DictionaryItem;
import com.sw.mes.base.system.service.DictionaryItemService;
import com.sw.mes.base.system.service.InventoryManageInfoService;
import com.sw.mes.base.workinprocess.dto.CurrentWipStorageStatusDto;
import com.sw.mes.base.workinprocess.entity.PlanProcessingOrder;
import com.sw.mes.base.workinprocess.service.PlanProcessingOrderService;
import com.sw.mes.base.workinprocess.service.WipStorageService;
import com.sw.mes.core.api.system.FbFeignClients;
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.dto.RankResultDto;
import com.sw.mes.core.dto.mes.pc.yb.ProductionBindingTrayDto;
import com.sw.mes.core.enums.EnumValuesFactory;
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.NumberUtil;
import com.sw.mes.core.utils.StringUtils;
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.yb.fls.service.FlsToMesService;
import com.sw.mes.yb.mcs.dto.CrystalTrayBindInfoDto;
import com.sw.mes.yb.mcs.dto.CrystalTrayUnBindInfoDto;
import com.sw.mes.yb.mcs.dto.SpellBindingDto;
import com.sw.mes.yb.mcs.event.EventPublishService;
import com.sw.mes.yb.mcs.event.RankResultEvent;
import com.sw.mes.yb.mcs.service.YbMesToMcsService;
import com.sw.mes.yb.mcs.utils.ResultDto;
import com.sw.mes.yb.pad.entity.ProductionBackCuttingRecord;
import com.sw.mes.yb.pad.entity.SectionNoDetail;
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.pc.entity.Section;
import com.sw.mes.yb.pc.service.SectionService;
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.dto.BindingCrystalDto;
import com.sw.mes.yb.turnstore.dto.BindingVerifyDto;
import com.sw.mes.yb.turnstore.dto.ManualCallDto;
import com.sw.mes.yb.turnstore.entity.ProductionBindingTray;
import com.sw.mes.yb.turnstore.entity.ProductionBindingTrayLog;
import com.sw.mes.yb.turnstore.service.ProductionBindingTrayLogService;
import com.sw.mes.yb.turnstore.service.ProductionBindingTrayService;

import lombok.extern.slf4j.Slf4j;


/**
 * @Author
 * @Description：
 * @Date: Create in
 * @Modified By:
 */
@Service
@Slf4j
@Transactional
public class ProductionBindingTrayServiceImpl extends BaseServiceImpl<ProductionBindingTray> implements ProductionBindingTrayService {

    @Value("${spring.profiles.active}")
    private String active;

    ProductionBindingTrayDao dao;

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

    @Autowired
    private ModelMapper modelMapper;


    @Autowired
    private ProductionBindingTrayLogService productionBindingTrayLogService;

    @Autowired
    private LongCrystalService longCrystalService;

    @Autowired
    private WipStorageService wipStorageService;

    @Autowired
    private DictionaryItemService dictionaryItemService;
    /**
     * 晶段信息service
     */
    @Autowired
    private SectionNoDetailService sectionNoDetailService;

    /**
     * 画线信息service
     */
    @Autowired
    private ProductionPaintingLineService productionPaintingLineService;
    /**
     * 画线/反切画线信息详情service
     */
    @Autowired
    private ProductionPaintingLineDetailService productionPaintingLineDetailService;
    /**
     * 反切画线信息service
     */
    @Autowired
    private ProductionRecutService productionRecutService;
    /**
     * 加工工单service
     */
    @Autowired
    private PlanProcessingOrderService planProcessingOrderService;

    @Autowired
    private YbInspectDataService ybInspectDataService;

    @Autowired
    private FlsToMesService flsToMesService;

    @Autowired
    private YbMesToMcsService ybMesToMcsService;

    @Autowired
    private DefaultCrystalAttrService defaultCrystalAttrService;


    @Autowired
    private YbInspectDataService inspectDataBaseService;

    @Autowired
    private InventoryManageInfoService inventoryManageInfoService;

    @Autowired
    @Lazy
    private FbFeignClients fbFeignClients;

    @Autowired
    @Qualifier("eventPublishService")
    private EventPublishService publishService;

    @Autowired
    private SectionService sectionService;

    @Override
    public List<String> findCrystalNoByTrayNo(String trayNo) {
        List<String> crystalNoByTrayNo = this.dao.findCrystalNoByTrayNo(trayNo);
        return crystalNoByTrayNo;
    }

    @Override
    public List<ProductionBindingTray> findCrystalNoByTrayNoV2(String trayNo) {
        return dao.findCrystalNoByTrayNoV2(trayNo);
    }

    @Override
    public ProductionBindingTray getByTrayNoAndLocationNo(String pailNum, String locationNo) {
        return dao.getByTrayNoAndLocationNo(pailNum, locationNo);
    }

    @Override
    public Result bindingCrystal(ProductionBindingTrayDto dto) {
        if (StringUtils.isBlank(dto.getTrayNo())) {
            return ResultGenerator.fail("载具编号不能为空，请检查...");
        }

        String trayNo = dto.getTrayNo().toUpperCase();
        if (trayNo.startsWith("TPT")) {//回收料
            return this.bindingRecycledMaterial(dto);
        } else {
            //如果是反切不要生成检验数据，人工绑定根据外观情况决定要不要生成检验数据
            String point = dto.getPoint();
            if (StringUtils.equals(point, "6.JD")) {
                return this.bindingSection2(dto);
            } else if (StringUtils.equals(point, "2.YJY")) {
                return this.bindingSection(dto);
            } else {
                return this.bindingSection2(dto);
            }
        }
    }

    @Override
    public Result bindingCrystalVerify(ProductionBindingTrayDto dto) {
        if (StringUtils.isBlank(dto.getTrayNo())) {
            return ResultGenerator.fail("载具编号不能为空，请检查...");
        }

        String trayNo = dto.getTrayNo().toUpperCase();
        if (trayNo.startsWith("TPT")) {//回收料
            this.bindingRecycledMaterialVerify(dto);
            return ResultGenerator.success("可以绑定！");
        } else {
            this.bindingSectionVerify(dto);
            return ResultGenerator.success("可以绑定！");
        }
    }


    //晶段晶棒绑定
    public Result bindingSection(ProductionBindingTrayDto dto) {

        //校验绑定
        BindingVerifyDto bindingVerifyDto = this.bindingSectionVerify(dto);

        ProductionBindingTray productionBindingTray = fromDto(bindingVerifyDto.getDto());
        productionBindingTray.setBindingTime(new Date());
        this.dao.save(productionBindingTray);

        // 写入载具绑定记录表
        ProductionBindingTrayLog log = new ProductionBindingTrayLog();
        log.setBindingPeople(dto.getBindingPeople());
        log.setIsBinding(productionBindingTray.getIsBinding());
        log.setCrystalNo(dto.getCrystalNo());
        log.setGmtCreate(new Date());
        log.setBindingTime(productionBindingTray.getBindingTime());
        log.setTrayNo(dto.getTrayNo());
        log.setLocationNo(dto.getLocationNo());
        log.setClassName(dto.getClassName());
        log.setClassnoname(dto.getClassNoName());
        log.setBindingSite(dto.getBindingSite());
        productionBindingTrayLogService.saveOrUpdate(log);

        //圆棒手动入库点位 发送给mcs
        if ("4.YJY".equals(bindingVerifyDto.getOldPoint())) {
            ManualCallDto manualCallDto = new ManualCallDto();
            manualCallDto.setPoint(bindingVerifyDto.getOldPoint());
            manualCallDto.setCrystalNo(dto.getCrystalNo());
            //人工入库任务
            ResultDto resultDto = ybMesToMcsService.addManualCall(manualCallDto);
            if (resultDto.getCode() != 200) {
                throw new BusinessException("圆棒手动入库点位,下发MCS失败！：" + resultDto.getMessage());
            }
        }

        //非自动绑定
        if (dto.getIsBinding() != 0) {
            //圆棒直发绑定点位，推送mcs绑定信息
            this.dealWithSend(dto, bindingVerifyDto.getOldPoint(), bindingVerifyDto.getSectionNoDetail(), bindingVerifyDto.getInspectDataBase());
        }

        //是非标加工时，重新匹配方棒订单
        if ("3.YJY".equals(bindingVerifyDto.getOldPoint()) && dto.getStandard() != null && dto.getStandard().equals("1")) {
            this.zfPublishRankResult(bindingVerifyDto.getInspectDataBase());
        }
        return ResultGenerator.success();
    }


    /**
     * 圆棒下料绑定时，同时生成一条圆棒检验数据，保存外观检验信息
     *
     * @param dto
     * @return
     */
    //晶段晶棒绑定
    public Result bindingSection2(ProductionBindingTrayDto dto) {
        log.info("人工-圆棒托盘绑定信息，编号为[{}], 点位为", dto.getCrystalNo(), dto.getPoint());
        //校验绑定
        BindingVerifyDto bindingVerifyDto = this.bindingSectionVerify(dto);

        ProductionBindingTray productionBindingTray = fromDto(bindingVerifyDto.getDto());
        productionBindingTray.setBindingTime(new Date());
        this.dao.save(productionBindingTray);

        // 写入载具绑定记录表
        ProductionBindingTrayLog productionBindingTrayLog = new ProductionBindingTrayLog();
        productionBindingTrayLog.setBindingPeople(dto.getBindingPeople());
        productionBindingTrayLog.setIsBinding(productionBindingTray.getIsBinding());
        productionBindingTrayLog.setCrystalNo(dto.getCrystalNo());
        productionBindingTrayLog.setGmtCreate(new Date());
        productionBindingTrayLog.setBindingTime(productionBindingTray.getBindingTime());
        productionBindingTrayLog.setTrayNo(dto.getTrayNo());
        productionBindingTrayLog.setLocationNo(dto.getLocationNo());
        productionBindingTrayLog.setClassName(dto.getClassName());
        productionBindingTrayLog.setClassnoname(dto.getClassNoName());
        productionBindingTrayLog.setBindingSite(dto.getBindingSite());
        productionBindingTrayLogService.saveOrUpdate(productionBindingTrayLog);

        //圆棒手动入库点位 发送给mcs
        if ("4.YJY".equals(bindingVerifyDto.getOldPoint())) {
            ManualCallDto manualCallDto = new ManualCallDto();
            manualCallDto.setPoint(bindingVerifyDto.getOldPoint());
            manualCallDto.setCrystalNo(dto.getCrystalNo());
            //人工入库任务
            ResultDto resultDto = ybMesToMcsService.addManualCall(manualCallDto);
            if (resultDto.getCode() != 200) {
                throw new BusinessException("圆棒手动入库点位,下发MCS失败！：" + resultDto.getMessage());
            }
        }

        //生成晶棒检验数据
        try {
            if(!StringUtils.contains(dto.getPoint(), "HX")){
                createYbData(dto);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("绑定托盘时创建圆棒数据异常：" + e.getMessage());
        }

        //圆棒直发绑定点位，推送mcs绑定信息
        this.dealWithSend(dto, bindingVerifyDto.getOldPoint(), bindingVerifyDto.getSectionNoDetail(), bindingVerifyDto.getInspectDataBase());

        //是非标加工时，重新匹配方棒订单
        if ("3.YJY".equals(bindingVerifyDto.getOldPoint()) && dto.getStandard() != null && dto.getStandard().equals("1")) {
            this.zfPublishRankResult(bindingVerifyDto.getInspectDataBase());
        }

        return ResultGenerator.success();
    }

    public Result createYbData(ProductionBindingTrayDto dto) {
        YbInspectDataCUDto ybInspectDataCUDto = new YbInspectDataCUDto();
        YbInspectDataCUDto ybInspectDataDto = ybInspectDataService.getYbInspectDataDto(dto.getCrystalNo());
        String fromMark =dto.getCrystalNo().substring(SectionIndexRangeEnum.基地追溯产品类型.getBeginIndex(), SectionIndexRangeEnum.基地追溯产品类型.getEndIndex());
        LongCrystal byCrystalNo = null;
        if (fromMark.matches("[A-Z]+")) {
            byCrystalNo = longCrystalService.findByCrystalNo(dto.getCrystalNo().substring(SectionIndexRangeEnum.毛棒范围.getBeginIndex(), SectionIndexRangeEnum.毛棒范围.getEndIndex()));
        } else {
            byCrystalNo = longCrystalService.findByCrystalNo(dto.getCrystalNo().substring(0, 12));
        }
        if (ybInspectDataDto == null) {
            throw new RuntimeException("晶棒信息不存在！");
        }
        if (byCrystalNo == null) {
            throw new RuntimeException("晶棒信息不存在！");
        }
        ybInspectDataCUDto.setSectionNo(ybInspectDataDto.getSectionNo());
        ybInspectDataCUDto.setActualLength(ybInspectDataDto.getActualLength());
        ybInspectDataCUDto.setProductTypeSecond(ybInspectDataDto.getProductTypeSecond());
        ybInspectDataCUDto.setDopant(ybInspectDataDto.getDopant());
        ybInspectDataCUDto.setConductiveType(ybInspectDataDto.getConductiveType());
        ybInspectDataCUDto.setDiameterMin(ybInspectDataDto.getDiameterMin());
        ybInspectDataCUDto.setDiameterMax(ybInspectDataDto.getDiameterMax());
        ybInspectDataCUDto.setDistortion(ybInspectDataDto.getDistortion());
        ybInspectDataCUDto.setEdgeBark(ybInspectDataDto.getEdgeBark());
        ybInspectDataCUDto.setCrack(ybInspectDataDto.getCrack());
        ybInspectDataCUDto.setCheckReback(dto.getCheckReback());
        ybInspectDataCUDto.setSlopeLength(ybInspectDataCUDto.getSlopeLength());
        ybInspectDataCUDto.setClosureIdentification(byCrystalNo.getClosureIdentification());
        //截断下料绑定生成圆棒检验数据的，也赋值方棒边长字段
        ybInspectDataCUDto.setSideLengthRange(byCrystalNo.getSideLengthRange());
        return ybInspectDataService.saveYbInspectData(ybInspectDataCUDto);
    }


    public BindingVerifyDto bindingSectionVerify(ProductionBindingTrayDto dto) {
        BindingVerifyDto bindingVerifyDto = new BindingVerifyDto();
        String oldPoint = dto.getPoint();

        //如果载具工位为空，或者载具为托盘，则默认载具工位1
        if (StringUtils.isBlank(dto.getTrayNo())) {
            throw new BusinessException("载具编号不能为空，请检查...");
        }

        if (dto.getTrayNo().toUpperCase().startsWith("TP") || StringUtils.isBlank(dto.getLocationNo())) {
            dto.setLocationNo("1");
        }

        //单晶集合
        List<String> listSectionNo = new ArrayList<>();
        YbInspectData inspectDataBase = inspectDataBaseService.findBySectionNo(dto.getCrystalNo());
        if (inspectDataBase != null) {
            if (inspectDataBase.getSticksCount() != null && inspectDataBase.getSticksCount() > 1) {
                listSectionNo = Arrays.asList(inspectDataBase.getSectionCompose().split(","));
                //获取拼棒信息
                Section section = sectionService.findBySectionNo(dto.getCrystalNo());
                if (section != null && section.getSectionNo() != dto.getCrystalNo()) {
                    dto.setCrystalNo(section.getSectionNo());
                    inspectDataBase = inspectDataBaseService.findBySectionNo(section.getSectionNo());
                }
            } else {
                listSectionNo.add(inspectDataBase.getSectionNo());
            }
        } else {
            listSectionNo.add(dto.getCrystalNo());
        }

        for (String sectionNo : listSectionNo) {
            //查询工单是否为组托状态，组托状态下不允许绑定托盘
            PlanProcessingOrder planProcessingOrder = planProcessingOrderService.findByCode(sectionNo);
            if (planProcessingOrder == null) {
                throw new BusinessException("【" + sectionNo + "】编号不存在，请检查...");
            }
            if (planProcessingOrder.getStatus() == EnumValuesFactory.PlanProcessingOrderStatus.组托.getKey()) {
                throw new BusinessException("单晶【" + sectionNo + "】已在" + EnumValuesFactory.PlanProcessingOrderStatus.组托.getValue() + "状态，不允许绑定托盘。");
            }

            List<ProductionBindingTray> productionBindingTrays = this.dao.findByCrystalNo(sectionNo);
            if (productionBindingTrays != null && productionBindingTrays.size() > 0) {
                throw new BusinessException("该单晶【" + sectionNo + "】已被载具号:[" + productionBindingTrays.get(0).getTrayNo() + "]绑定");
            }

            //查询当前站点
            Result<CurrentWipStorageStatusDto> currentWipStorageStatusDtoResult = wipStorageService.selectWipStorageResult(sectionNo);
            if (currentWipStorageStatusDtoResult.getCode() != ResultCode.SUCCESS.getCode()) {
                throw new BusinessException("查询站点信息失败");
            }
            if (currentWipStorageStatusDtoResult.getData() == null) {
                throw new BusinessException("站点信息为空");
            }
            CurrentWipStorageStatusDto currentWipStorageStatusDto = currentWipStorageStatusDtoResult.getData();
                        /*
              点位：截断人工下料
              限制：当前晶段必须为‘圆棒检验待进站’或 ‘圆棒检验进站’状态才可绑定；
             */
            if ("6.JD".equals(oldPoint)
                    && !(currentWipStorageStatusDto.getWipStorageCode().equals(EnumValuesFactory.WipStorageCode.圆棒检验.getKey()))
            ) {
                throw new BusinessException("当前晶段在" + currentWipStorageStatusDto.getWipStorageCodeName() + currentWipStorageStatusDto.getWipStorageStatusName() + "，无法在该点位绑定");
            }

            /*
              点位：圆棒人工绑定
              限制：当前晶段必须为‘圆棒检验待进站’状态才可绑定；

              点位：直发点位绑定
              限制：当前晶段必须为‘圆棒检验进站’、‘粘圆棒进站'、’’‘开方待进站’、‘开方进站’才可绑定；
             */
            if ("1.YJY".equals(oldPoint) || "3.YJY".equals(oldPoint)) {

                if ("1.YJY".equals(oldPoint)
                        && !(currentWipStorageStatusDto.getWipStorageCode().equals(EnumValuesFactory.WipStorageCode.圆棒检验.getKey())
                        && currentWipStorageStatusDto.getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.待进站.getKey())
                ) {
                    throw new BusinessException("当前晶段在" + currentWipStorageStatusDto.getWipStorageCodeName() + currentWipStorageStatusDto.getWipStorageStatusName() + "，无法在该点位绑定");
                }
                if ("3.YJY".equals(oldPoint)
                        && !(currentWipStorageStatusDto.getWipStorageCode().equals(EnumValuesFactory.WipStorageCode.圆棒检验.getKey())
                        && currentWipStorageStatusDto.getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.已进站.getKey())
                        && !(currentWipStorageStatusDto.getWipStorageCode().equals(EnumValuesFactory.WipStorageCode.粘圆棒.getKey())
                        && currentWipStorageStatusDto.getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.已进站.getKey())
                        && !(currentWipStorageStatusDto.getWipStorageCode().equals(EnumValuesFactory.WipStorageCode.开方.getKey())
                        && currentWipStorageStatusDto.getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.待进站.getKey())
                        && !(currentWipStorageStatusDto.getWipStorageCode().equals(EnumValuesFactory.WipStorageCode.开方.getKey())
                        && currentWipStorageStatusDto.getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.已进站.getKey())
                        && !(currentWipStorageStatusDto.getWipStorageCode().equals(EnumValuesFactory.WipStorageCode.圆棒截断.getKey())
                        && currentWipStorageStatusDto.getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.待进站.getKey())
                ) {
                    throw new BusinessException("当前晶段在" + currentWipStorageStatusDto.getWipStorageCodeName() + currentWipStorageStatusDto.getWipStorageStatusName() + "，无法在该点位绑定");
                }
            }
        }

        // 查询此单晶是否已经被绑定
        List<ProductionBindingTray> trayNos = dao.findByTrayNo(dto.getTrayNo());
//        List<ProductionBindingTray> trayNos = this.dao.findByTrayNoAndCrystalNo(dto.getTrayNo());
        for (ProductionBindingTray trayNo : trayNos) {
            if (trayNo.getLocationNo() != null && trayNo.getLocationNo().equals(dto.getLocationNo())) {
                if (StringUtils.isNotEmpty(trayNo.getCrystalNo())) {
                    throw new BusinessException("该载具【" + trayNo.getLocationNo() + "】工位,已绑定【" + trayNo.getCrystalNo() + "】,无法绑定");
                } else {
                    dto.setId(trayNo.getId());
                }
            }

        }

//        if (trayNos != null && trayNos.size() == 2) {
//            return ResultGenerator.fail("该载具号【" + dto.getTrayNo() + "】工位已满,无法绑定");
//        }
        //如果没有指定，那就默认人工绑定
        if (dto.getIsBinding() == null) {
            dto.setIsBinding(1);
        }

        if (StringUtils.isNotBlank(dto.getPoint())) {
            String[] pointArr = dto.getPoint().split("\\.");
            if (pointArr.length > 1) {
                dto.setPoint(pointArr[1]);
            } else {
                dto.setPoint(pointArr[0]);
            }
        }


        //如果没有上料点位，则不判断是否在当前点位的工序
        if (StringUtils.isNotBlank(dto.getPoint()) && !"3.YJY".equals(oldPoint) && !"2.YJY".equals(oldPoint) && !"JD".equals(dto.getPoint())) {
            String wipStorageName = EnumValuesFactory.WipStorageCode.getText(dto.getPoint());
            if (wipStorageName == null) {
                throw new BusinessException("载具绑定点位配置中的【" + dto.getPoint() + "】在制品工步代码不存在");
            }
            DictionaryItem dictionaryItem = dictionaryItemService.findByThemeValueAndValueAndEnable(Constants.BIND_SITE, oldPoint, true);
            if (dictionaryItem == null) {
                throw new BusinessException("该上料点位配置已不存在，请刷新页面重试");
            }
            wipStorageService.selectWipStorage(dto.getCrystalNo(), dto.getPoint(), null);
            dto.setBindingSite(dictionaryItem.getName());
        }

        SectionNoDetail sectionNoDetail = sectionNoDetailService.findBySectionNo(dto.getCrystalNo());
        if ("JD".equals(oldPoint)) {
            if (sectionNoDetail.getDistortion() != null && sectionNoDetail.getDistortion().compareTo(BigDecimal.ZERO) != 0) {
                throw new BusinessException("扭：" + sectionNoDetail.getDistortion() + ",不允许绑定");
            }
        }
        bindingVerifyDto.setDto(dto);
        bindingVerifyDto.setInspectDataBase(inspectDataBase);
        bindingVerifyDto.setSectionNoDetail(sectionNoDetail);
        bindingVerifyDto.setOldPoint(oldPoint);
        return bindingVerifyDto;
    }

    private void dealWithSend(ProductionBindingTrayDto dto, String oldPoint, SectionNoDetail sectionNoDetail, YbInspectData inspectDataBase) {

        if ("3.YJY".equals(oldPoint) && inspectDataBase != null && inspectDataBase.getSticksCount() != null && inspectDataBase.getSticksCount() > 1) {
            //拼棒直发
            SpellBindingDto spellBindingDto = new SpellBindingDto();
//            //非标棒不允许绑定
//            if (!"标棒".equals(inspectDataBase.getSectionType())) {
//                throw new BusinessException("非标棒不允许绑定直发线");
//            }
            //推送MCS
            spellBindingDto.setSectionNo(dto.getCrystalNo());
            spellBindingDto.setType("拼棒");
            spellBindingDto.setTrayCode(dto.getTrayNo());
            spellBindingDto.setSectionNo1("");
            spellBindingDto.setSectionNo2("");
            String productType = ybMesToMcsService.productTypeConversion(inspectDataBase.getProductTypeSecond());
            spellBindingDto.setProductType(productType);
            spellBindingDto.setPn(inspectDataBase.getConductiveType());
            spellBindingDto.setProductRank(inspectDataBase.getProductLevel());
            spellBindingDto.setSpellCount(inspectDataBase.getSticksCount());
            spellBindingDto.setTotalLength(inspectDataBase.getSpellBarLength());
            List<String> sectionNos = new ArrayList<>();
            List<String> spellLength = new ArrayList<>();
            List<String> spellWeight = new ArrayList<>();
            BigDecimal totalWeight = new BigDecimal("0");
            for (String sectionNo : inspectDataBase.getSectionCompose().split(",")) {
                YbInspectData inspectData = inspectDataBaseService.findBySectionNo(sectionNo);
                sectionNos.add(inspectData.getSectionNo());
                spellLength.add(inspectData.getActualLength().toString());
                spellWeight.add(inspectData.getTheoryWeight().toString());
                totalWeight = totalWeight.add(inspectData.getTheoryWeight());
            }
            spellBindingDto.setTotalWeight(totalWeight);
            spellBindingDto.setSectionNos(StringUtils.join(sectionNos, ","));
            spellBindingDto.setSpellLength(StringUtils.join(spellLength, ","));
            spellBindingDto.setSpellWeight(StringUtils.join(spellWeight, ","));

            if (active != null && active.equals("prod")) {
                ResultDto resultDto = ybMesToMcsService.spellBinding(spellBindingDto);
                if (resultDto.getStatus() != 100) {
                    throw new BusinessException("拼棒托盘绑定信息,下发MCS失败！：" + resultDto.getMessage());
                }
            }
        } else {
            CrystalTrayBindInfoDto crystalTrayBindInfoDto = new CrystalTrayBindInfoDto();
            if (!"7.HX".equals(oldPoint)) {
                if (sectionNoDetail == null) {
                    throw new BusinessException("晶段信息不存在");
                }
                //晶段类型根据晶段规格、参杂剂、长度判断，圆棒生产管理》检验数据管理》辨准与规则维护》默认值维护》晶棒属性
                //绑定信息下发mcs
                crystalTrayBindInfoDto.setSectionNo(dto.getCrystalNo());
                crystalTrayBindInfoDto.setTail(NumberUtil.String2Integer(dto.getCrystalDirection(), 0));
                crystalTrayBindInfoDto.setTrayCode(dto.getTrayNo());
                crystalTrayBindInfoDto.setBindUser(BaseContextHandler.getUsername());
                String productType = ybMesToMcsService.productTypeConversion(sectionNoDetail.getSpecs());
                crystalTrayBindInfoDto.setProductType(productType);
                crystalTrayBindInfoDto.setPn(sectionNoDetail.getConductiveType());

                if ("3.YJY".equals(oldPoint)) {
                    //直发绑定整棒标棒直发
                    if (inspectDataBase == null) {
                        throw new BusinessException("不存在检验信息，不允许绑定直发线");
                    }
                    //setHasGone 去向mcs没用，会根据属性判断
                    if ("标棒".equals(inspectDataBase.getSectionType())) {
                        crystalTrayBindInfoDto.setType("TYPE_S");
                        crystalTrayBindInfoDto.setHasGone(CrystalTrayBindInfoDto.HasGone_ZF);
                    } else {
                        crystalTrayBindInfoDto.setType("TYPE_N");
                        crystalTrayBindInfoDto.setHasGone(CrystalTrayBindInfoDto.HasGone_RK);
                    }
//                    检验数据库为反切
//                    不存在 未截断 反切画线记录 提示当前晶棒检验数据为反切晶棒，但不存在反切画线记录不能反切。
//
//                    检验数据库不为反切
//                    存在 未截断 反切画线记录   反切  推送

                    //当前晶段  未截断的  反切画线数据
                    List<ProductionBackCuttingRecord> productionBackCuttingRecord = productionRecutService.findAllBySegmentNo(inspectDataBase.getSectionNo());
                    if (productionBackCuttingRecord != null && productionBackCuttingRecord.size() > 0) {
                        crystalTrayBindInfoDto.setType("TYPE_R");
                        crystalTrayBindInfoDto.setHasGone(CrystalTrayBindInfoDto.HasGone_FQ);
                    } else {
                        if (inspectDataBase.getIsCutBack() != null && inspectDataBase.getIsCutBack() == 1) {
                            throw new BusinessException("当前晶棒检验数据为反切晶棒，但不存在反切画线记录不能反切");
                        }
                    }
                } else {
                    String type = defaultCrystalAttrService.getDefaultCrystalAttrOneTimes(sectionNoDetail.getDopant(), sectionNoDetail.getSpecs(), inspectDataBase == null ? null : inspectDataBase.getProductLevel(), sectionNoDetail.getLength());
                    if (type == null) {
                        throw new BusinessException("默认值维护中晶棒属性未查到晶段类型");
                    } else {
                        if ("标棒".equals(type)) {
                            crystalTrayBindInfoDto.setType("TYPE_S");
                        } else if ("线体免检".equals(type)) {
                            throw new BusinessException("类型为：" + type + ",不允许绑定");
                        } else {
                            //"非标棒".equals(type)
                            crystalTrayBindInfoDto.setType("TYPE_N");
                        }

                        //截断过站
                        if ("JD".equals(dto.getPoint())) {
                            // TODO: 2022/3/22 注释过站操作，自动截断功能改为上料时整根晶棒一次过截断站，不再需要单根短棒过站功能
                            //                Result result = this.execJd(dto);
                            //                if (result.getCode() != 200) {
                            //                    throw new BusinessException("截断过站失败：" + result.getMessage());
                            //                }
                            crystalTrayBindInfoDto.setHasGone(CrystalTrayBindInfoDto.HasGone_JY);
                        }
                        //已在检验工序的棒子，需要上料时，上料点位为截断应急上下料，需要指定去向为检验
                        else if ("1.YJY".equals(oldPoint)) {
                            crystalTrayBindInfoDto.setHasGone(CrystalTrayBindInfoDto.HasGone_JY);
                        } else if ("2.YJY".equals(oldPoint)) {
                            //去向反切
                            crystalTrayBindInfoDto.setHasGone(CrystalTrayBindInfoDto.HasGone_FQ);
                        }
                    }
                }

                if ("prod".equals(active)) {
                    ResultDto resultDto = ybMesToMcsService.crystalTrayBindInfo(crystalTrayBindInfoDto);
                    if (resultDto.getStatus() == null || resultDto.getStatus() != 100) {
                        throw new BusinessException("绑定信息下发mcs失败：" + resultDto.getMessage());
                    }
                }
            }
        }
    }

    /**
     * 直发绑定下发方棒订单
     *
     * @param inspectDataBase
     * @return
     */
    public void zfPublishRankResult(YbInspectData inspectDataBase) {
        try {
            if (inspectDataBase != null) {
                BigDecimal theoryWeight = inspectDataBase.getTheoryWeight();
                if (inspectDataBase.getSticksCount() > 1) {
                    //查询粘圆棒整棒信息
                    Section section = sectionService.findBySectionNo(inspectDataBase.getSectionNo());
                    if (section != null) {
//                        actualWeight = section.getActualWeight();
                        theoryWeight = section.getTheoryWeight();
                    }
                }
                RankResultDto rankResultDto = new RankResultDto();
                rankResultDto.setProductRank(inspectDataBase.getProductLevel());
                rankResultDto.setTestRank(inspectDataBase.getProductLevelExperiment());
                rankResultDto.setSectionNo(inspectDataBase.getSectionNo());
                //掺杂剂
                rankResultDto.setDopant(inspectDataBase.getDopant());
                //单晶规格
                rankResultDto.setSpecs(inspectDataBase.getProductTypeSecond());
                //导电型号
                rankResultDto.setConductiveType(inspectDataBase.getConductiveType());
                //单晶总长
                rankResultDto.setLength(inspectDataBase.getSpellBarLength());
                rankResultDto.setType(inspectDataBase.getSectionType());
                rankResultDto.setGradeType(inspectDataBase.getGradeType());
                rankResultDto.setActualLength(inspectDataBase.getActualLength());
                rankResultDto.setCrystalNo(inspectDataBase.getCrystalNo());
                rankResultDto.setData(inspectDataBase.getSectionType());
//                rankResultDto.setWareHouseLength(inspectDataBase.getWareHouseLength());
//                rankResultDto.setActualWeight(actualWeight);
                rankResultDto.setTheoryWeight(theoryWeight);
                rankResultDto.setDiameterMin(inspectDataBase.getDiameterMin());
                rankResultDto.setDiameterMax(inspectDataBase.getDiameterMax());
//                rankResultDto.setDiameterJudge(inspectDataBase.getDiamDecide());
                rankResultDto.setDistortion(inspectDataBase.getDistortion());
                rankResultDto.setIsBevel(inspectDataBase.getIsBevel().toString());
//                rankResultDto.setFineDiameter(inspectDataBase.getFineDiameter());
//                rankResultDto.setFineCutLength(inspectDataBase.getFineCutLength());
                rankResultDto.setPiecewiseNum(inspectDataBase.getPiecewiseNum());
                rankResultDto.setSticksCount(inspectDataBase.getSticksCount());
                rankResultDto.setAgainNum(inspectDataBase.getAgainNum());
                rankResultDto.setHeadTailRecognition(inspectDataBase.getHeadTailRecognition());
//                rankResultDto.setIsSeeBottom(inspectDataBase.getIsSeeBottom());
//                rankResultDto.setLineMarking(inspectDataBase.getLineMarking());
                rankResultDto.setIsCutBack(inspectDataBase.getIsCutBack());
                //非标棒加工匹配订单时赋值
                if ("非标棒".equals(inspectDataBase.getSectionType())) {
                    rankResultDto.setMatchingType(1);
                }
                //if ("标棒".equals(rankResultDto.getType()) && "正常".equals(rankResultDto.getGradeType())) {
                Result<String> result = fbFeignClients.findProductionScheduleCodePro(rankResultDto);
                if (result.getCode() == ResultCode.SUCCESS.getCode() && result.getData() != null && org.apache.commons.lang3.StringUtils.isNotBlank(result.getData())) {
                    rankResultDto.setOrderNo(result.getData());
                }
                //}
                //下发wms,mcs
                publishService.publishEvent(new RankResultEvent(this, rankResultDto));
            }
        } catch (Exception e) {

        }
    }

    //回收料绑定
    public Result bindingRecycledMaterial(ProductionBindingTrayDto dto) {
        String oldPoint = dto.getPoint();
        ProductionBindingTray productionBindingTray;
        BindingVerifyDto bindingVerifyDto = bindingRecycledMaterialVerify(dto);
        dto = bindingVerifyDto.getDto();
        productionBindingTray = fromDto(dto);
        productionBindingTray.setBindingTime(new Date());
        this.dao.save(productionBindingTray);

        // 写入载具绑定记录表
        ProductionBindingTrayLog log = new ProductionBindingTrayLog();
        log.setBindingPeople(dto.getBindingPeople());
        log.setIsBinding(productionBindingTray.getIsBinding());
        log.setCrystalNo(dto.getCrystalNo());
        log.setGmtCreate(new Date());
        log.setBindingTime(productionBindingTray.getBindingTime());
        log.setTrayNo(dto.getTrayNo());
        log.setLocationNo(dto.getLocationNo());
        log.setClassName(dto.getClassName());
        log.setClassnoname(dto.getClassNoName());
        log.setBindingSite(dto.getBindingSite());
        productionBindingTrayLogService.saveOrUpdate(log);
        return ResultGenerator.success();
    }

    public BindingVerifyDto bindingRecycledMaterialVerify(ProductionBindingTrayDto dto) {
        BindingVerifyDto bindingVerifyDto = new BindingVerifyDto();
        //如果载具工位为空，则默认载具工位1
        dto.setLocationNo("1");

        List<ProductionBindingTray> productionBindingTrays = this.dao.findByCrystalNo(dto.getCrystalNo());
        if (productionBindingTrays != null && productionBindingTrays.size() > 0) {
            throw new BusinessException("编号【" + dto.getCrystalNo() + "】已被载具号:[" + productionBindingTrays.get(0).getTrayNo() + "]绑定");
        }
        // 查询此单晶是否已经被绑定
        List<ProductionBindingTray> trayNos = dao.findByTrayNo(dto.getTrayNo());
        for (ProductionBindingTray trayNo : trayNos) {
            if (trayNo.getLocationNo() != null && trayNo.getLocationNo().equals(dto.getLocationNo())) {
                if (StringUtils.isNotEmpty(trayNo.getCrystalNo())) {
                    throw new BusinessException("该载具【" + trayNo.getLocationNo() + "】工位,已绑定【" + trayNo.getCrystalNo() + "】,无法绑定");
                } else {
                    dto.setId(trayNo.getId());
                }
            }
        }
        //如果没有指定，那就默认人工绑定
        if (dto.getIsBinding() == null) {
            dto.setIsBinding(1);
        }

        if (StringUtils.isNotBlank(dto.getPoint())) {
            String[] pointArr = dto.getPoint().split("\\.");
            if (pointArr.length > 1) {
                dto.setPoint(pointArr[1]);
            } else {
                dto.setPoint(pointArr[0]);
            }
        }

        //如果没有上料点位，则不判断是否在当前点位的工序
//        if (StringUtils.isNotBlank(dto.getPoint())) {
//            DictionaryItem dictionaryItem = dictionaryItemService.findByThemeValueAndValueAndEnable(Constants.BIND_SITE, oldPoint, true);
//            if (dictionaryItem == null) {
//                throw new BusinessException("该上料点位配置已不存在，请刷新页面重试");
//            }
//            dto.setBindingSite(dictionaryItem.getName());
//        }
        bindingVerifyDto.setDto(dto);
        return bindingVerifyDto;
    }

    @Override
    public Result unbundlingCrystal(BindingCrystalDto bindingCrystalDto) {
        //如果单晶在立体库，不让pda解绑
        //非0为人工解绑
//        if (bindingCrystalDto.getIsBinding() == null || bindingCrystalDto.getIsBinding() != 0) {
//            InventoryManageInfo oneByRoundSnOrderByIdDesc = null;
//            if (bindingCrystalDto.getTrayNo().startsWith("TPY")) {
//                //圆棒
//                oneByRoundSnOrderByIdDesc = inventoryManageInfoService.findOneByRoundSnAndCrystalTypeOrderByIdDesc(bindingCrystalDto.getCrystalNo(), 0);
//            } else if (bindingCrystalDto.getTrayNo().startsWith("TPF")) {
//                //方棒
//                oneByRoundSnOrderByIdDesc = inventoryManageInfoService.findOneByRoundSnAndCrystalTypeOrderByIdDesc(bindingCrystalDto.getCrystalNo(), 1);
//            }
//
//            if (oneByRoundSnOrderByIdDesc != null) {
//                throw new BusinessException("当前单晶已入立库，不允许解绑！");
//            }
//        }

        ProductionBindingTray bindingTray = this.dao.findByTrayNoAndCrystalNo(bindingCrystalDto.getTrayNo(), bindingCrystalDto.getCrystalNo());

        if (bindingTray != null && StringUtils.isNotBlank(bindingTray.getCrystalNo())) {
            // 解绑需要同时改变长棒表载具号中AGV送验状态
            LongCrystal longCrystal = longCrystalService.findByCrystalNo(bindingTray.getCrystalNo());
            if (longCrystal != null) {
                //检查当前晶棒是否在送验站点
                Result<CurrentWipStorageStatusDto> result =
                        wipStorageService.selectWipStorageResult(longCrystal.getCrystalNo());
                if (result.getCode() == ResultCode.SUCCESS.getCode()
                        && EnumValuesFactory.WipStorageCode.送验.getKey().equals(result.getData().getWipStorageCode())
                ) {
                    // 未送验
                    longCrystal.setCrystalStatus(EnumValuesFactory.CrystalStatus.未送验.getKey());
                    longCrystal.setAgvTaskCode(null);
                    longCrystalService.saveOrUpdate(longCrystal);
                }
            }

            bindingTray.setBindingSite("");
            bindingTray.setCrystalNo(null);
            bindingTray.setToWhere("");
            bindingTray.setIsBinding(2);
            this.saveOrUpdate(bindingTray);

            //添加绑定载具记录
            Date currentDate = new Date();
            ProductionBindingTrayLog log = new ProductionBindingTrayLog();
            log.setTrayNo(bindingCrystalDto.getTrayNo());
            log.setCrystalNo(bindingCrystalDto.getCrystalNo());
            log.setBindingTime(currentDate);
            log.setBindingSite(StringUtils.isEmpty(bindingCrystalDto.getBindingSite()) ? "PDA人工解绑" : bindingCrystalDto.getBindingSite());
            log.setIsBinding(2);//解绑
            log.setBindingPeople(BaseContextHandler.getUsername());
            log.setGmtCreate(currentDate);
            log.setLocationNo(bindingTray.getLocationNo());
            log.setReason(bindingCrystalDto.getReason());
            productionBindingTrayLogService.saveOrUpdate(log);
        }
        //托盘解绑信息下发mcs
        if (StringUtils.isNotEmpty(bindingCrystalDto.getTrayNo())) {
            String trayNo = bindingCrystalDto.getTrayNo();
            trayNo = trayNo.toUpperCase();
            if (trayNo.startsWith("TP") && !trayNo.startsWith("TPT")) {
                CrystalTrayUnBindInfoDto crystalTrayUnBindInfoDto = new CrystalTrayUnBindInfoDto();
                crystalTrayUnBindInfoDto.setTrayCode(bindingCrystalDto.getTrayNo());
                //推送mcs解绑信息
                Thread thread = new Thread(() -> {
                    ybMesToMcsService.crystalTrayUnBindInfo(crystalTrayUnBindInfoDto);
                });
                thread.start();
            }
        } else {
            throw new BusinessException("托盘号不能为空");
        }
        return ResultGenerator.success();
    }

    public ProductionBindingTray fromDto(ProductionBindingTrayDto dto) {
        return modelMapper.map(dto, ProductionBindingTray.class);
    }

    @Override
    public ProductionBindingTray getByCrystalNo(String crystalNo) {
        List<ProductionBindingTray> trays = dao.findByCrystalNo(crystalNo);
        if (trays.size() > 0) {
            return trays.get(0);
        } else {
            return null;
        }
    }

    /**
     * PDA头尾回收料绑定载具车
     *
     * @param pailNum 载具车号
     * @return
     */
    @Override
    public void bindingRecycledPailNum(String pailNum) {

        ProductionBindingTray dto = new ProductionBindingTray();
        dto.setIsBinding(0);
        dto.setBindingPeople("PDA回收料绑定");
        dto.setBindingTime(new Date());
        dto.setTrayNo(pailNum);
        dto.setCrystalNo(pailNum);
        this.dao.save(dto);
        // 写入载具绑定记录表
        ProductionBindingTrayLog log = new ProductionBindingTrayLog();
        log.setBindingPeople(dto.getBindingPeople());
        log.setIsBinding(dto.getIsBinding());
        log.setCrystalNo(dto.getCrystalNo());
        log.setGmtCreate(new Date());
        log.setBindingTime(new Date());
        log.setTrayNo(dto.getTrayNo());
        log.setLocationNo(dto.getLocationNo());
        log.setClassName(BaseContextHandler.getUserTeamGroup());
        log.setClassnoname(BaseContextHandler.getUserClassNo());
        log.setBindingSite(dto.getBindingSite());
        productionBindingTrayLogService.saveOrUpdate(log);
    }

    /**
     * fls自动解绑载具车与单晶关系
     *
     * @param pailNum
     * @return
     */
    @Override
    public Result flsUnbindingPailNum(String pailNum) {
        if (StringUtils.isBlank(pailNum)) {
            return ResultGenerator.fail("请传入正确的载具车号!");
        }
        ProductionBindingTray bindingTray = this.dao.findByTrayNoAndCrystalNo(pailNum, pailNum);

        if (bindingTray != null && StringUtils.isNotBlank(bindingTray.getCrystalNo())) {


            bindingTray.setBindingSite("");
            bindingTray.setCrystalNo(null);
            bindingTray.setToWhere("");
            bindingTray.setIsBinding(2);
            this.saveOrUpdate(bindingTray);

            //添加绑定载具记录
            Date currentDate = new Date();
            ProductionBindingTrayLog log = new ProductionBindingTrayLog();
            log.setTrayNo(pailNum);
            log.setCrystalNo(pailNum);
            log.setBindingTime(currentDate);
            log.setBindingSite("fls自动解绑");
            log.setIsBinding(2);//解绑
            log.setBindingPeople(BaseContextHandler.getUsername());
            log.setGmtCreate(currentDate);
            log.setLocationNo(bindingTray.getLocationNo());
            log.setReason("");
            productionBindingTrayLogService.saveOrUpdate(log);
        }

        return ResultGenerator.success();
    }

    /**
     * 根据单晶编号判断该单晶是否
     *
     * @param sectionNo
     * @return
     */
    public boolean isBind(String sectionNo) {

        return false;
    }

    public boolean isBind(String trayNo, String locationNo) {
        return false;
    }

    @Override
    public List<ProductionBindingTray> getByTrayNo(String code) {
        return dao.findByTrayNoAndCrystalNo(code);
    }

    @Override
    public List<ProductionBindingTray> findByTrayNo(String trayNo) {
        return dao.findByTrayNo(trayNo);
    }

    @Override
    public List<ProductionBindingTray> findBindingTrayByTrayNo(String trayNo) {
        return dao.findBindingTrayByTrayNo(trayNo);
    }

    @Override
    public void updateByCrystalNo(String crystalNoOld, String crystalNo) {
        dao.updateByCrystalNo(crystalNoOld, crystalNo);
    }
}
