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

import akka.actor.ActorRef;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesInputDefectRecordService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesNcProcessingService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionDispatchContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionProcessContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPartContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPsOutContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MesNcProcessingInputModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MesPartInspectionInputModel;
import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmRouteDataService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.codemaker.SnowflakeIdMaker;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesDefectType;
import cn.estsh.i3plus.pojo.mes.bean.MesPartSap;
import cn.estsh.i3plus.pojo.mes.bean.nc.MesPartInspection;
import cn.estsh.i3plus.pojo.mes.bean.nc.MesPartInspectionDetail;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.model.StationResultBean;
import cn.estsh.i3plus.pojo.mes.model.StepResult;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import cn.estsh.impp.framework.boot.exception.ImppBusiException;
import com.google.common.base.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @Description : 加工异常处理工步
 * @Author : zxw
 **/
@Slf4j
@Service
public class MesProductResultErrorHandleStepService extends BaseStepService {
    @Autowired
    private SnowflakeIdMaker snowflakeIdMaker;

    @Autowired
    private IMesProductionProcessContextStepService productionProcessContextStepService;

    @Autowired
    private IMesNcProcessingService ncProcessingService;

    @Autowired
    private IMesInputDefectRecordService inputDefectRecordService;

    @Autowired
    private IMesProductionDispatchContextStepService mesProductionDispatchContextStepService;

    @Autowired
    private IFsmRouteDataService fsmRouteDataService;

    private static final Map<String, ActorRef> refMap = new ConcurrentHashMap<>(200);

    @Override
    public StepResult execute(StationRequestBean reqBean) {

        StepResult stepResult = StepResult.getSuccessComplete();
        StationResultBean resultBean = new StationResultBean();

        // 获取加工结果
        String productResult = mesProductionDispatchContextStepService.getProductResultContext(reqBean);

        // 如果是报废或者可疑，需要编辑条码状态为不合格、并且nc判定需要新增一条记录
        Integer resultInt;
        try {
            resultInt = StringUtils.isEmpty(productResult) ? MesExtEnumUtil.PRODUCE_QC_STATUS.QUALIFIED.getValue() : Integer.valueOf(productResult);
        } catch (Exception e) {
            resultInt = MesExtEnumUtil.PRODUCE_QC_STATUS.QUALIFIED.getValue();
        }

        if (resultInt.compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.QUALIFIED.getValue()) == 0) return stepResult;

        //获取上下文产出条码数据信息集合
        List<MesProductionPsOutContext> productionPsOutContextList = mesProductionDispatchContextStepService.getProductionPsOutContext(reqBean);

        //获取上下文产出零件信息
        List<MesProductionPartContext> productionPartContextList = mesProductionDispatchContextStepService.getProductionPartContext(reqBean);

        try {
            // 保存加工异常记录(NC判断记录)
            saveProductResultException(reqBean, productionPsOutContextList, productionPartContextList, resultInt);
        } catch (ImppBusiException e) {
            stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), String.format("加工[%s] NC信息保存失败: %s", MesExtEnumUtil.PRODUCE_QC_STATUS.valueOfDescription(resultInt), e.getErrorDetail()));
        } catch (Exception e) {
            String webMsg = String.format("加工[%s] NC信息保存失败: %s", MesExtEnumUtil.PRODUCE_QC_STATUS.valueOfDescription(resultInt), fsmRouteDataService.handleFsmCfgOrDefault(reqBean, MesPcnEnumUtil.FSM_CFG.FSM_EXCEPTION_MSG.getCode()));
            this.sendMessage(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.ERROR.getValue()), webMsg, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            this.cacheException(reqBean, reqBean.getStepName(), webMsg, e, true);
            foundExThrowNoShowMsg();
        }

        return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), stepResult, String.format("加工[%s] NC信息保存成功!", MesExtEnumUtil.PRODUCE_QC_STATUS.valueOfDescription(resultInt)));
   }

    /**
     * 存加工异常记录
     * @param reqBean
     * @param productionPsOutContextList
     */
    private void saveProductResultException(StationRequestBean reqBean, List<MesProductionPsOutContext> productionPsOutContextList, List<MesProductionPartContext> productionPartContextList, Integer productResult) {
        String defectTypeCode = MesEnumUtil.DEFECT_TYPE_CODE.DETERMIND.getValue();
        productionPsOutContextList.forEach(mesProduceSn -> {
            String productVersion = null;
            List<MesProductionPartContext> mesProductionPartContextList = CollectionUtils.isEmpty(productionPartContextList) ? null :
                    productionPartContextList.stream().filter(mesProductionPartContext -> Objects.equal(mesProduceSn.getForeignKey(),mesProductionPartContext.getForeignKey())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(mesProductionPartContextList)) {
                productVersion = mesProductionPartContextList.get(0).getProductVersion();
            }
            MesNcProcessingInputModel model = new MesNcProcessingInputModel();
            MesDefectType mesDefectType = new MesDefectType();
            mesDefectType.setBackDefect(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
            mesDefectType.setDefectTypeCode(defectTypeCode);
            mesDefectType.setDefectTypeName(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getDescription());
            //mesDefectType.setDefectType(MesExtEnumUtil.MES_DEFECT_TYPE);
            model.setSn(mesProduceSn.getProductSn());
            model.setPerson(mesDefectType);
            model.setUserName(reqBean.getUserInfo());

            MesPartInspection partInspection = new MesPartInspection();

            Long id = snowflakeIdMaker.nextId();
            partInspection.setWorkCenterCode(reqBean.getWorkCenterCode());
            partInspection.setSourceType(MesExtEnumUtil.PART_INSPECTION_SOURCE_TYPE.SINGLE.getValue());


            partInspection.setPartNo(mesProduceSn.getPartNo());
            partInspection.setPartName(mesProduceSn.getPartName());
            partInspection.setDefectTypeCode(mesDefectType.getDefectTypeCode());
            partInspection.setInspectionDate(TimeTool.getToday());
            partInspection.setLotNo(mesProduceSn.getLotNo());
            if (productResult.compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.SCRAP.getValue()) == 0) {
                partInspection.setNcStatus(MesExtEnumUtil.PART_INSPECTION_NC_STATUS.SCRAP.getValue());
            } else {
                partInspection.setNcStatus(MesExtEnumUtil.PART_INSPECTION_NC_STATUS.CREATE.getValue());
            }
            partInspection.setRejectQty(mesProduceSn.getQty());
            partInspection.setShiftCode(mesProduceSn.getShiftCode());
            partInspection.setSn(mesProduceSn.getProductSn());
            partInspection.setOrganizeCode(reqBean.getOrganizeCode());
            partInspection.setQty(mesProduceSn.getQty());
            partInspection.setInspectionStatus(MesExtEnumUtil.PART_INSPECTION_STATUS.FAIL.getValue());
            partInspection.setId(id);
            ConvertBean.serviceModelInitialize(partInspection, reqBean.getUserInfo());

            MesPartInspectionDetail mesPartInspectionDetail = new MesPartInspectionDetail();
            mesPartInspectionDetail.setPid(id);
            mesPartInspectionDetail.setStatus(MesExtEnumUtil.PART_INSPECTION_NC_STATUS.CREATE.getValue());
            mesPartInspectionDetail.setDefectTypeCode(mesDefectType.getDefectTypeCode());
            mesPartInspectionDetail.setDefectTypeName(mesDefectType.getDefectTypeName());
            model.setPartInspection(partInspection);
            model.setType(MesExtEnumUtil.EQUIP_VARIABLE_CFG_CATEGORY.PRODUCT_SUSPICIOUS.getCode());
            model.setProductVersion(productVersion);

            if (Objects.equal(MesExtEnumUtil.EQUIP_VARIABLE_CFG_CATEGORY.PRODUCT_SCRAP.getCode(), productResult)) {
                model.setType(MesExtEnumUtil.NC_TYPE.SCRAP.getValue());
            }
            MesPartSap mesPartSap = new MesPartSap();
            mesPartSap.setPartNo(mesProduceSn.getPartNo());

            model.setPart(mesPartSap);
            model.setPartInspectionDetailList(Arrays.asList(mesPartInspectionDetail));
            if (productResult.compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.SCRAP.getValue()) == 0) {
                ncProcessingService.saveNc(model, reqBean.getOrganizeCode(), true);
            } else {
                MesPartInspectionInputModel inspectModel = new MesPartInspectionInputModel();
                inspectModel.setPart(mesPartSap);
                inspectModel.setLotNo(mesProduceSn.getLotNo());
                inspectModel.setPartNo(mesProduceSn.getPartNo());
                inspectModel.setQty(mesProduceSn.getQty());
                inspectModel.setSn(mesProduceSn.getProductSn());
                inspectModel.setWorkCenterCode(mesProduceSn.getWorkCenterCode());
                inspectModel.setPartInspection(partInspection);
                inspectModel.setShiftCode(mesProduceSn.getShiftCode());
                inspectModel.setProductVersion(productVersion);
                inspectModel.setUserInfo(reqBean.getUserInfo());
                inspectModel.setSourceType(MesExtEnumUtil.PART_INSPECTION_SOURCE_TYPE.SINGLE.getValue());
                inputDefectRecordService.saveSusPartInspection(inspectModel, reqBean.getOrganizeCode());
            }
        });
    }
}
