package com.ruoshui.market.handler;

import com.ruoshui.market.entity.DataApiEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

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

@Slf4j
public class MappingHandlerMapping {

    private static Map<String, DataApiEntity> mappings = new ConcurrentHashMap<>();
    private RequestMappingHandlerMapping requestMappingHandlerMapping;
    private RequestHandler handler;
    private Method method;

    {
        try {
            method = RequestHandler.class.getDeclaredMethod("invoke", HttpServletRequest.class, HttpServletResponse.class, Map.class, Map.class, Map.class);
        } catch (NoSuchMethodException e) {
        }
    }

    private String ignore = "services";
    private String prefix = "v1.0.0";
    private String separator = "/";

    public MappingHandlerMapping() {}

    public void setRequestMappingHandlerMapping(RequestMappingHandlerMapping requestMappingHandlerMapping) {
        this.requestMappingHandlerMapping = requestMappingHandlerMapping;
    }

    public void setHandler(RequestHandler handler) {
        this.handler = handler;
    }

    public static DataApiEntity getMappingApiInfo(HttpServletRequest request,String url) {
        NativeWebRequest webRequest = new ServletWebRequest(request);
        String requestMapping = (String) webRequest.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
        return getMappingApiInfo(buildMappingKey(request.getMethod(), url));
    }

    public static DataApiEntity getMappingApiInfoA(String apicode) {
        return getMappingApiInfo(apicode);
    }

    public static DataApiEntity getMappingApiInfo(String key) {
        return mappings.get(key);
    }

    public static String buildMappingKey(String requestMethod, String requestMapping) {
        return requestMethod.toUpperCase() + ":" + requestMapping;
    }

    /**
     * 注册请求映射
     *
     * @param api API实体对象
     */
    public static void registerMapping(DataApiEntity api) {
        if (api == null) {
            log.warn("传入的 API 实体对象为空");
            return;
        }

        String mappingKey = api.getApiCode();
        if (StringUtils.isEmpty(mappingKey)) {
            log.warn("API Code 为空，无法注册映射");
            return;
        }

        // 如果已存在，先移除旧的映射
        if (mappings.containsKey(mappingKey)) {
            log.info("移除已存在的映射: {}", mappingKey);
            mappings.remove(mappingKey);
        }

        log.info("注册接口: {}, 映射键: {}", api.getApiName(), mappingKey);
        mappings.put(mappingKey, api);
    }

    /**
     * 取消注册请求映射
     *
     * @param api
     */
    public static void unregisterMapping(DataApiEntity api) {
        log.info("取消注册接口:{}", api.getApiName());
        String mappingKey = api.getApiCode();
        //String mappingKey = getMappingKey(api);
        if (mappings.containsKey(mappingKey)) {
            // 取消注册
            mappings.remove(mappingKey);
            //requestMappingHandlerMapping.unregisterMapping(getRequestMapping(api));
        }
    }

    private String getMappingKey(DataApiEntity api) {
        return buildMappingKey(api.getReqMethod().toUpperCase(), getRequestPath(api.getApiVersion(), api.getApiUrl()));
    }

    private RequestMappingInfo getRequestMapping(DataApiEntity api) {
        return RequestMappingInfo.paths(getRequestPath(api.getApiVersion(), api.getApiUrl())).methods(RequestMethod.valueOf(api.getReqMethod().toUpperCase())).build();
    }

    /**
     * 调用接口 /services/v1.0.0/user/1
     * @param version
     * @param path
     * @return
     */
    private String getRequestPath(String version, String path) {
        if (version != null) {
            prefix = version;
        }
        return separator + ignore + separator + prefix + (path.startsWith(separator) ? path : (separator + path));
    }
}
