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

import cn.estsh.i3plus.ext.mes.pcn.api.base.IMesProdShiftRecordService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProduceSnExtService;
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.apiservice.serviceimpl.step.method.MesPartDataMapSaveStepService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProdShiftContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionProcessContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPsOutContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.mes.pcn.util.StringUtil;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesPart;
import cn.estsh.i3plus.pojo.mes.bean.MesProduceSn;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkCell;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkCenter;
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.repository.MesProduceSnRepository;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import com.alibaba.fastjson.JSONObject;
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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description : 保存零件条码信息工步
 * @Author : wangjie
 **/
@Slf4j
@Service("mesProductSnSaveStepService")
public class MesProductSnSaveStepService extends BaseStepService {

    @Autowired
    private IMesProductionProcessContextStepService productionProcessContextStepService;

    @Autowired
    private IMesProductionDispatchContextStepService productionDispatchContextStepService;

    @Autowired
    private MesPartDataMapSaveStepService partDataMapSaveStepService;

    @Autowired
    private IMesProduceSnExtService produceSnExtService;

    @Autowired
    private MesProduceSnRepository produceSnRepository;

    @Autowired
    private IMesProdShiftRecordService prodShiftRecordService;

    @Override
    public StepResult execute(StationRequestBean reqBean) {

        StationResultBean resultBean = new StationResultBean();

        StepResult stepResult = StepResult.getSuccessComplete();

        //获取上下文信息
        MesProductionProcessContext productionProcessContext = productionProcessContextStepService.dispatchCurCellEquipment(reqBean);

        //配置错误 抛出异常
        if (!productionProcessContext.getSuccess()) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), productionProcessContext.getMessage());

        //存储生产过程上下文对象
        productionProcessContextStepService.dispatchProductionProcessContext(reqBean, productionProcessContext);

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

        if (CollectionUtils.isEmpty(productionPsOutContextList)) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), "当前不存在产出零件条码信息,请重置工序解决!");

        //获取生产线的当前班组班次信息
        MesProdShiftContext prodShiftContext = prodShiftRecordService.getMesProdShiftKvBean(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode());

        if (null == prodShiftContext) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), "当前不存在生产开班记录,请重新开班!");

        //获取上下文零件数据信息
        List<String> partNoList = (productionPsOutContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getPartNo()))).map(MesProductionPsOutContext::getPartNo).collect(Collectors.toList())).stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());
        partDataMapSaveStepService.savePartDataMap(reqBean, resultBean, stepResult, partNoList, false, false);

        //获取上下文加工结果
        String productResult = productionDispatchContextStepService.getProductResultContext(reqBean);
        Map<String, MesPart> partMap = (Map<String, MesPart>) stepResult.getObj();

        MesWorkCenter workCenter = productionProcessContext.getWorkCenter();
        MesWorkCell workCell = productionProcessContext.getWorkCell();

        productionPsOutContextList.stream().filter(o -> null != o).forEach(o -> saveProduceSnData(reqBean, resultBean, productionProcessContext, o, partMap, prodShiftContext, productResult, workCenter, workCell));

        //保存上下文产出条码数据信息集合
        productionDispatchContextStepService.dispatchProductionPsOutContext(reqBean, productionPsOutContextList);

        return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), stepResult, "保存零件条码成功!");

    }

    private MesProductionPsOutContext saveProduceSnData(StationRequestBean reqBean, StationResultBean resultBean, MesProductionProcessContext productionProcessContext, MesProductionPsOutContext productionPsOutContext,
                                           Map<String, MesPart> partMap, MesProdShiftContext prodShiftContext, String productResult, MesWorkCenter workCenter, MesWorkCell workCell) {

        //根据零件条码ID查询零件条码信息
        MesProduceSn produceSn = produceSnExtService.getProduceSn(reqBean.getOrganizeCode(), productionPsOutContext.getId());

        if (null == produceSn) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), String.format("请检查零件条码信息,产出零件条码[%s]ID[%s]信息不存在!", productionPsOutContext.getProductSn(), productionPsOutContext.getId()));

        //零件信息
        MesPart part = partMap.get(produceSn.getPartNo());

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

        productionPsOutContext.setAreaCode(reqBean.getAreaCode());
        propertyMap.put(MesPcnExtConstWords.AREA_CODE, productionPsOutContext.getAreaCode());

        productionPsOutContext.setWorkCenterCode(reqBean.getWorkCenterCode());
        propertyMap.put(MesPcnExtConstWords.WORK_CENTER_CODE, productionPsOutContext.getWorkCenterCode());

        productionPsOutContext.setWorkCellCode(reqBean.getWorkCellCode());
        propertyMap.put(MesPcnExtConstWords.WORK_CELL_CODE, productionPsOutContext.getWorkCellCode());

        productionPsOutContext.setRouteCode(reqBean.getRouteCode());
        propertyMap.put(MesPcnExtConstWords.ROUTE_CODE, productionPsOutContext.getRouteCode());

        productionPsOutContext.setProcessCode(reqBean.getProcessCode());
        propertyMap.put(MesPcnExtConstWords.PROCESS_CODE, productionPsOutContext.getProcessCode());

        productionPsOutContext.setCraftCode(productionProcessContext.getCraftCode());
        propertyMap.put(MesPcnExtConstWords.CRAFT_CODE, productionPsOutContext.getCraftCode());

        productionPsOutContext.setShiftCode(prodShiftContext.getShiftCode());
        propertyMap.put(MesPcnExtConstWords.SHIFT_CODE, productionPsOutContext.getShiftCode());

        productionPsOutContext.setShiftGroup(prodShiftContext.getShiftGroup());
        propertyMap.put(MesPcnExtConstWords.SHIFT_GROUP, productionPsOutContext.getShiftGroup());

        productionPsOutContext.setProcessLabelTemplate(part.getProcessLabelTemplate());
        propertyMap.put(MesPcnExtConstWords.PROCESS_LABEL_TEMPLATE, productionPsOutContext.getProcessLabelTemplate());

        productionPsOutContext.setProdLabelTemplate(part.getProductLabelTemplate());
        propertyMap.put(MesPcnExtConstWords.PROD_LABEL_TEMPLATE, productionPsOutContext.getProdLabelTemplate());

        productionPsOutContext.setCustLabelTemplate(part.getCustLabelTemplate());
        propertyMap.put(MesPcnExtConstWords.CUST_LABEL_TEMPLATE, productionPsOutContext.getCustLabelTemplate());

        ConvertBean.serviceModelUpdate(productionPsOutContext, reqBean.getUserInfo());
        propertyMap.put(MesPcnExtConstWords.MODIFY_DATE_TIME, productionPsOutContext.getModifyDatetime());
        propertyMap.put(MesPcnExtConstWords.MODIFY_USER, productionPsOutContext.getModifyUser());
        propertyMap.put(MesPcnExtConstWords.SYSTEM_SYNC_STATUS, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
        propertyMap.put(MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME, MesPcnExtConstWords.EMPTY);

        if (StringUtils.isEmpty(productionPsOutContext.getLotNo()) || !productionPsOutContext.getLotNo().equals(productionPsOutContext.getModifyDatetime().substring(0, 10))) {
            productionPsOutContext.setLotNo(productionPsOutContext.getModifyDatetime().substring(0, 10));
            propertyMap.put(MesPcnExtConstWords.LOT_NO, productionPsOutContext.getLotNo());
        }

        if (StringUtils.isEmpty(productionPsOutContext.getInWorkCenterTime())) {
            productionPsOutContext.setInWorkCenterTime(productionPsOutContext.getModifyDatetime());
            propertyMap.put(MesPcnExtConstWords.IN_WC_TIME, productionPsOutContext.getInWorkCenterTime());
        }

        if (!StringUtils.isEmpty(productResult) && Integer.valueOf(productResult).compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.QUALIFIED.getValue()) != 0) {
            productionPsOutContext.setQcStatus(Integer.valueOf(productResult));
            propertyMap.put(MesPcnExtConstWords.QC_STATUS, productionPsOutContext.getQcStatus());
        }

        //非排序 或者 排序的末道工位
        if (workCenter.getCenterType().compareTo(MesExtEnumUtil.WORK_CENTER_TYPE.NOSORT.getValue()) == 0 ||
                (!StringUtils.isEmpty(workCell.getIsEndWorkCell()) && workCell.getIsEndWorkCell().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0)) {
            productionPsOutContext.setSnStatus(MesExtEnumUtil.PRODUCE_SN_STATUS.OFFLINE.getValue());
            propertyMap.put(MesPcnExtConstWords.SN_STATUS, productionPsOutContext.getSnStatus());

            productionPsOutContext.setOutWorkCenterTime(productionPsOutContext.getModifyDatetime());
            propertyMap.put(MesPcnExtConstWords.OUT_WC_TIME, productionPsOutContext.getOutWorkCenterTime());
        } else {
            //排序非末道
            if (productionPsOutContext.getSnStatus().compareTo(MesExtEnumUtil.PRODUCE_SN_STATUS.PROCESSING.getValue()) != 0) {
                productionPsOutContext.setSnStatus(MesExtEnumUtil.PRODUCE_SN_STATUS.PROCESSING.getValue());
                propertyMap.put(MesPcnExtConstWords.SN_STATUS, productionPsOutContext.getSnStatus());
            }
        }

        String[] propertyName = new String[propertyMap.size()];
        Object[] propertyValue = new Object[propertyMap.size()];

        Integer index = 0;
        for (Map.Entry<String, Object> innerEntry : propertyMap.entrySet()) {
            if (null == innerEntry) continue;
            propertyName[index] = innerEntry.getKey();
            propertyValue[index] = innerEntry.getValue();
            index ++;
        }

        produceSnRepository.updateByPropertiesNoSync(new String[]{MesPcnExtConstWords.ID, MesPcnExtConstWords.ORGANIZE_CODE}, new Object[]{produceSn.getId(), reqBean.getOrganizeCode()}, propertyName, propertyValue);

        log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- PS:{} --- ID:{} --- QUERY:{} --- productResult:{} --- UPDATE:{}",
                reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(),
                StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), productionPsOutContext.getProductSn(), produceSn.getId(), JSONObject.toJSONString(produceSn), productResult, JSONObject.toJSONString(propertyMap));

        return productionPsOutContext;

    }

}
