package com.ema.admin.handler;

import com.ema.common.domain.vo.ResultVo;
import org.jetbrains.annotations.Nullable;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Arrays;
import java.util.List;

/**
 * 全局响应拦截器：自动将Controller返回值封装为ResultVo格式
 * 无需在Controller方法上写ResultVo<User>，直接返回User即可
 */

@ControllerAdvice // 作用于所有Controller
public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> {

    /**
     * 需要排除拦截的URL路径列表
     * 可根据实际需求添加或修改
     */
    private static final List<String> EXCLUDE_URLS = Arrays.asList(
            "/swagger-resources",
            "/v2/api-docs",
            "/v3/api-docs"
    );

    /**
     * 判断是否需要拦截：除了ResultVo、String类型，其他所有返回值都需要拦截封装
     * 同时排除指定URL路径的请求
     *
     * @param returnType    方法返回值类型
     * @param converterType 消息转换器类型
     * @return true=拦截，false=不拦截
     */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 排除ResultVo类型，避免重复封装
        Class<?> clazz = returnType.getParameterType();
        if (ResultVo.class.isAssignableFrom(clazz)) {
            return false;
        }
        // 排除String类型，避免ClassCastException
        if (String.class.isAssignableFrom(clazz)) {
            return false;
        }
        // 通过URL路径排除特定请求
        return !shouldExcludeByPath();
    }

    /**
     * 判断当前请求是否需要排除
     * 通过检查URL路径是否在排除列表中
     *
     * @return true=需要排除，false=不需要排除
     */
    private boolean shouldExcludeByPath() {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes == null) {
                return false;
            }
            javax.servlet.http.HttpServletRequest request = attributes.getRequest();
            String uri = request.getRequestURI();
            // 检查URL是否在排除列表中（支持路径前缀匹配）
            return EXCLUDE_URLS.stream().anyMatch(uri::startsWith);
        } catch (Exception e) {
            // 如果获取请求信息失败，默认不排除
            return false;
        }
    }

    /**
     * 拦截后的处理：将返回值封装为ResultVo.success(data)
     * @param body 原始返回值（如User、List、String等）
     * @param returnType 方法返回值类型
     * @param selectedContentType 响应媒体类型
     * @param selectedConverterType 消息转换器类型
     * @param request 请求对象
     * @param response 响应对象
     * @return 封装后的ResultVo对象
     *
     */
    @Nullable
    @Override
    public Object beforeBodyWrite(@Nullable Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        // 自动封装为成功响应，body为业务数据
        return ResultVo.success(body);
    }

}
