package com.ningdatech.pmapi.common.handler;

import cn.hutool.json.JSONUtil;
import com.ningdatech.basic.model.ApiResponse;
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.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @Author liuxinxin
 * @Date 2021/7/21 11:26
 * @Version 1.0
 **/
@RestControllerAdvice(basePackages = {
        "com.ningdatech.pmapi.fiscal.controller",
        "com.ningdatech.pmapi.organization.controller",
        "com.ningdatech.pmapi.projectdeclared.controller",
        "com.ningdatech.pmapi.projectlib.controller",
        "com.ningdatech.pmapi.sys.controller",
        "com.ningdatech.pmapi.todocenter.controller",
        "com.ningdatech.pmapi.user.controller",
        "com.ningdatech.pmapi.expert.controller"
})
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> {

    private static final String SWAGGER_CLASS_PREFIX = "springfox.documentation";

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return filter(methodParameter);
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType,
                                  Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest,
                                  ServerHttpResponse serverHttpResponse) {
        ApiResponse<Object> apiResponse = ApiResponse.ofSuccess(o);
        // 处理字符串时，遇到了类型转换的问题，debug一步一步跟踪，原来是对于字符串的ContentType是“text-plain”，
        // ConverterType是StringHttpMessageConverter这个类型转换，
        // 由于将结果封装成了自定义的ApiResponse类型，所以有ApiResponse转换成String报错
        // 所以需要对String类型的返回值单独进行处理
        if (o instanceof String) {
            return JSONUtil.toJsonStr(apiResponse);
        }
        return ApiResponse.ofSuccess(o);
//        return o;
    }

    private Boolean filter(MethodParameter methodParameter) {
        Class<?> declaringClass = methodParameter.getDeclaringClass();
        // swagger中的所有返回不进行统一封装
        if (declaringClass.getName().contains(SWAGGER_CLASS_PREFIX)) {
            return false;
        }
        if (methodParameter.hasMethodAnnotation(ExceptionHandler.class)) {
            return false;
        }
        // 如果本身就是使用ApiResponse返回，则不需要进行格式化
        return !methodParameter.getParameterType().equals(ApiResponse.class);
    }
}
