package shop.alien.util.encryption.advice;

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
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.util.AntPathMatcher;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import shop.alien.util.encryption.StandardAesUtil;
import shop.alien.util.encryption.properties.EncryptProperties;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * 响应体加密 Advice
 * 拦截带有 @Encrypt 注解的控制器方法，将返回结果 AES 加密后返回
 */
@ControllerAdvice
public class EncryptResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    @Autowired
    private EncryptProperties encryptProperties;

    @Autowired
    private HttpServletRequest request;

    private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 1. 如果接口加密关闭，不加密
        if (!encryptProperties.isApiEnabled()) {
            return false;
        }

        // 2. 路径排除校验
        String uri = request.getRequestURI();
        List<String> excludePaths = encryptProperties.getExcludePaths();
        if (excludePaths != null && !excludePaths.isEmpty()) {
            for (String pattern : excludePaths) {
                if (PATH_MATCHER.match(pattern, uri)) {
                    return false;
                }
            }
        }

        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (body == null) {
            return null;
        }
        
        // 1. 将返回对象序列化为 JSON 字符串
        String data = JSON.toJSONString(body);
        
        // 2. 执行 AES 加密
        String encryptedData = StandardAesUtil.encrypt(data, encryptProperties.getKey(), encryptProperties.getIv());
        
        // 3. 返回加密后的字符串（直接写回响应流）
        return encryptedData;
    }
}
