package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.base;

import cn.estsh.i3plus.ext.mes.pcn.api.base.IQualityDecisionService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.ISxRepairWorkService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.IWorkCenterExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnRepairService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.jx.IJxProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.jx.IJxProduceSnMcRecordService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MesProduceSnModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.ProduceSnExtModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.RepairRequestModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.ConvertBeanExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtEnumUtil;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.exception.ImppExceptionEnum;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.*;
import cn.estsh.i3plus.pojo.mes.repository.*;
import cn.estsh.impp.framework.boot.exception.ImppExceptionBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.testng.annotations.AfterSuite;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: Wynne.Lu
 * @CreateDate: 2019/8/30 1:39 PM
 * @Description:
 **/
@Service
public class QualityDecisionService implements IQualityDecisionService {

    @Autowired
    private IProduceSnExtService produceSnExtService;

    @Autowired
    private IProduceSnRepairService produceSnRepairService;

    @Autowired
    private MesProduceSnExtRepository produceSnExtRepository;

    @Autowired
    private IJxProduceSnMcRecordService produceSnMcRecordService;

    @Autowired
    private MesDefectRepository mesDefectRDao;

    @Autowired
    private MesTypeCfgRepository typeCfgRepository;

    @Autowired
    private MesBadCellRepository badCellRepository;

    @Autowired
    private MesBadCellDetailRepository mesBadCellDetailRDao;

    @Autowired
    private MesProcessRepository mesProcessRDao;

    @Autowired
    private IWorkCenterExtService workCenterExtService;

    @Autowired
    private MesProcessCellRepository mesProcessCellRDao;

    @Autowired
    private MesProduceSnMcRecordRepository produceSnMcRecordRepository;

    @Autowired
    private MesBadCellDetailRepository badCellDetailRepository;

    @Autowired
    private MesRepairRecordExtRepository repairRecordExtRepository;

    @Autowired
    private IJxProduceSnExtService jxProduceSnExtService;

    public static final int MANAGE_CODE = 10;
    public static final int SERIAL_NUMBER = 20;
    public static final int PRODUCT_SN = 30;

    @Override
    public Map<String, Object> doCheckSerialNumberExt(String serialNumber, String organizeCode, String workCenterCode) {

        Map<String, Object> resultMap = new HashMap<>();

        Map<String, Object> map = doCheckSerialNumber(serialNumber, organizeCode, workCenterCode);

        ProduceSnExtModel produceSnExt = map.containsKey("snModel") ? (ProduceSnExtModel) map.get("snModel") : null;

        if (produceSnExt.getQcStatus() == MesPcnExtEnumUtil.MC_RECORD_QC_STATUS.FALSE.getValue()) {
            resultMap.put("isFreeze", true);
        } else {
            resultMap.put("isFreeze", false);
        }

        resultMap.put("object", produceSnExt);

        return resultMap;
    }

    @Override
    public Map<String, Object> doCheckSerialNumber(String serialNumber, String organizeCode, String workCenterCode) {

        boolean isFinalCheckAfterSn = false;

        MesProduceSnMcRecord produceSnMcRecordDb = produceSnMcRecordService.getProduceSnMcRecordDb(organizeCode, serialNumber);

        ProduceSnExtModel produceSnExtModel = new ProduceSnExtModel();
        MesProduceSnExt produceSnExt = null;
        if(produceSnMcRecordDb != null){

            produceSnExt = produceSnExtService.getProduceSnExtBySn(organizeCode, produceSnMcRecordDb.getSerialNumber());

            if (produceSnExt == null) {

                BeanUtils.copyProperties(produceSnMcRecordDb, produceSnExtModel, MesPcnExtConstWords.ID);

            } else {
                BeanUtils.copyProperties(produceSnExt, produceSnExtModel, MesPcnExtConstWords.ID);

                produceSnExtModel.setSerialNumber(produceSnMcRecordDb.getManageCode());

            }

        } else {

            produceSnExt = produceSnExtService.getProduceSnExtByProductSn(organizeCode, serialNumber);

            if (produceSnExt == null) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("条码信息不存在，请检查")
                        .build();
            }

            if(produceSnExt.getSnStatus() > MesPcnExtEnumUtil.PRODUCE_SN_STATUS.PROCESS.getValue()){
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("扫描的条码的条码状态为【下线】，不可以操作")
                        .build();
            }

            BeanUtils.copyProperties(produceSnExt, produceSnExtModel, MesPcnExtConstWords.ID);

            // 先查询条码信息，判断最终工单号字段与工单号字段是否一致，一致的话判断生产线跟条码信息的生产线是否一致,工单不一样的话，根据最终工单号与条码查询返工条码表，判断生产线是否一致
            if (produceSnExt.getLastWorkOrderNo().equals(produceSnExt.getWorkOrderNo())) {
                if(!workCenterCode.equals(produceSnExt.getWorkCenterCode())){
                    throw ImppExceptionBuilder.newInstance()
                            .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                            .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                            .setErrorDetail("当前扫描的条码[%s]的产线为[%s]，与当前选择的产线[%s]不一致，请重新扫描", serialNumber, produceSnExt.getWorkCenterCode(), workCenterCode)
                            .build();
                }
            } else {
                MesProduceSnRepair produceSnRepair = produceSnRepairService.getProduceSnRepairBySnAndOrderNo(organizeCode, serialNumber, produceSnExt.getLastWorkOrderNo());
                if(null!=produceSnRepair && !workCenterCode.equals(produceSnRepair.getWorkCenterCode())){
                    throw ImppExceptionBuilder.newInstance()
                            .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                            .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                            .setErrorDetail("当前扫描的条码[%s]的产线为[%s]，与当前选择的产线[%s]不一致，请重新扫描", serialNumber, produceSnRepair.getWorkCenterCode(), workCenterCode)
                            .build();
                }

                produceSnExtModel.setWorkOrderNo(produceSnRepair.getWorkOrderNo());
                produceSnExtModel.setWorkTime(produceSnRepair.getWorkTime());
                produceSnExtModel.setShiftCode(produceSnRepair.getShiftCode());

                isFinalCheckAfterSn = true;
            }

        }

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("snModel", produceSnExtModel);
        resultMap.put("sn", produceSnExt);
        resultMap.put("mcRecord", produceSnMcRecordDb);
        resultMap.put("isFinalCheckAfterSn", isFinalCheckAfterSn);

        return resultMap;
    }

    private String getWorkOrderNo(String workOrderNo, RepairRequestModel model) {
        // 10-管理码；20-过程条码：30-产品条码
        Integer snType = 0;

        String querySn = null;
        if (StringUtils.isEmpty(model.getProductSn())) {
            if (StringUtils.isEmpty(model.getSerialNumber())) {
                if (!StringUtils.isEmpty(model.getManageCode())) {
                    snType = MANAGE_CODE;
                    querySn = model.getManageCode();
                }
            } else {
                snType = SERIAL_NUMBER;
                querySn = model.getSerialNumber();
            }
        } else {
            snType = PRODUCT_SN;
            querySn = model.getProductSn();
        }

        if (StringUtils.isEmpty(querySn)) {
            switch (snType) {
                case MANAGE_CODE:
                    MesProduceSnMcRecord produceSnMcRecordDb = produceSnMcRecordRepository.getByProperty(
                            new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.MANAGE_CODE, MesPcnExtConstWords.SN_STATUS},
                            new Object[]{model.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), querySn, MesPcnExtEnumUtil.MC_RECORD_SN_STATUS.LINE_ON.getValue()});

                    if (produceSnMcRecordDb == null) {
                        throw ImppExceptionBuilder.newInstance()
                                .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                                .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                                .setErrorDetail("管理码[%s]不存在", querySn)
                                .build();
                    }

                    workOrderNo =  produceSnMcRecordDb.getWorkOrderNo();
                    break;
                case SERIAL_NUMBER:
                    MesProduceSnExt produceSnExtBySn = produceSnExtService.getProduceSnExtBySn(model.getOrganizeCode(), querySn);

                    if (produceSnExtBySn == null) {
                        throw ImppExceptionBuilder.newInstance()
                                .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                                .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                                .setErrorDetail("过程条码[%s]不存在", querySn)
                                .build();
                    }

                    workOrderNo = produceSnExtBySn.getLastWorkOrderNo();
                    break;
                case PRODUCT_SN:
                    MesProduceSnExt produceSnExtByProductSn = produceSnExtService.getProduceSnExtByProductSn(model.getOrganizeCode(), querySn);

                    if (produceSnExtByProductSn == null) {
                        throw ImppExceptionBuilder.newInstance()
                                .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                                .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                                .setErrorDetail("产品条码[%s]不存在", querySn)
                                .build();
                    }

                    workOrderNo = produceSnExtByProductSn.getLastWorkOrderNo();
                    break;
                default:
                    throw ImppExceptionBuilder.newInstance()
                            .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                            .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                            .setErrorDetail("入参缺少生产工单号")
                            .build();
            }
        } else {
            if (StringUtils.isEmpty(workOrderNo)) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("入参缺少生产工单号")
                        .build();
            }
        }

        return workOrderNo;
    }

    @Override
    public Map<String,List<MesDefect>> findMesDefect(String organizeCode) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(organizeCode, MesPcnExtConstWords.ORGANIZE_CODE, packBean);
        List<MesDefect> mesDefects = mesDefectRDao.findByHqlWhere(packBean);

        if(CollectionUtils.isEmpty(mesDefects)){
            return new HashMap<>();
        }

        List<MesTypeCfg> typeCfgList = typeCfgRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, "typeCode"},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(),
                        CommonEnumUtil.IS_VAILD.VAILD.getValue(), MesPcnExtEnumUtil.MES_TYPE_CFG_EXT.BAD.getValue()});
        Map<String, List<MesTypeCfg>> typeCfgMap = CollectionUtils.isEmpty(typeCfgList) ? null :
                typeCfgList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getTypeCode()))).collect(Collectors.groupingBy(MesTypeCfg::getBusinessTypeCode));
        for (MesDefect defectDb : mesDefects) {
            List<MesTypeCfg> typeCfgs = CollectionUtils.isEmpty(typeCfgMap) ? null : typeCfgMap.get(defectDb.getDefectType());
            defectDb.setDefectTypeName(CollectionUtils.isEmpty(typeCfgs) ? null : typeCfgs.get(0).getBusinessTypeName());
        }

        Map<String,List<MesDefect>> mesDefectMap = mesDefects.stream().collect(Collectors.groupingBy(q -> q.getDefectType() + "&&" + q.getDefectTypeName()));

        return mesDefectMap;
    }

    @Override
    public void insertMesBadCellAndDetail(RepairRequestModel repairRequestModel) {
        List<MesBadCellDetail> badCellDetailList = getMesBadCellDetails(repairRequestModel);

        Map<String, Object> map = doCheckSerialNumber(repairRequestModel.getSerialNumber(), repairRequestModel.getOrganizeCode(), repairRequestModel.getWorkCenterCode());

        ProduceSnExtModel produceSnExtModel = map.containsKey("snModel") ? (ProduceSnExtModel) map.get("snModel") : null;

        MesProduceSnExt produceSnExt = map.containsKey("sn") ? (MesProduceSnExt) map.get("sn") : null;

        MesProduceSnMcRecord produceSnMcRecordDb = map.containsKey("mcRecord") ? (MesProduceSnMcRecord) map.get("mcRecord") : null;

        String workOrderNo;
        if (StringUtils.isEmpty(produceSnExtModel.getLastWorkOrderNo())) {
            workOrderNo = produceSnExtModel.getWorkOrderNo();
        } else {
            workOrderNo = produceSnExtModel.getLastWorkOrderNo();
        }

        MesWorkCenterExt workCenterExt = getMesWorkCenterExt(repairRequestModel);

        insertBadCell(repairRequestModel, badCellDetailList, workOrderNo, produceSnExtModel, workCenterExt);

        insertBadCellDetail(repairRequestModel, badCellDetailList, produceSnExtModel, produceSnExt, produceSnMcRecordDb, workCenterExt);

        saveProduceSnMcRecordDb(repairRequestModel, produceSnMcRecordDb);

        updateProduceSnQcAndOptionType(repairRequestModel, produceSnExt);

    }

    private List<MesBadCellDetail> getMesBadCellDetails(RepairRequestModel repairRequestModel) {
        List<MesBadCellDetail> badCellDetailList = repairRequestModel.getMesDefectRecordList();
        if (CollectionUtils.isEmpty(badCellDetailList)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("入参缺少不良明细数据")
                    .build();
        }
        return badCellDetailList;
    }

    private void updateProduceSnQcAndOptionType(RepairRequestModel repairRequestModel, MesProduceSnExt produceSnExt) {
        if ((produceSnExt != null) && (!StringUtils.isEmpty(produceSnExt.getLastWorkOrderNo()))) {
            produceSnExt.setQcStatus(MesPcnExtEnumUtil.PRODUCE_SN_QC_STATUS.DEFECTED.getValue());
            produceSnExt.setOperateType(MesPcnExtEnumUtil.SN_OPERATE_TYPE.REPAIR.getValue());
            jxProduceSnExtService.clearProduceSnProcess(produceSnExt);
            ConvertBean.serviceModelUpdate(produceSnExt, repairRequestModel.getModifyUser());
            produceSnExt.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
            new ConvertBeanExt(produceSnExt).convertBean(produceSnExt);
            produceSnExtRepository.save(produceSnExt);
        }
    }

    private void saveProduceSnMcRecordDb(RepairRequestModel repairRequestModel, MesProduceSnMcRecord produceSnMcRecordDb) {
        if (produceSnMcRecordDb != null) {
            produceSnMcRecordDb.setQcStatus(MesPcnExtEnumUtil.MC_RECORD_QC_STATUS.FALSE.getValue());
            produceSnMcRecordDb.setOperateType(MesPcnExtEnumUtil.SN_OPERATE_TYPE.REPAIR.getValue());
            ConvertBean.serviceModelUpdate(produceSnMcRecordDb, repairRequestModel.getModifyUser());
            produceSnMcRecordRepository.save(produceSnMcRecordDb);
        }
    }

    private void insertBadCellDetail(RepairRequestModel repairRequestModel, List<MesBadCellDetail> badCellDetailList, ProduceSnExtModel produceSnExtModel, MesProduceSnExt produceSnExt, MesProduceSnMcRecord produceSnMcRecordDb, MesWorkCenterExt workCenterExt) {
        for (MesBadCellDetail mesBadCellDetail : badCellDetailList) {
            MesBadCellDetail badCellDetail = new MesBadCellDetail();
            BeanUtils.copyProperties(mesBadCellDetail, badCellDetail, MesPcnExtConstWords.ID);
            badCellDetail.setWorkTime(workCenterExt.getWorkTime());
            badCellDetail.setShiftCode(workCenterExt.getShiftCode());

            // 产品条码为空说明是试制条码
            if (produceSnExt == null) {

                if (!StringUtils.isEmpty(produceSnExtModel.getManageCode())) badCellDetail.setManageCode(produceSnExtModel.getManageCode());
                if (produceSnMcRecordDb != null) badCellDetail.setThirdPartyPid(String.valueOf(produceSnMcRecordDb.getId()));

            } else {

                if (!StringUtils.isEmpty(produceSnExt.getSerialNumber())) badCellDetail.setSerialNumber(produceSnExt.getSerialNumber());
                if (!StringUtils.isEmpty(produceSnExt.getProductSn())) badCellDetail.setProductSn(produceSnExt.getProductSn());
                if (!StringUtils.isEmpty(produceSnExt.getTrayNo())) badCellDetail.setManageCode(produceSnExt.getTrayNo());
                if (produceSnMcRecordDb != null) badCellDetail.setThirdPartyPid(String.valueOf(produceSnMcRecordDb.getId()));

            }

            badCellDetail.setWorkCellCode(repairRequestModel.getWorkCellCode());
            badCellDetail.setRepairStatus(MesPcnExtEnumUtil.MES_REPAIR_STATUS.NO_REPAIR.getValue());
            badCellDetail.setApprovalStatus(MesPcnExtEnumUtil.BAD_CELL_DETAIL_APPROVAL_STATUS.UN_APPROVAL.getValue());
            ConvertBean.serviceModelInitialize(badCellDetail, repairRequestModel.getModifyUser());
            badCellDetail.setDefectActionTime(badCellDetail.getCreateDatetime());
            mesBadCellDetailRDao.insert(badCellDetail);
        }
    }

    private MesWorkCenterExt getMesWorkCenterExt(RepairRequestModel repairRequestModel) {
        MesWorkCenterExt workCenterExt = workCenterExtService.getWorkCenterExtByWorkCenterCode(repairRequestModel.getOrganizeCode(), repairRequestModel.getWorkCenterCode());
        if (null == workCenterExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产线代码[%s]无效", repairRequestModel.getWorkCenterCode())
                    .build();
        }
        if (StringUtils.isEmpty(workCenterExt.getShiftCode()) || StringUtils.isEmpty(workCenterExt.getWorkTime())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产线[%s]未启动班次", repairRequestModel.getWorkCenterCode())
                    .build();
        }
        return workCenterExt;
    }

    private void insertBadCell(RepairRequestModel repairRequestModel, List<MesBadCellDetail> badCellDetailList, String workOrderNo, ProduceSnExtModel produceSnExtModel, MesWorkCenterExt workCenterExt) {
        MesBadCell mesBadCell = badCellRepository.getByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID,
                        MesPcnExtConstWords.WORK_ORDER_NO, MesPcnExtConstWords.WORK_TIME, MesPcnExtConstWords.SHIFT_CODE, MesPcnExtConstWords.WORK_CELL_CODE},
                new Object[]{repairRequestModel.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(),
                        workOrderNo, workCenterExt.getWorkTime(), workCenterExt.getShiftCode(), repairRequestModel.getWorkCellCode()});

        if(mesBadCell == null){
            MesProcess processDb = mesProcessRDao.getByProperty(
                    new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.PROCESS_CODE},
                    new Object[]{repairRequestModel.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), repairRequestModel.getProcessCode()});
            mesBadCell = new MesBadCell();
            mesBadCell.setOrganizeCode(repairRequestModel.getOrganizeCode());
            mesBadCell.setPartNo(produceSnExtModel.getPartNo());
            mesBadCell.setPartNameRdd(produceSnExtModel.getPartNameRdd());
            mesBadCell.setWorkCenterCode(repairRequestModel.getWorkCenterCode());
            mesBadCell.setWorkCellCode(repairRequestModel.getWorkCellCode());
            mesBadCell.setProcessCode(repairRequestModel.getProcessCode());
            mesBadCell.setProcessNameRdd(null != processDb ? processDb.getProcessName() : null);
            mesBadCell.setQty(new Double(badCellDetailList.size()));
            mesBadCell.setWorkOrderNo(workOrderNo);
            mesBadCell.setWorkTime(workCenterExt.getWorkTime());
            mesBadCell.setShiftCode(workCenterExt.getShiftCode());
            ConvertBean.serviceModelInitialize(mesBadCell, repairRequestModel.getModifyUser());
            badCellRepository.insert(mesBadCell);
        }else {
            mesBadCell.setQty(MathOperation.add(mesBadCell.getQty(), new Double(badCellDetailList.size())));
            ConvertBean.serviceModelUpdate(mesBadCell, repairRequestModel.getModifyUser());
            badCellRepository.save(mesBadCell);
        }
    }

    @Override
    public void doUnfreeze(RepairRequestModel repairRequestModel) {

        Map<String, Object> map = doCheckSerialNumber(repairRequestModel.getSerialNumber(), repairRequestModel.getOrganizeCode(), repairRequestModel.getWorkCenterCode());

        ProduceSnExtModel produceSnExtModel = map.containsKey("snModel") ? (ProduceSnExtModel) map.get("snModel") : null;

        MesProduceSnExt produceSnExt = map.containsKey("sn") ? (MesProduceSnExt) map.get("sn") : null;

        MesProduceSnMcRecord produceSnMcRecordDb = map.containsKey("mcRecord") ? (MesProduceSnMcRecord) map.get("mcRecord") : null;

        boolean isFinalCheckAfterSn =  map.containsKey("isFinalCheckAfterSn");

        List<MesBadCellDetail> badCellDetailList = getMesBadCellDetails(repairRequestModel, isFinalCheckAfterSn, produceSnExtModel, produceSnExt);

        boolean isCompleteRepair =  CollectionUtils.isEmpty(badCellDetailList) ? true : badCellDetailList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getRepairStatus()) && MesPcnExtEnumUtil.MES_REPAIR_STATUS.NO_REPAIR.getValue() == o.getRepairStatus())).collect(Collectors.toList()).size() > 0 ;

        if (produceSnExtModel.getQcStatus() != MesPcnExtEnumUtil.PRODUCE_SN_QC_STATUS.DEFECTED.getValue()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("当前条码状态为[%s],不为[%s]", MesPcnExtEnumUtil.PRODUCE_SN_STATUS.valueOfDescription(produceSnExtModel.getSnStatus()), MesPcnExtEnumUtil.PRODUCE_SN_STATUS.PROCESS.getDescription())
                    .build();
        }

        if (isCompleteRepair) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("未维修完成")
                    .build();
        }

        if ((produceSnExt != null) && (!StringUtils.isEmpty(produceSnExt.getSerialNumber()))) {
            produceSnExt.setOperateType(MesPcnExtEnumUtil.SN_OPERATE_TYPE.QUALIFIED.getValue());
            produceSnExt.setQcStatus(MesPcnExtEnumUtil.PRODUCE_SN_QC_STATUS.QUALIFIED.getValue());
            ConvertBean.serviceModelUpdate(produceSnExt, repairRequestModel.getModifyUser());
            new ConvertBeanExt(produceSnExt).convertBean(produceSnExt);
            produceSnExtRepository.save(produceSnExt);
        }

        if (produceSnMcRecordDb != null) {
            produceSnMcRecordDb.setQcStatus(MesPcnExtEnumUtil.MC_RECORD_QC_STATUS.TRUE.getValue());
            ConvertBean.serviceModelUpdate(produceSnMcRecordDb, repairRequestModel.getModifyUser());
            produceSnMcRecordRepository.save(produceSnMcRecordDb);
        }

        List<MesRepairRecordExt> repairRecordBySerialNumberList = getMesRepairRecordExts(isFinalCheckAfterSn, repairRequestModel.getOrganizeCode(), repairRequestModel.getSerialNumber(), produceSnExtModel, produceSnExt);

        if (!CollectionUtils.isEmpty(badCellDetailList)) {
            for (MesBadCellDetail badCellDetail : badCellDetailList) {
                badCellDetail.setIsUnfreeze(MesPcnExtEnumUtil.IS_UNFREEZE.YES.getValue());
                ConvertBean.serviceModelUpdate(badCellDetail, repairRequestModel.getModifyUser());
            }

            badCellDetailRepository.saveAll(badCellDetailList);
        }

        if (!CollectionUtils.isEmpty(repairRecordBySerialNumberList)) {
            for (MesRepairRecordExt repairRecordExt : repairRecordBySerialNumberList) {
                repairRecordExt.setIsUnfreeze(MesPcnExtEnumUtil.IS_UNFREEZE.YES.getValue());
                ConvertBean.serviceModelUpdate(repairRecordExt, repairRequestModel.getModifyUser());
            }

            repairRecordExtRepository.saveAll(repairRecordBySerialNumberList);
        }
    }


    private List<MesRepairRecordExt> getMesRepairRecordExts(boolean isFinalCheckAfterSn, String organizeCode, String querySn, ProduceSnExtModel produceSnExtModel, MesProduceSnExt produceSnExt) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        // lastWorkOrderNo 为空 代表为试制上线管理码
        if (StringUtils.isEmpty(produceSnExtModel.getLastWorkOrderNo())) {
            DdlPreparedPack.getStringEqualPack(produceSnExtModel.getWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
            DdlPreparedPack.getStringEqualPack(querySn, MesPcnExtConstWords.MANAGE_CODE, packBean);
        } else if (produceSnExt.getLastWorkOrderNo().equals(produceSnExt.getWorkOrderNo())) {
            if (isFinalCheckAfterSn) {
                DdlPreparedPack.getStringEqualPack(produceSnExtModel.getLastWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
                DdlPreparedPack.getStringEqualPack(produceSnExt.getProductSn(), MesPcnExtConstWords.PRODUCT_SN, packBean);
            } else {
                DdlPreparedPack.getStringEqualPack(produceSnExt.getWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
                DdlPreparedPack.getStringEqualPack(produceSnExt.getSerialNumber(), MesPcnExtConstWords.SERIAL_NUMBER, packBean);
            }
        } else {
            DdlPreparedPack.getStringEqualPack(produceSnExt.getLastWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
            DdlPreparedPack.getStringEqualPack(produceSnExt.getProductSn(), MesPcnExtConstWords.PRODUCT_SN, packBean);
        }
        DdlPreparedPack.getNumEqualPack(MesPcnExtEnumUtil.IS_UNFREEZE.NO.getValue(), MesPcnExtConstWords.IS_UNFREEZE, packBean);
        packBean.setOrderByStr(" order by createDatetime desc ");
        return repairRecordExtRepository.findByHqlWhere(packBean);
    }
    private List<MesBadCellDetail> getMesBadCellDetails(RepairRequestModel repairRequestModel, boolean isFinalCheckAfterSn, ProduceSnExtModel produceSnExtModel, MesProduceSnExt produceSnExt) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(repairRequestModel.getOrganizeCode());
        if (StringUtils.isEmpty(produceSnExtModel.getLastWorkOrderNo())) {
            DdlPreparedPack.getStringEqualPack(produceSnExtModel.getWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
            DdlPreparedPack.getStringEqualPack(produceSnExtModel.getSerialNumber(), MesPcnExtConstWords.MANAGE_CODE, packBean);
        } else if (produceSnExtModel.getLastWorkOrderNo().equals(produceSnExtModel.getWorkOrderNo())){
            if (isFinalCheckAfterSn) {
                DdlPreparedPack.getStringEqualPack(produceSnExtModel.getLastWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
                DdlPreparedPack.getStringEqualPack(produceSnExt.getProductSn(), MesPcnExtConstWords.PRODUCT_SN, packBean);
            } else {
                DdlPreparedPack.getStringEqualPack(produceSnExtModel.getWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
                DdlPreparedPack.getStringEqualPack(produceSnExt.getSerialNumber(), MesPcnExtConstWords.SERIAL_NUMBER, packBean);
            }
        } else {
            DdlPreparedPack.getStringEqualPack(produceSnExtModel.getLastWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
            DdlPreparedPack.getStringEqualPack(produceSnExtModel.getProductSn(), MesPcnExtConstWords.PRODUCT_SN, packBean);
        }
        DdlPreparedPack.getNumEqualPack(MesPcnExtEnumUtil.IS_UNFREEZE.NO.getValue(), MesPcnExtConstWords.IS_UNFREEZE, packBean);
        packBean.setOrderByStr(" order by createDatetime desc ");
        return badCellDetailRepository.findByHqlWhere(packBean);
    }

    @Override
    public MesProcessCell getMesProcessCell(String workCenterCode, String workCellCode, String organizeCode) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(workCenterCode, MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(workCellCode, MesPcnExtConstWords.WORK_CELL_CODE, packBean);
        return mesProcessCellRDao.getByProperty(packBean);
    }

}
