/**
 * Token 验证中间件
 *
 * 验证请求头中的 X-Runtime-Token 是否为已配对的 connectionKey 或 runtime binding token。
 * 也提供联合中间件，同时支持面板 cookie 会话认证，用于可从面板 UI 触发的操作。
 */
import { hasRuntimeBinding, validateRuntimeBindingToken, } from "../services/runtime-binding.js";
import { getConfiguredConnectionKeys } from "../services/auto-register.js";
import { validateSession } from "../services/panel-auth.js";
function extractRuntimeToken(req) {
    const headerToken = req.header("X-Runtime-Token");
    if (headerToken) {
        return headerToken.trim();
    }
    const authorization = req.header("Authorization") || "";
    const bearerMatch = authorization.match(/^Bearer\s+(.+)$/i);
    return bearerMatch?.[1]?.trim() || "";
}
function validateConfiguredToken(token) {
    if (!token) {
        return false;
    }
    if (getConfiguredConnectionKeys().includes(token)) {
        return true;
    }
    return false;
}
/**
 * 校验 runtime token。
 * 主流程：复用 REST 中间件的 runtime binding token 与 connectionKey 校验逻辑，供 WebSocket upgrade 使用。
 */
export function isRuntimeTokenValid(token) {
    const normalized = String(token || "").trim();
    return validateRuntimeBindingToken(normalized) || validateConfiguredToken(normalized);
}
/**
 * Token 验证中间件
 * 检查请求头中的 X-Runtime-Token 或 Authorization: Bearer 是否有效。
 *
 * 支持面板/服务器绑定时写入的动态令牌和 bridge 实例 connectionKey。
 */
export function validateToken(req, res, next) {
    const token = extractRuntimeToken(req);
    if (isRuntimeTokenValid(token)) {
        next();
        return;
    }
    if (!hasRuntimeBinding()) {
        res.status(401).json({
            error: "runtime_bridge_unpaired",
            message: "Runtime bridge is not paired. Add this instance from the panel first.",
        });
        return;
    }
    res.status(401).json({ error: "unauthorized" });
}
// ── 面板 cookie 会话验证 ──────────────────────────────────────
const PANEL_COOKIE_NAME = "panel_sid";
function parseCookies(cookieHeader) {
    const result = {};
    if (!cookieHeader)
        return result;
    for (const part of cookieHeader.split(";")) {
        const idx = part.indexOf("=");
        if (idx === -1)
            continue;
        const key = part.slice(0, idx).trim();
        const val = part.slice(idx + 1).trim();
        if (key)
            result[key] = val;
    }
    return result;
}
function extractPanelSessionToken(req) {
    const cookies = parseCookies(req.headers.cookie);
    return cookies[PANEL_COOKIE_NAME];
}
/**
 * 联合中间件：同时支持 runtime token 和面板 cookie 会话。
 * 面板前端调用时需要 cookie 认证（由浏览器自动附带），
 * 调度中心/服务端调用时使用 X-Runtime-Token 或 Authorization: Bearer。
 * 适用于可从面板 UI 或外部 API 两种途径触发的操作。
 */
export function validateTokenOrPanelSession(req, res, next) {
    // 优先检查 runtime token（服务端调用）
    const token = extractRuntimeToken(req);
    if (isRuntimeTokenValid(token)) {
        next();
        return;
    }
    // 回退检查面板 cookie 会话（浏览器调用）
    const panelToken = extractPanelSessionToken(req);
    if (panelToken && validateSession(panelToken)) {
        next();
        return;
    }
    res.status(401).json({ error: "unauthorized" });
}
