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

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.actor.shipping.dispatch.IFsmCommonService;
import cn.estsh.i3plus.mes.pcn.util.StationKvBeanUtil;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrder;
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.List;
import java.util.stream.Collectors;

/**
 * @Description : 生产工单顺序防错工步 【非排序】
 * @Author : wangjie
 **/
@Slf4j
@Service("mesProductSeqCheckNosortStepService")
public class MesProductSeqCheckNosortStepService extends MesProductSeqCheckStepService {

    @Autowired
    private IFsmCommonService fsmCommonService;

    @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<MesProductionPartContext> productionPartContextList = productionDispatchContextStepService.getProductionPartContext(reqBean);

        //验证是否存在加工单
        if (!checkIsExistWorkOrder(productionPartContextList)) return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "当前无加工单信息,无需进行加工单顺序防错验证!");

        //验证工位是否设置需要顺序防错
        if (!isNeedCheckProductSeq(productionPartContextList))
            return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, String.format("生产线[%s]工位[%s]未设置顺序防错,无需进行加工单顺序防错验证!", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode()));

        //验证是否存在工艺强过码, 存在则保存 并返回强过的加工单
        List<String> workOrderNoList2Jump = doHandleCraftJumpCode(reqBean, productionPartContextList);
        if (!CollectionUtils.isEmpty(workOrderNoList2Jump))
            return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().scanInfo(workOrderNoList2Jump.toString()), stepResult, String.format("加工单%s跳过顺序防错验证成功!", workOrderNoList2Jump.toString()));

        //验证是否已经全部通过
        if (!isExistNeedCheckProductSeq(productionPartContextList)) return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean, stepResult, "加工单均已通过顺序防错验证!");

        //顺序防错验证处理
        doHandleProductSeqCheck(reqBean, resultBean, stepResult, productionProcessContext, productionPartContextList);

        //删除手动选择的腔数及工单信息上下文
        if (!stepResult.isCompleted()) productionProcessContextStepService.removeFunctionChooseCavityOrderContext(reqBean);
        else {
            //保存选择/扫描/读取的腔数及工单信息上下文 [并标记已验证过顺序防错]
            productionProcessContextStepService.dispatchFunctionChooseCavityOrderContext(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.CRAFT_JUMP_CODE, "是否已验证顺序防错", CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr()),
                    new StationKvBean(MesPcnExtConstWords.WORK_ORDER_NO, "加工单", productionPartContextList.stream().filter(o -> null != o).map(MesProductionPartContext::getWorkOrderNo).collect(Collectors.joining(MesPcnExtConstWords.SEMICOLON)))));
        }

        return stepResult;

    }

    //顺序防错验证处理
    private void doHandleProductSeqCheck(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult, MesProductionProcessContext productionProcessContext, List<MesProductionPartContext> productionPartContextList) {

        //非排序顺序防错级别配置[工位参数]
        String checkProductSeqCfg = getCheckProductSeqCfg(reqBean);

        //当是零件级别的配置的时候 搜集工单号 去重
        List<String> filterWorkOrderNoList = StringUtils.isEmpty(checkProductSeqCfg) ? null :
                (productionPartContextList.stream().filter(o -> (null != o && o.getIsFinishCode().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0))
                        .map(MesProductionPartContext::getWorkOrderNo).collect(Collectors.toList())).stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());

        List<String> workOrderNoList = new ArrayList<>();

        for (MesProductionPartContext productionPartContext : productionPartContextList) {

            if (null == productionPartContext) continue;
            if (StringUtils.isEmpty(productionPartContext.getWorkOrderNo())) continue;
            if (productionPartContext.getCheckSeqResult().compareTo(MesPcnExtConstWords.ZERO) != 0) continue;

            //顺序防错验证
            Boolean result = doProductSeqCheckNosort(reqBean, stepResult, productionProcessContext, productionPartContext, checkProductSeqCfg, filterWorkOrderNoList);

            productionPartContext.checkSeqResult(!result ? CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue() : CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());

            workOrderNoList.add(productionPartContext.getWorkOrderNo());

        }

        //保存上下文产出零件信息
        productionDispatchContextStepService.dispatchProductionPartContext(reqBean, productionPartContextList);

        if (stepResult.isCompleted()) this.sendMessage(reqBean, resultBean.writeDbLog().scanInfo(workOrderNoList.toString()), String.format("加工单%s顺序防错验证成功!", workOrderNoList.toString()), MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
        else this.sendMessage(reqBean, resultBean.writeDbLog().scanInfo(workOrderNoList.toString()), stepResult.getMsg(), MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);

    }

    //非排序顺序防错级别配置[工位参数]
    private String getCheckProductSeqCfg(StationRequestBean reqBean) {
        return fsmCommonService.checkWcpcMapIsMatchValue(reqBean, MesPcnExtConstWords.CHECK_PRODUCT_SEQ_CFG, CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr());
    }

    //顺序防错验证 【非排序】
    private Boolean doProductSeqCheckNosort(StationRequestBean reqBean, StepResult stepResult, MesProductionProcessContext productionProcessContext,
                                            MesProductionPartContext productionPartContext, String checkProductSeqCfg, List<String> workOrderNoList) {

        String message = StringUtils.isEmpty(stepResult.getMsg()) ? MesPcnExtConstWords.EMPTY : stepResult.getMsg() + MesPcnExtConstWords.SEMICOLON;

        //根据生产工单顺序号,生产线代码查询上一个生产工单信息
        MesWorkOrder workOrder;
        if (StringUtils.isEmpty(checkProductSeqCfg)) {
            workOrder = workOrderExtService.getWorkOrder(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), productionPartContext.getProductSeq());
        } else if (workOrderNoList.size() == 1) {
            //增加零件号条件
            workOrder = workOrderExtService.getWorkOrderByPart(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), productionPartContext.getProductSeq(), productionPartContext.getPartNo());
        } else {
            //增加零件号条件, 查询时排除 搜集的其他腔的工单号
            workOrder = workOrderExtService.getWorkOrderByPartAndOrderNo(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), productionPartContext.getProductSeq(),  productionPartContext.getPartNo(), filterWorkOrderNoList(workOrderNoList, productionPartContext.getWorkOrderNo()));
        }

        if (null == workOrder) return true;

        if (workOrder.getWorkOrderStatus().compareTo(MesExtEnumUtil.ORDER_STATUS.CLOSE.getValue()) >= 0) return true;

        return stepResult.isCompleted(false).msg(String.format("%s加工单[%s]生产顺序号[%s]顺序防错验证失败,前一个加工单[%s]生产顺序号[%s]工单状态[%s]",
                message, productionPartContext.getWorkOrderNo(), productionPartContext.getProductSeq(), workOrder.getWorkOrderNo(), workOrder.getProductSeq(), MesExtEnumUtil.ORDER_STATUS.valueOfDescription(workOrder.getWorkOrderStatus()))).isCompleted();

    }

    //搜集其他腔的工单号
    private List<String> filterWorkOrderNoList(List<String> workOrderNoList, String workOrderNo) {
        return workOrderNoList.stream().filter(o -> (!StringUtils.isEmpty(o) && !o.equals(workOrderNo))).collect(Collectors.toList());
    }

}
