package com.yaoai.security.config;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import com.yaoai.common.context.UserContext;
import com.yaoai.security.context.TenantContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {

    private static final String[] OPEN_PATHS = {
            "/auth/**",
            "/swagger-ui/**", "/swagger-ui.html",
            "/v3/api-docs/**",
            "/actuator/**",
            "/ping",
            "/system/**",
            "/local-files",
            "/admin-api/**",
            "/agent/runs/*/events"   // SSE: token 通过 query param 传入，由 controller 手动校验
    };

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // Sa-Token 鉴权拦截器
        registry.addInterceptor(new SaInterceptor(handle ->
                SaRouter.match("/**")
                        .notMatch(OPEN_PATHS)
                        .check(r -> {
                            StpUtil.checkLogin();
                            UserContext.set(StpUtil.getLoginIdAsLong());
                            // 登录后将 tenantId 写入 ThreadLocal，供业务层使用
                            Object tenantId = StpUtil.getSession().get("tenantId");
                            if (tenantId != null) {
                                TenantContext.set(((Number) tenantId).longValue());
                            }
                        })
        )).addPathPatterns("/**");

        // 请求结束后清理 ThreadLocal，防止线程池复用时数据污染
        registry.addInterceptor(new HandlerInterceptor() {
            @Override
            public void afterCompletion(HttpServletRequest req,
                                        HttpServletResponse res,
                                        Object handler, Exception ex) {
                UserContext.clear();
                TenantContext.clear();
            }
        }).addPathPatterns("/**");
    }
}
