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.api.busi.ISxThirdPartyPlcCollectDataJobService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.jx.IJxPlcExtService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.busi.station.jx.JxSnProcessingModuleService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesWorkOrderExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.SxThirdPartyPlcCollectDataModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.WorkOrderExtModel;
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.serviceimpl.base.BaseStepService;
import cn.estsh.i3plus.pojo.mes.bean.MesObjectCfg;
import cn.estsh.i3plus.pojo.mes.bean.MesPlc;
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 com.alibaba.fastjson.JSONObject;
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.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.stream.Collectors;

/**
 * @Description : 嘉兴条码加工采集生产数据工步
 * @Reference :
 * @Author : wangjie
 * @CreateDate : 2019-07-11
 * @Modify:
 **/
@Slf4j
@Service("jxSnProcessingCollectProductDataStepService")
public class JxSnProcessingCollectProductDataStepService extends BaseStepService {

    @Autowired
    private ISxWorkOrderExtService workOrderExtService;

    @Autowired
    private JxSnProcessingModuleService snProcessingModuleService;

    @Autowired
    private IJxPlcExtService plcExtService;

    @Autowired
    private IFsmCommonService fsmCommonService;

    @Override
    public StepResult execute(StationRequestBean reqBean) {

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

        StationResultBean resultBean = new StationResultBean();

        if (StringUtils.isEmpty(reqBean.getSerialNumber()) && StringUtils.isEmpty(reqBean.getProductSn())) return execNonCompleteAndSendMsgReturn(reqBean, resultBean, "入参缺少过程条码或产品条码!");

        String suffixSn = StringUtils.isEmpty(reqBean.getProductSn()) ? getManageCode(reqBean.getTray(), 1) : reqBean.getProductSn();
        String suffix = String.format("当前产品:%s[%s]", StringUtils.isEmpty(reqBean.getProductSn()) ? "管理编码" : "产品条码", suffixSn);

        Boolean result = (Boolean) reqBean.getDataMap().get(MesPcnExtConstWords.RESULT);

        if (null == result) execCollectProductData(reqBean, resultBean, suffix);

        String msg = (String) reqBean.getDataMap().get(MesPcnExtConstWords.INFO);

        reqBean.getDataMap().remove(MesPcnExtConstWords.RESULT);
        reqBean.getDataMap().remove(MesPcnExtConstWords.INFO);

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

        if (result) return execSuccessCompleteAndSendMsgReturn(reqBean, resultBean, String.format("%s检测数据采集完成!", suffix));
        else return execNonCompleteAndSendMsgReturn(reqBean, resultBean, String.format("%s检测数据采集失败!%s", suffix, msg));

    }

    private void execCollectProductData(StationRequestBean reqBean, StationResultBean resultBean, String suffix) {

        fsmCommonService.checkWcpcMapForDoScan(reqBean);

        String plcCodes = fsmCommonService.getAndCheckWcpcMapIsContainsKey(reqBean, reqBean.getWcpcMap(), MesPcnExtConstWords.PLC_CODE_UC);
        if (StringUtils.isEmpty(plcCodes)) foundExThrowNoShowMsg();

        String key = new StringJoiner(MesPcnExtConstWords.COLON).add(MesPcnExtConstWords.PRODUCT_DATA).add(reqBean.getOrganizeCode()).add(reqBean.getWorkCenterCode()).add(reqBean.getWorkCellCode()).toString();

        String[] plcCodeArr = checkPlcCodeIsValid(reqBean, resultBean, plcCodes, key);

        String plcCodeListStr = plcExtService.getCachedData(key, MesPcnExtConstWords.PLC_CODE_UC);
        List<String> plcCodeList = !StringUtils.isEmpty(plcCodeListStr) ? JSONObject.parseArray(plcCodeListStr, String.class) : doHandlePlcCodeList(reqBean, resultBean, key);

        List<String> plcCodeList2Cfg = checkObjectCfgIsValid(reqBean, resultBean, plcCodeList, key);

        doHandlePlcCodeList(reqBean, key, plcCodeListStr, plcCodeList, plcCodeList2Cfg);

        String curExecWorkOrderNo = getCurExecWorkOrderNo(reqBean, resultBean);

        WorkOrderExtModel orderModel = getWorkOrderExtModel(reqBean, resultBean, curExecWorkOrderNo);

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put(key, new SxThirdPartyPlcCollectDataModel().userInfo(reqBean.getUserInfo())
                .location(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode())
                .order(orderModel.getOrderNo(), orderModel.getPartNo(), orderModel.getPartNameRdd())
                .sn(reqBean.getSerialNumber(), reqBean.getProductSn()).manageCode(reqBean.getTray())
                .plcCode2Flag(plcCodeArr[0], plcCodeArr[1]).plcCode2DataList(plcCodeList)
                .timeOut(reqBean.getWcpcMap().get(MesPcnExtConstWords.TIME_OUT_CFG)));

        ((ISxThirdPartyPlcCollectDataJobService) SpringContextsUtil.getBean(MesPcnExtConstWords.SX_TPPC_SUFFIX + MesPcnExtConstWords.PRODUCT_DATA + MesPcnExtConstWords.SERVICE_SUFFIX)).doThirdPartyPlcCollectData(paramMap);

        execSendMsgAndThrowEx(reqBean, resultBean, String.format("%s检测数据正在采集中...", suffix));

    }

    private String[] checkPlcCodeIsValid(StationRequestBean reqBean, StationResultBean resultBean, String plcCodes, String key) {
        String[] plcCodeArr = plcCodes.split(MesPcnExtConstWords.COMMA);
        if (plcCodeArr.length != 2) execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("生产线[%s]工位[%s]工位参数[%s]维护的PLC代码[%s]无效!", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), MesPcnExtConstWords.PLC_CODE_UC, plcCodes));

        for (String plcCode : plcCodeArr) {
            MesPlc plc = plcExtService.getPlcData(reqBean.getOrganizeCode(), key, plcCode);
            if (null == plc || (StringUtils.isEmpty(plc.getChannel()) || StringUtils.isEmpty(plc.getDevice()) || StringUtils.isEmpty(plc.getTagAddress())))
                execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("生产线[%s]工位[%s]工位参数[%s]维护的PLC代码[%s]其中[%s]未配置有效的PLC信息!", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), MesPcnExtConstWords.PLC_CODE_UC, plcCodes, plcCode));
        }

        return plcCodeArr;
    }

    private List<String> doHandlePlcCodeList(StationRequestBean reqBean, StationResultBean resultBean, String key) {
        List<MesPlc> plcList = plcExtService.getPlcDbList(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode());
        plcList = CollectionUtils.isEmpty(plcList) ? null : plcList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getChannel()) && !StringUtils.isEmpty(o.getDevice()) && !StringUtils.isEmpty(o.getTagAddress()))).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(plcList)) execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("生产线[%s]工位[%s]未配置有效的数据位PLC信息!", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode()));
        plcList.forEach(o -> plcExtService.doCacheData(reqBean.getOrganizeCode(), key, o.getPlcCode(), JSONObject.toJSONString(o)));
        return plcList.stream().filter(o -> null != o).map(MesPlc::getPlcCode).collect(Collectors.toList());
    }

    private void doHandlePlcCodeList(StationRequestBean reqBean, String key, String plcCodeListStr, List<String> plcCodeList, List<String> plcCodeList2Cfg) {
        if (!StringUtils.isEmpty(plcCodeListStr) && (plcCodeList.containsAll(plcCodeList2Cfg) && plcCodeList2Cfg.containsAll(plcCodeList))) return;
        plcExtService.doCacheData(reqBean.getOrganizeCode(), key, MesPcnExtConstWords.PLC_CODE_UC, JSONObject.toJSONString(plcCodeList2Cfg));
    }

    private List<String> checkObjectCfgIsValid(StationRequestBean reqBean, StationResultBean resultBean, List<String> plcCodeList, String key) {
        String value = plcExtService.getCachedData(key, MesPcnExtConstWords.OBJECT_CODE_UC);
        List<MesObjectCfg> objectCfgList = !StringUtils.isEmpty(value) ? JSONObject.parseArray(value, MesObjectCfg.class) : getObjectCfgDbList(reqBean, resultBean, plcCodeList);

        List<String> plcCodeList2ObjectCfg = CollectionUtils.isEmpty(objectCfgList) ? null : objectCfgList.stream().filter(o -> null != o).map(MesObjectCfg::getPlcCode).collect(Collectors.toList());
        plcCodeList2ObjectCfg = CollectionUtils.isEmpty(plcCodeList2ObjectCfg) ? null : plcCodeList2ObjectCfg.stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());

        if (CollectionUtils.isEmpty(plcCodeList2ObjectCfg)) execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("生产线[%s]工位[%s]配置的数据位PLC信息未关联有效的对象结构信息!", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode()));

        if (StringUtils.isEmpty(value)) plcExtService.doCacheData(reqBean.getOrganizeCode(), key, MesPcnExtConstWords.OBJECT_CODE_UC, JSONObject.toJSONString(objectCfgList));

        List<String> plcCodeList2Cfg = objectCfgList.stream().filter(o -> null != o).map(MesObjectCfg::getPlcCode).collect(Collectors.toList());
        return plcCodeList2Cfg.stream().filter(o -> null != o).distinct().collect(Collectors.toList());
    }

    private List<MesObjectCfg> getObjectCfgDbList(StationRequestBean reqBean, StationResultBean resultBean, List<String> plcCodeList) {
        List<MesObjectCfg> objectCfgList = plcExtService.getObjectCfgDbList(reqBean.getOrganizeCode(), plcCodeList);
        if (CollectionUtils.isEmpty(objectCfgList)) execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("生产线[%s]工位[%s]配置的数据位PLC信息未维护有效的对象结构信息!", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode()));
        return objectCfgList;
    }

    private String getCurExecWorkOrderNo(StationRequestBean reqBean, StationResultBean resultBean) {
        String curExecWorkOrderNo = (String) snProcessingModuleService.doHandleCurExecWorkOrder(reqBean, 1, null);
        if (StringUtils.isEmpty(curExecWorkOrderNo)) execExpSendMsgAndThrowEx(reqBean, resultBean, "此前操作的工单号已丢失,请选择启动状态的生产工单!");
        return curExecWorkOrderNo;
    }

    private WorkOrderExtModel getWorkOrderExtModel(StationRequestBean reqBean, StationResultBean resultBean, String curExecWorkOrderNo) {
        WorkOrderExtModel orderModel = !reqBean.getDataMap().containsKey(MesPcnExtConstWords.WORK_ORDER) ? null :
                JSONObject.parseObject(JSONObject.toJSONString(reqBean.getDataMap().get(MesPcnExtConstWords.WORK_ORDER)), WorkOrderExtModel.class);
        if (null == orderModel) {
            MesWorkOrderExt workOrderExt = workOrderExtService.getWorkOrderExtByOrderNo(reqBean.getOrganizeCode(), curExecWorkOrderNo);
            if (null != workOrderExt) {
                orderModel = new WorkOrderExtModel();
                BeanUtils.copyProperties(workOrderExt, orderModel, MesPcnExtConstWords.ID);
            }
        }
        if (null == orderModel) execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("此前操作的工单号[%s]对应的信息不存在!", curExecWorkOrderNo));
        return orderModel;
    }

    private String getManageCode(String manageCode, Integer length) {
        if (StringUtils.isEmpty(manageCode)) return null;
        String[] manageCodeArr = manageCode.split(MesPcnExtConstWords.AND);
        if (manageCodeArr.length >= length) return manageCodeArr[length - 1];
        else return null;
    }


}