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

import cn.estsh.i3plus.ext.mes.pcn.api.base.ISxWorkOrderExtService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesWorkOrderExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.WorkOrderExtModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtEnumUtil;
import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmCommonService;
import cn.estsh.i3plus.mes.pcn.api.iservice.base.IModuleService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.base.BaseStepService;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.platform.common.util.MesPcnConstWords;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
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.impp.framework.boot.util.SpringContextsUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;

/**
 * @Description : 嘉兴初始化工单工步
 * @Reference :
 * @Author : wangjie
 * @CreateDate : 2019-07-11
 * @Modify:
 **/
@Slf4j
@Service("jxInitOrderStepService")
public class JxInitOrderStepService extends BaseStepService {

    @Autowired
    private IFsmCommonService fsmCommonService;

    @Autowired
    private ISxWorkOrderExtService workOrderExtService;

    @Override
    public StepResult execute(StationRequestBean reqBean) {

        log.info("工厂{}生产线{}工位{}: --- STEP EXECUTE --- JxInitOrderStepService --- START --- ", reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode());

        StepResult stepResult = StepResult.getSuccessComplete();

        StationResultBean resultBean = new StationResultBean();

        String curExecWorkOrderNo = (String) doHandleModuleObjectMethod(reqBean, resultBean, MesPcnExtConstWords.doHandleCurExecWorkOrder, 1, null);
        String selectWorkOrderNo = (String) doHandleModuleObjectMethod(reqBean, resultBean, MesPcnExtConstWords.doHandleSelectWorkOrderNo, 1, null);

        String curExecWorkOrderNoReal = curExecWorkOrderNo;
        String selectWorkOrderNoReal = (StringUtils.isEmpty(selectWorkOrderNo) || !selectWorkOrderNo.contains(MesPcnExtConstWords.COLON)) ? selectWorkOrderNo : selectWorkOrderNo.split(MesPcnExtConstWords.COLON)[1];

        if (StringUtils.isEmpty(selectWorkOrderNoReal) && StringUtils.isEmpty(curExecWorkOrderNoReal)) execSendGuideAndThrowEx(reqBean, resultBean, "请选择启动状态的生产工单!");

        if (!StringUtils.isEmpty(selectWorkOrderNoReal)) doHandleModuleObjectMethod(reqBean, resultBean, MesPcnExtConstWords.doHandleSelectWorkOrderNo, 3, null);
        if (!StringUtils.isEmpty(selectWorkOrderNoReal) && !StringUtils.isEmpty(curExecWorkOrderNoReal)) {
            if (selectWorkOrderNoReal.equals(curExecWorkOrderNoReal)) selectWorkOrderNoReal = null;
            else curExecWorkOrderNoReal = null;
        }

        MesWorkOrderExt workOrderExt = null;

        outerLoop:
        if (stepResult.isCompleted() && !StringUtils.isEmpty(selectWorkOrderNoReal)) {
            workOrderExt = workOrderExtService.getWorkOrderExtByOrderNo(reqBean.getOrganizeCode(), selectWorkOrderNoReal);
            String suffix = String.format("%s[%s]", !selectWorkOrderNo.contains(MesPcnExtConstWords.COLON) ?
                    "选择的工单号" : (selectWorkOrderNo.contains(MesPcnExtConstWords.TMP_ORDER) ? "临时工单号" : "回退工单号"), selectWorkOrderNoReal);

            curExecWorkOrderNoReal = checkSelectOrderIsValidCenter(reqBean, stepResult, workOrderExt, curExecWorkOrderNo, suffix);
            if (!stepResult.isCompleted()) break outerLoop;

            curExecWorkOrderNoReal = checkWorkOrderExtIsValid(stepResult, workOrderExt, curExecWorkOrderNo, suffix);
            if (!stepResult.isCompleted()) break outerLoop;

            curExecWorkOrderNoReal = doCacheCurExecWorkOrderNo(reqBean, resultBean, stepResult, selectWorkOrderNoReal, curExecWorkOrderNo, suffix);
            if (!stepResult.isCompleted()) break outerLoop;

            if (selectWorkOrderNo.contains(MesPcnExtConstWords.TMP_ORDER) && !StringUtils.isEmpty(curExecWorkOrderNo))
                doHandleModuleObjectMethod(reqBean, resultBean, MesPcnExtConstWords.doHandleSelectWorkOrderNo, 2, new StringJoiner(MesPcnExtConstWords.COLON).add(MesPcnExtConstWords.BACK_ORDER).add(curExecWorkOrderNo).toString());
        }

        if (!stepResult.isCompleted()) reqBean.setScanInfo(null);

        if (!StringUtils.isEmpty(curExecWorkOrderNoReal)) {
            workOrderExt = workOrderExtService.getWorkOrderExtByOrderNo(reqBean.getOrganizeCode(), curExecWorkOrderNoReal);
            checkWorkOrderExtIsValid(stepResult, workOrderExt, curExecWorkOrderNo,
                    String.format("%s此前操作的工单号[%s]", stepResult.isCompleted() ? MesPcnExtConstWords.EMPTY : stepResult.isCompleted(true).getMsg(), curExecWorkOrderNoReal));
        }

        if (!StringUtils.isEmpty(stepResult.getMsg()))
            this.sendMessage(reqBean, resultBean, !stepResult.isCompleted() ? stepResult.getMsg() : String.format("%s可在此前操作的工单号[%s]下继续操作!", stepResult.getMsg(), curExecWorkOrderNoReal),
                    MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, !stepResult.isCompleted() ? MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT : MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);

        if (null == workOrderExt || !stepResult.isCompleted()) execSendGuideAndThrowEx(reqBean, resultBean, "请选择启动状态的生产工单!");

        cacheOrderModel(reqBean, workOrderExt);

        if (StringUtils.isEmpty(selectWorkOrderNo) || !selectWorkOrderNo.contains(MesPcnExtConstWords.TMP_ORDER)) reqBean.setScanInfo(null);

        log.info("工厂{}生产线{}工位{}: --- STEP EXECUTE --- JxInitOrderStepService --- SUCCESS --- ", reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode());

        return stepResult;
    }

    private String checkSelectOrderIsValidCenter(StationRequestBean reqBean, StepResult stepResult, MesWorkOrderExt workOrderExt, String curExecWorkOrderNo, String suffix) {

        if (null == workOrderExt) stepResult.isCompleted(false).msg(String.format("%s对应的工单信息不存在!", suffix));

        if (stepResult.isCompleted() && !reqBean.getWorkCenterCode().equals(workOrderExt.getWorkCenterCode()))
            stepResult.isCompleted(false).msg(String.format("%s关联生产线[%s]与当前生产线[%s]不一致,不支持在此工位操作!", suffix, workOrderExt.getWorkCenterCode(), reqBean.getWorkCenterCode()));

        return !stepResult.isCompleted() ? curExecWorkOrderNo : null;

    }

    private String checkWorkOrderExtIsValid(StepResult stepResult, MesWorkOrderExt workOrderExt, String curExecWorkOrderNo, String suffix) {

        if (MesPcnExtEnumUtil.WORK_ORDER_STATUS.OPEN.getValue() != workOrderExt.getWorkOrderStatus())
            stepResult.isCompleted(false).msg(String.format("%s状态[%s],不支持在此工位操作!", suffix, MesPcnExtEnumUtil.WORK_ORDER_STATUS.valueOfDescription(workOrderExt.getWorkOrderStatus())));

        if (stepResult.isCompleted() && MathOperation.compareTo(workOrderExt.getQty(), new Double(0)) <= 0)
            stepResult.isCompleted(false).msg(String.format("%s计划数量为[0],不支持在此工位操作!", suffix));

        return !stepResult.isCompleted() ? curExecWorkOrderNo : null;

    }

    private String doCacheCurExecWorkOrderNo(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult, String selectWorkOrderNo, String curExecWorkOrderNo, String suffix) {
        Boolean flag = (Boolean) doHandleModuleObjectMethod(reqBean, resultBean, MesPcnExtConstWords.doHandleCurExecWorkOrder, 2, selectWorkOrderNo);
        if (!flag) stepResult.isCompleted(false).msg(String.format("%s初始化失败!", suffix));
        else execStateModule(reqBean, resultBean);

        if (stepResult.isCompleted()) this.sendMessage(reqBean, resultBean, String.format("%s初始化成功!", suffix), MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);

        return !stepResult.isCompleted() ? curExecWorkOrderNo : null;
    }

    private void cacheOrderModel(StationRequestBean reqBean, MesWorkOrderExt workOrderExt) {
        WorkOrderExtModel orderModel = new WorkOrderExtModel();
        BeanUtils.copyProperties(workOrderExt, orderModel, MesPcnExtConstWords.ID);
        reqBean.getDataMap().put(MesPcnExtConstWords.WORK_ORDER, orderModel);
    }

    private Object doHandleModuleObjectMethod(StationRequestBean reqBean, StationResultBean resultBean, String methodStr, Integer flag, String value) {
        fsmCommonService.checkWcpcMapForDoScan(reqBean);
        try {
            IModuleService moduleService = (IModuleService) SpringContextsUtil.getBean(reqBean.getWcpcMap().get(MesPcnConstWords.MODULE_OBJECT));
            Method method = moduleService.getClass().getDeclaredMethod(methodStr, reqBean.getClass(), Integer.class, String.class);
            method.setAccessible(true);
            return method.invoke(moduleService, reqBean, flag, value);
        } catch (Exception e) {
            execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("执行展示组件内部方法[%s]参数[flag=%s,value=%s]出现异常:%s", methodStr, flag, value, e.getMessage()));
            return null;
        }
    }

    private Object execStateModule(StationRequestBean reqBean, StationResultBean resultBean) {
        fsmCommonService.checkWcpcMapForDoScan(reqBean);
        try {
            IModuleService moduleService = (IModuleService) SpringContextsUtil.getBean(reqBean.getWcpcMap().get(MesPcnConstWords.MODULE_OBJECT));
            Method method = moduleService.getClass().getDeclaredMethod(MesPcnExtConstWords.execStateModule, reqBean.getClass(), List.class, Map.class);
            method.setAccessible(true);
            return method.invoke(moduleService, reqBean, null, null);
        } catch (Exception e) {
            execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("执行展示组件内部方法[%s]出现异常:%s", MesPcnExtConstWords.execStateModule, e.getMessage()));
            return null;
        }
    }

}
