package com.ttstd.signaling.config;

import jakarta.servlet.http.HttpServletRequest;

import java.util.Set;

/**
 * 统一管理“无需鉴权即可访问”的端点。
 *
 * <p>所有免登录/免令牌的公开接口集中在此登记，避免各过滤器各自硬编码放行规则
 * 导致遗漏或冲突（例如登录接口被误拦截返回 401）。
 *
 * <p>匹配规则：
 * <ul>
 *   <li>{@link #EXACT} 中的精确路径（含任意 HTTP 方法）一律放行；</li>
 *   <li>{@link #PREFIXES} 中的前缀路径一律放行；</li>
 *   <li>OPTIONS 预检请求一律放行；</li>
 *   <li>其余路径交由对应鉴权过滤器处理。</li>
 * </ul>
 */
public final class PublicEndpoints {

    private PublicEndpoints() {
    }

    /** 精确免鉴权路径（不区分 HTTP 方法）。 */
    public static final Set<String> EXACT = Set.of(
            // 主控端用户体系
            "/api/auth/register",
            "/api/auth/login",
            "/api/auth/refresh",
            // 设备激活 / 设备令牌
            "/api/device/provision",
            "/api/device/token",
            // 后台管理员：登录接口免鉴权（其余后台接口均需 admt_ 令牌）
            "/api/admin/login",
            // 后台健康检查（运维探针）
            "/api/admin/health"
    );

    /** 免鉴权前缀。 */
    public static final Set<String> PREFIXES = Set.of(
            // WebSocket 握手前的公开信令协商路径（如有）
    );

    /** 判断请求是否免鉴权。 */
    public static boolean isPublic(HttpServletRequest request) {
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            return true;
        }
        String path = request.getServletPath();
        if (path == null) {
            return false;
        }
        if (EXACT.contains(path)) {
            return true;
        }
        for (String prefix : PREFIXES) {
            if (path.startsWith(prefix)) {
                return true;
            }
        }
        return false;
    }
}
