package cn.ey.biz.module.system.framework.dynamic_api.core.service;

import cn.ey.biz.module.system.framework.dynamic_api.core.AbstractResourceStorage;
import cn.ey.biz.module.system.framework.dynamic_api.core.handler.RequestHandler;
import cn.ey.biz.module.system.framework.dynamic_api.core.util.Mapping;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;

import static cn.ey.biz.common.exception.util.ServiceExceptionUtil.exception;

@Slf4j
public class RequestDynamicRegistry extends AbstractDynamicRegistry {

	private final Method method = RequestHandler.class.getDeclaredMethod("invoke", HttpServletRequest.class, HttpServletResponse.class, Map.class, Map.class, Map.class, Map.class);

	private final Mapping mapping;

	private Object handler;

	private final boolean allowOverride;

	private final String prefix;

	public RequestDynamicRegistry(AbstractResourceStorage resourceStorage,
								  Mapping mapping,
								  RequestHandler handler,
								  boolean allowOverride,
								  String prefix) throws NoSuchMethodException {
		super(resourceStorage);
		this.mapping = mapping;
		this.handler = handler;
		this.allowOverride = allowOverride;
		this.prefix = StringUtils.defaultIfBlank(prefix, "") + "/";
	}

	@Override
	public boolean register(MappingNode mappingNode) {
		String mappingKey = mappingNode.getMappingKey();
		String requestMethod = mappingNode.getEntity().getMethod();
		String path = mappingNode.getEntity().getPath();
		RequestMappingInfo requestMappingInfo = mapping.paths(path).methods(RequestMethod.valueOf(requestMethod.toUpperCase())).build();
		if (mapping.getHandlerMethods().containsKey(requestMappingInfo)) {
			if (!allowOverride) {
				String REQUEST_PATH_CONFLICT = "接口[{}({})]与应用冲突，无法注册";
				log.error(REQUEST_PATH_CONFLICT, mappingNode.getEntity().getName(), mappingKey);
				throw exception(-1, REQUEST_PATH_CONFLICT.format(mappingNode.getEntity().getName(), mappingKey));
			}
			log.warn("取消注册应用接口:{}", requestMappingInfo);
			// 取消注册原接口
			mapping.unregister(requestMappingInfo);
		}
		log.info("注册接口[{}({})]", mappingNode.getEntity().getName(), mappingKey);
		mapping.register(requestMappingInfo, handler, method);
		mappingNode.setMappingData(requestMappingInfo);
		return true;
	}

	@Override
	protected void unregister(MappingNode mappingNode) {
		log.debug("取消注册接口[{}({})]", mappingNode.getEntity().getName(), mappingNode.getMappingKey());
		mapping.unregister((RequestMappingInfo) mappingNode.getMappingData());
	}

}
