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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionCustomContextStepService;
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.MesCellEquipContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPartContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionProcessContext;
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.StationKvBeanUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesPart;
import cn.estsh.i3plus.pojo.mes.model.StationKvBean;
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 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.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description : 扫描产成零件工步
 * @Author : wangjie
 **/
@Slf4j
@Service("mesProductionPartNoScanStepService")
public class MesProductionPartNoScanStepService extends BaseStepService {

    @Autowired
    private IMesProductionProcessContextStepService productionProcessContextStepService;

    @Autowired
    private IMesProductionDispatchContextStepService productionDispatchContextStepService;

    @Autowired
    private IMesProductionCustomContextStepService productionCustomContextStepService;

    @Autowired
    private MesPartDataMapSaveStepService partDataMapSaveStepService;

    @Override
    public StepResult guide(StationRequestBean reqBean) {

        productionCustomContextStepService.sendStepContextMessage(reqBean);

        return stepSuccessCompleteAndSendGuideReturn(reqBean, new StationResultBean().writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), "请扫描产成零件!");

    }

    @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);

        //扫描信息置空
        String scanInfo = reqBean.resetScanInfo(reqBean.getScanInfo());

        //获取手动选择的腔数及零件信息上下文
        List<StationKvBean> chooseCavityPart = productionProcessContextStepService.getFunctionChooseCavityPartContext(reqBean);

        if (CollectionUtils.isEmpty(chooseCavityPart) && StringUtils.isEmpty(scanInfo)) stepSendGuideAndThrowEx(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), "请扫描产成零件!");

        List<MesProductionPartContext> productionPartContextList;
        List<String> readList;
        List<String> partNoList;
        String cellMessageSorce = null;
        String suffix = null;

        if (!CollectionUtils.isEmpty(chooseCavityPart)) {

            //工位信息来源
            cellMessageSorce = chooseCavityPart.stream().filter(o -> (null != o && o.getKey().equals(MesPcnExtConstWords.CELL_MESSAGE_SOURCE))).findFirst().get().getValue();

            //搜集读取的产成零件编码
            readList = new ArrayList<>(Arrays.asList(chooseCavityPart.stream().filter(o -> (null != o && o.getKey().equals(MesPcnExtConstWords.PART_NO))).findFirst().get().getValue().split(MesPcnExtConstWords.SEMICOLON)));

            //发送工步内容
            scanInfo = chooseCavityPart.stream().filter(o -> (null != o && !o.getKey().equals(MesPcnExtConstWords.CELL_MESSAGE_SOURCE))).map(o -> o.getName() + MesPcnExtConstWords.SQUARE_BRACKETS_L + o.getValue() + MesPcnExtConstWords.SQUARE_BRACKETS_R).collect(Collectors.joining(MesPcnExtConstWords.SEMICOLON));
            productionCustomContextStepService.sendStepContextMessage(reqBean, scanInfo, MesExtEnumUtil.CELL_MESSAGE_SOURCE.getByValue(Integer.valueOf(cellMessageSorce)));

            //零件编码去重
            partNoList = readList.stream().filter(o -> (!StringUtils.isEmpty(o) && !o.equals(productionProcessContext.getFinishCode()))).distinct().collect(Collectors.toList());

            //验证零件编码有效性
            if (!CollectionUtils.isEmpty(partNoList)) partDataMapSaveStepService.savePartDataMap(reqBean, resultBean, stepResult, partNoList, true, false);

            //验证失败,删除手动选择的腔数及零件信息上下文
            if (CollectionUtils.isEmpty(partNoList) || !stepResult.isCompleted()) productionProcessContextStepService.removeFunctionChooseCavityPartContext(reqBean);
            else suffix = String.format("%s:%s", MesExtEnumUtil.CELL_MESSAGE_SOURCE.valueOfDescription(Integer.valueOf(cellMessageSorce)), scanInfo);

        } else {

            //发送工步内容
            productionCustomContextStepService.sendStepContextMessage(reqBean, scanInfo, MesExtEnumUtil.CELL_MESSAGE_SOURCE.SCAN);

            //获取上下文产成零件信息
            productionPartContextList = productionDispatchContextStepService.getProductionPartContext(reqBean);

            //搜集上下文产成零件编码
            readList = CollectionUtils.isEmpty(productionPartContextList) ? new ArrayList<>() : productionPartContextList.stream().filter(o -> !StringUtils.isEmpty(o)).map(MesProductionPartContext::getPartNo).collect(Collectors.toList());

            //合并当前扫描的零件编码
            readList.add(scanInfo);

            //零件编码去重
            partNoList = readList.stream().filter(o -> (!StringUtils.isEmpty(o) && !o.equals(productionProcessContext.getFinishCode()))).distinct().collect(Collectors.toList());

            //验证零件编码有效性
            if (!CollectionUtils.isEmpty(partNoList)) partDataMapSaveStepService.savePartDataMap(reqBean, resultBean, stepResult, partNoList, true, true);

            if (stepResult.isCompleted()) suffix = String.format("%s:%s[%s]", MesExtEnumUtil.CELL_MESSAGE_SOURCE.SCAN.getDescription(), !scanInfo.equals(productionProcessContext.getFinishCode()) ? "零件编码" : "空腔嘛", scanInfo);

        }

        //验证失败
        if (!stepResult.isCompleted()) return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, stepResult.getMsg());

        //封装产出零件信息信息
        productionPartContextList = partDataMapSaveStepService.getProductionPartContext(reqBean, productionProcessContext, new ArrayList<>(), (Map<String, MesPart>) stepResult.getObj(), readList);

        //验证是否全部为空腔
        if (partDataMapSaveStepService.checkIsAllFinishCode(productionPartContextList)) return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "当前产成零件信息全部为空腔,已清除当前的空腔数据!");

        //保存设备当前一轮工序的产出零件信息
        productionDispatchContextStepService.dispatchProductionPartContext(reqBean, productionPartContextList);

        //扫描模式下判断当前是否满足设备腔数
        if (CollectionUtils.isEmpty(chooseCavityPart)) {
            MesCellEquipContext cellEquipContext = productionProcessContext.getCurCellEquip();
            if (cellEquipContext.getCavity().compareTo(productionPartContextList.size()) > 0) return stepDynamicsCompleteAndSendMsgReturn(
                    reqBean, resultBean.writeDbLog().scanInfo(scanInfo),
                    stepResult, false, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT,
                    String.format("当前%s验证成功,已知腔数[%s],还需要再连续扫描[%s]次产成零件!", suffix, cellEquipContext.getCavity(), cellEquipContext.getCavity() - productionPartContextList.size()));
        }

        //存储展示组件MODULE_CONTENT内容
        productionDispatchContextStepService.dispatchModuleContentContext(reqBean, partDataMapSaveStepService.getModuleContextData2PartNo(reqBean, productionPartContextList));

        //缓存产成零件编码到上下文得基础信息中, 下次开模即可无须再次选择或者扫描产成零件编码
        if (CollectionUtils.isEmpty(chooseCavityPart) || !cellMessageSorce.equals(MesExtEnumUtil.CELL_MESSAGE_SOURCE.READ.getValueStr())) {
            productionProcessContextStepService.dispatchFunctionChooseCavityPartContext(reqBean, StationKvBeanUtil.addStationKvBeanList(new ArrayList<>(),
                    new StationKvBean(MesPcnExtConstWords.CAVITY, "腔数", String.valueOf(productionPartContextList.size())),
                    new StationKvBean(MesPcnExtConstWords.CELL_MESSAGE_SOURCE, "工位信息来源", MesExtEnumUtil.CELL_MESSAGE_SOURCE.READ.getValueStr()),
                    new StationKvBean(MesPcnExtConstWords.PART_NO, "零件编码", productionPartContextList.stream().filter(o -> null != o).map(MesProductionPartContext::getPartNo).collect(Collectors.joining(MesPcnExtConstWords.SEMICOLON)))));
        }

        return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().scanInfo(scanInfo), stepResult, String.format("当前%s验证成功!", suffix));

    }

}
