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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesContainerBindDispatchService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.rulematch.containerbind.checkqty.MesAbstractContainerBindCheckQtyService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.util.MesPcnException;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MesContainerPartsModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

public class ContainerBindManager {
    public static final ContainerBindManager INSTANCE = new ContainerBindManager();

    private final Map<String, IMesContainerBindDispatchService> dispatchServices = new HashMap<>();
    private final Map<MesExtEnumUtil.CONTAINER_TYPE_MIX_TYPE, MesAbstractContainerBindCheckQtyService> checkQtyServices = new HashMap<>();

    private ContainerBindManager() {

    }

    public void register(MesExtEnumUtil.CONTAINER_TYPE containerType, MesExtEnumUtil.CONTAINER_PART_MATCH_TYPE matchType, IMesContainerBindDispatchService dispatchService) {
        String containerKey = containerType != null ? containerType.name() : "*";
        String matchKey = matchType != null ? matchType.name() : "*";
        dispatchServices.put(containerKey + ":" + matchKey, dispatchService);
    }

    public void registerCheckQty(MesExtEnumUtil.CONTAINER_TYPE_MIX_TYPE type, MesAbstractContainerBindCheckQtyService checkQtyService) {
        checkQtyServices.put(type, checkQtyService);
    }

    public IMesContainerBindDispatchService getDispatchService(MesExtEnumUtil.CONTAINER_TYPE containerType, MesExtEnumUtil.CONTAINER_PART_MATCH_TYPE matchType) {
        assert containerType != null;
        assert matchType != null;
        String containerKey = containerType.name();
        String matchKey = matchType.name();
        IMesContainerBindDispatchService dispatchService = dispatchServices.get(containerKey + ":" + matchKey);
        if (dispatchService == null) {
            dispatchService = dispatchServices.get("*:" + matchKey);
        }
        if (dispatchService == null) {
            dispatchService = dispatchServices.get(matchKey + ":*");
        }
        if (dispatchService == null) {
            MesPcnException.throwMesBusiException("容器类型【%s】的容器零件确认方式【%s】未配置绑定策略", containerType.getDescription(), matchType.getDescription());
        }
        return dispatchService;
    }

    public MesAbstractContainerBindCheckQtyService getCheckQtyService(MesExtEnumUtil.CONTAINER_TYPE_MIX_TYPE type) {
        if (type == null) {
            MesPcnException.throwMesBusiException("容器类型混包类型无效");
        }
        MesAbstractContainerBindCheckQtyService checkQtyService = checkQtyServices.get(type);
        if (checkQtyService == null) {
            MesPcnException.throwMesBusiException("容器类型混包类型【%s】未配置校验数量策略", type.getDescription());
        }
        return checkQtyService;
    }

    public Map<String, Object> matchNumberRule(String organizeCode, String barcode, MesContainerPartsModel model) {
        Map<String, Object> result = new HashMap<>();
        result.put(MesPcnExtConstWords.RESULT, false);

        if (StringUtils.isEmpty(organizeCode)) {
            result.put(MesPcnExtConstWords.MESSAGE, "请检查必要参数:工厂信息!");
            return result;
        }
        if (StringUtils.isEmpty(barcode)) {
            result.put(MesPcnExtConstWords.MESSAGE, "请检查必要参数:条码信息!");
            return result;
        }
        if (model == null || model.getContainerType() == null) {
            result.put(MesPcnExtConstWords.MESSAGE, "请检查必要参数:容器类型信息!");
            return result;
        }
        if (model.getMatchType() == null) {
            result.put(MesPcnExtConstWords.MESSAGE, "请检查必要参数:匹配规则信息!");
            return result;
        }
        MesExtEnumUtil.CONTAINER_TYPE containerType = MesExtEnumUtil.CONTAINER_TYPE.getByValue(model.getContainerType());
        assert containerType != null;
        MesExtEnumUtil.CONTAINER_PART_MATCH_TYPE matchType = MesExtEnumUtil.CONTAINER_PART_MATCH_TYPE.getByValue(model.getMatchType());
        assert matchType != null;

        IMesContainerBindDispatchService dispatchService = getDispatchService(containerType, matchType);
        return dispatchService.matchNumberRule(organizeCode, barcode, model);
    }
}
