package com.seer.teach.common.advice;

import com.alibaba.fastjson2.JSON;
import com.seer.teach.common.ResultBean;
import com.seer.teach.common.annotation.EncryptionAnnotation;
import com.seer.teach.common.utils.AESUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
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.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Objects;

/**
 * @author Captain
 * @description: 响应加密
 *
 */
@Component
@Slf4j
@ControllerAdvice
public class EncryptResponseBodyAdviceConfig implements ResponseBodyAdvice {


    // 全局配置是否启用解密功能
    @Value("${zs.encryption.enabled:true}")
    private boolean encryptEnabled;

    /**
     * 判断是否需要加密
     *
     * @param methodParameter
     * @param aClass
     * @return
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        Class<?> declaringClass = methodParameter.getMethod().getDeclaringClass();
        // 如果是全局异常处理器，尝试从请求属性中获取原始处理器
        if (declaringClass.getName().equals("com.seer.teach.common.exception.GlobalExceptionHandler")) {
            return checkOriginalControllerSupports();
        }

        // 正常情况下的检查
        return encryptEnabled && (methodParameter.hasMethodAnnotation(EncryptionAnnotation.class)
                || declaringClass.isAnnotationPresent(EncryptionAnnotation.class));
    }
    private boolean checkOriginalControllerSupports() {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                Object handler = attributes.getRequest().getAttribute("org.springframework.web.servlet.HandlerMapping.bestMatchingHandler");
                if (handler instanceof HandlerMethod) {
                    HandlerMethod handlerMethod = (HandlerMethod) handler;
                    Class<?> controllerClass = handlerMethod.getBeanType();
                    return encryptEnabled && (handlerMethod.hasMethodAnnotation(EncryptionAnnotation.class)
                            || controllerClass.isAnnotationPresent(EncryptionAnnotation.class));
                }
            }
        } catch (Exception e) {
            log.debug("无法获取原始控制器信息: " + e.getMessage());
        }
        return false;
    }
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        // 只针对回参类型为ResultBean的对象，进行加密
        if (body instanceof ResultBean) {
            ResultBean commonResult = (ResultBean) body;
            Object data = commonResult.getData();
            if (Objects.nonNull(data)) {
                // 将响应结果转换为json格式
                try {
                    // 无论是对象还是集合，统一转为 JSON 字符串
                    String jsonString = JSON.toJSONString(data);
                    String encrypt = AESUtils.encrypt(jsonString);
                    commonResult.setData(encrypt);
                } catch (Exception e) {
                    log.error("加密失败"+e.getMessage());
                }
                return commonResult;
            }
        }
        return body;
    }

}
