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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesNumberRuleMatchDispatchService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProdRuleContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionAssemblyContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionAssemblyNosortContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionAssemblySortContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.pojo.mes.bean.MesProdRuleIgnoreCfg;
import cn.estsh.i3plus.pojo.mes.bean.MesProdRuleNosortCfg;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkCenter;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import cn.estsh.impp.framework.boot.util.SpringContextsUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Primary
@Service
public class MesNumberRuleMatchDispatchService implements IMesNumberRuleMatchDispatchService {

    @Override
    public List<?> matchNumberRule(String organizeCode, String sn, List<?> numberRuleList) {

        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(sn) || CollectionUtils.isEmpty(numberRuleList)) return null;

        List<Object> resultList = new ArrayList<>();

        if (numberRuleList.get(0) instanceof MesProdRuleNosortCfg) numberRuleList.forEach(o -> matchNumberRuleBackList(organizeCode, sn, resultList, ((MesProdRuleNosortCfg) o).getProdRuleIgnoreCfg(), MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.MATCH_TYPE_20.getStrategyClass(), o, ((MesProdRuleNosortCfg) o).getInPartNoRule()));

        if (numberRuleList.get(0) instanceof MesProdRuleContext) numberRuleList.forEach(o -> matchNumberRuleBackList(organizeCode, sn, resultList, ((MesProdRuleContext) o).getProdRuleIgnoreCfg(), MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.MATCH_TYPE_20.getStrategyClass(), o, ((MesProdRuleContext) o).getInPartNoRule()));

        if (numberRuleList.get(0) instanceof MesProductionAssemblyNosortContext) numberRuleList.forEach(o -> matchNumberRuleBackList(organizeCode, sn, resultList,  ((MesProductionAssemblyNosortContext) o).getProdRuleIgnoreCfg(), MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.valueOfStrategyClass(((MesProductionAssemblyNosortContext) o).getMatchType()), o, ((MesProductionAssemblyNosortContext) o).getMatchRule()));

        if (numberRuleList.get(0) instanceof MesProductionAssemblySortContext) numberRuleList.forEach(o -> matchNumberRuleBackList(organizeCode, sn, resultList, ((MesProductionAssemblySortContext) o).getProdRuleIgnoreCfg(), MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.valueOfStrategyClass(((MesProductionAssemblySortContext) o).getMatchType()), o, ((MesProductionAssemblySortContext) o).getMatchRule()));

        return resultList;

    }

    private List<Object> matchNumberRuleBackList(String organizeCode, String sn, List<Object> resultList, String prodRuleIgnoreCfg, String strategyClass, Object... params) {

        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(sn) || StringUtils.isEmpty(strategyClass) || null == params[0]) return resultList;

        Map<String, Object> result = ((IMesNumberRuleMatchDispatchService) SpringContextsUtil.getBean(strategyClass)).matchNumberRule(organizeCode, sn, params);

        if ((Boolean) result.get(MesPcnExtConstWords.RESULT) && !StringUtils.isEmpty(prodRuleIgnoreCfg)) {
            result = ((IMesNumberRuleMatchDispatchService) SpringContextsUtil.getBean(
                    MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.MATCH_TYPE_20.getStrategyClass())).matchIgnoreCfg(organizeCode, sn, result, JSONObject.parseArray(prodRuleIgnoreCfg, MesProdRuleIgnoreCfg.class));
        }

        if ((Boolean) result.get(MesPcnExtConstWords.RESULT)) resultList.add(params[0]);

        return resultList;

    }

    @Override
    public Map<String, Object> matchNumberRule(String organizeCode, String sn, Object numberRuleObj) {

        Map<String, Object> result = new HashMap<>();
        result.put(MesPcnExtConstWords.RESULT, false);

        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(sn) || null == numberRuleObj) {
            result.put(MesPcnExtConstWords.MESSAGE, String.format("请检查必要参数:工厂[%s]条码[%s]及规则匹配信息!", organizeCode, sn));
            return result;
        }

        if (numberRuleObj instanceof MesProdRuleNosortCfg) return matchNumberRuleBackMap(organizeCode, sn, result, ((MesProdRuleNosortCfg) numberRuleObj).getProdRuleIgnoreCfg(), MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.MATCH_TYPE_20.getStrategyClass(), numberRuleObj, ((MesProdRuleNosortCfg) numberRuleObj).getInPartNoRule());

        if (numberRuleObj instanceof MesProdRuleContext) return matchNumberRuleBackMap(organizeCode, sn, result, ((MesProdRuleContext) numberRuleObj).getProdRuleIgnoreCfg(), MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.MATCH_TYPE_20.getStrategyClass(), numberRuleObj, ((MesProdRuleContext) numberRuleObj).getInPartNoRule());

        if (numberRuleObj instanceof MesProductionAssemblyNosortContext) return matchNumberRuleBackMap(organizeCode, sn, result, ((MesProductionAssemblyNosortContext) numberRuleObj).getProdRuleIgnoreCfg(), MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.valueOfStrategyClass(((MesProductionAssemblyNosortContext) numberRuleObj).getMatchType()), numberRuleObj, ((MesProductionAssemblyNosortContext) numberRuleObj).getMatchRule());

        if (numberRuleObj instanceof MesProductionAssemblySortContext) return matchNumberRuleBackMap(organizeCode, sn, result, ((MesProductionAssemblySortContext) numberRuleObj).getProdRuleIgnoreCfg(), MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.valueOfStrategyClass(((MesProductionAssemblySortContext) numberRuleObj).getMatchType()), numberRuleObj, ((MesProductionAssemblySortContext) numberRuleObj).getMatchRule());

        return result;

    }

    private Map<String, Object> matchNumberRuleBackMap(String organizeCode, String sn, Map<String, Object> resultMap, String prodRuleIgnoreCfg, String strategyClass, Object... params) {

        if (StringUtils.isEmpty(strategyClass)) {
            resultMap.put(MesPcnExtConstWords.MESSAGE, "规则匹配信息的匹配确认方式配置错误,未找到相应的匹配策略!");
            return resultMap;
        }

        Map<String, Object> result = ((IMesNumberRuleMatchDispatchService) SpringContextsUtil.getBean(strategyClass)).matchNumberRule(organizeCode, sn, params);

        if ((Boolean) result.get(MesPcnExtConstWords.RESULT) && !StringUtils.isEmpty(prodRuleIgnoreCfg)) {
            result = ((IMesNumberRuleMatchDispatchService) SpringContextsUtil.getBean(
                    MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.MATCH_TYPE_20.getStrategyClass())).matchIgnoreCfg(organizeCode, sn, result, JSONObject.parseArray(prodRuleIgnoreCfg, MesProdRuleIgnoreCfg.class));
        }
        if ((Boolean) result.get(MesPcnExtConstWords.RESULT)) result.put(MesPcnExtConstWords.DATA, params[0]);

        return result;

    }

    @Override
    public Boolean checkAssemblySnUniqueInMould(MesWorkCenter workCenter, List<MesProdRuleContext> prodRuleContextList, List<? extends MesProductionAssemblyContext> productionAssemblyContextList, String assemblySn) {
        if (!checkAssemblySnUniqueInMould(workCenter, prodRuleContextList, assemblySn)) return false;
        if (!checkAssemblySnUniqueInMould(productionAssemblyContextList, assemblySn)) return false;
        return true;
    }

    @Override
    public Boolean checkAssemblySnUniqueInMould(MesWorkCenter workCenter, List<MesProdRuleContext> prodRuleContextList, String assemblySn) {

        if (CollectionUtils.isEmpty(prodRuleContextList)) return true;

        for (MesProdRuleContext prodRuleContext : prodRuleContextList) {

            if (null == prodRuleContext || StringUtils.isEmpty(prodRuleContext.getAssemblyDataJson())) continue;

            if (!checkAssemblySnUniqueInMould(prodRuleContext.getProductionAssemblyContextList(workCenter), assemblySn)) return false;

        }

        return true;
    }

    @Override
    public Boolean checkAssemblySnUniqueInMould(List<? extends MesProductionAssemblyContext> productionAssemblyContextList, String assemblySn) {

        if (CollectionUtils.isEmpty(productionAssemblyContextList)) return true;

        for (MesProductionAssemblyContext productionAssemblyContext : productionAssemblyContextList) {

            if (null == productionAssemblyContext) continue;

            if (!StringUtils.isEmpty(productionAssemblyContext.getAssemblySn()) && productionAssemblyContext.getAssemblySn().equals(assemblySn)) return false;

        }

        return true;
    }

}
