package cn.skcks.matrix.v2.interceptor;

import cn.skcks.matrix.v2.annotation.web.auth.Auth;
import cn.skcks.matrix.v2.annotation.web.auth.UnAuth;
import cn.skcks.matrix.v2.handler.AuthHandler;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
@SuppressWarnings({"unused"})
@ConditionalOnClass({Auth.class, UnAuth.class})
@RequiredArgsConstructor
public class AuthorizationInterceptor implements HandlerInterceptor {
    private final List<AuthHandler> authHandlers = new ArrayList<>();

    public List<AuthHandler> getAuthHandlers() {
        return authHandlers;
    }

    public void addAuthHandler(AuthHandler authHandler) {
        this.authHandlers.add(authHandler);
    }

    @Override
    public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
        log.info("[请求检测] 请求类型 => {}, 请求地址 => {}, {}", request.getMethod(), request.getRequestURI(), handler);

        if (!(handler instanceof HandlerMethod handlerMethod)) {
            return true;
        } else if (response.getStatus() != HttpServletResponse.SC_OK) {
            return true;
        }

        Method method = handlerMethod.getMethod();
        Class<?> clz = handlerMethod.getBeanType();
        if (method.isAnnotationPresent(Auth.class) || method.isAnnotationPresent(UnAuth.class) ||
                clz.isAnnotationPresent(Auth.class) || clz.isAnnotationPresent(UnAuth.class)) {
            if (method.isAnnotationPresent(UnAuth.class) || clz.isAnnotationPresent(UnAuth.class)) {
                UnAuth unAuth = method.isAnnotationPresent(UnAuth.class) ?
                        method.getAnnotation(UnAuth.class) :
                        handlerMethod.getBeanType().getAnnotation(UnAuth.class);

                if (!unAuth.required()) {
                    return executeAuthHandlers(request, response, handler);
                }
            } else if (method.isAnnotationPresent(Auth.class) || clz.isAnnotationPresent(Auth.class)) {
                Auth auth = method.isAnnotationPresent(Auth.class) ?
                        method.getAnnotation(Auth.class) :
                        handlerMethod.getBeanType().getAnnotation(Auth.class);

                if (auth.required()) {
                    return executeAuthHandlers(request, response, handler);
                }
            }
        }

        log.info("[权限检测] 无需权限认证 直接放行 {}", handler);
        return true;
    }

    private boolean executeAuthHandlers(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        for (AuthHandler authHandler : authHandlers) {
            if(!authHandler.auth(request,response,handler)){
                return false;
            }
        }
        return true;
    }
}
