import crypto from 'node:crypto';
const PUBLIC_URL = process.env.TUTANUS_PUBLIC_URL || 'http://localhost:3000';
const API_SECRET = process.env.TUTANUS_API_SECRET || '';
const IS_PROD = process.env.NODE_ENV === 'production';
const BLOQUEIO_AVISO = 'Acesso nao autorizado.';
const ROTAS_PUBLICAS = new Set([
    '/app-info',
    '/health',
    '/webhooks',
    '/ping',
]);
const ORIGENS_PERMITIDAS = new Set([
    PUBLIC_URL.replace(/\/$/u, ''),
    'http://localhost:3000',
    'http://localhost:5173',
]);
function isRotaPublica(path) {
    if (ROTAS_PUBLICAS.has(path))
        return true;
    if (path.startsWith('/setup'))
        return true;
    return false;
}
function originPermitida(origin) {
    if (!origin)
        return false;
    const normalizada = origin.replace(/\/$/u, '');
    for (const permitida of ORIGENS_PERMITIDAS) {
        if (normalizada === permitida || normalizada.startsWith(`${permitida}/`)) {
            return true;
        }
    }
    return false;
}
export function bloquearAcessoDireto(req, res, next) {
    if (isRotaPublica(req.path)) {
        next();
        return;
    }
    const xRequestedWith = req.headers['x-requested-with'];
    const secFetchSite = req.headers['sec-fetch-site'];
    const accept = req.headers.accept;
    const isXHR = xRequestedWith === 'XMLHttpRequest';
    const isFetch = accept?.includes('application/json');
    const isSameOrigin = secFetchSite === 'same-origin' || secFetchSite === 'same-site';
    if (!isXHR && !isFetch && !isSameOrigin) {
        if (req.method === 'GET') {
            res.redirect('/');
            return;
        }
        res.status(403).json({ erro: BLOQUEIO_AVISO });
        return;
    }
    next();
}
export function verificarOrigem(req, res, next) {
    if (isRotaPublica(req.path)) {
        next();
        return;
    }
    const origin = req.headers.origin;
    const referer = req.headers.referer;
    const source = origin || referer;
    if (source && !originPermitida(source)) {
        res.status(403).json({ erro: BLOQUEIO_AVISO });
        return;
    }
    next();
}
export async function verificarAssinaturaApi(req, res, next) {
    if (isRotaPublica(req.path)) {
        next();
        return;
    }
    if (!API_SECRET) {
        if (IS_PROD) {
            res.status(401).json({ erro: 'API secret nao configurada (TUTANUS_API_SECRET).' });
            return;
        }
        next();
        return;
    }
    const signature = req.headers['x-api-signature'];
    if (!signature) {
        res.status(401).json({ erro: BLOQUEIO_AVISO });
        return;
    }
    const timestamp = req.headers['x-api-timestamp'];
    if (!timestamp) {
        res.status(401).json({ erro: BLOQUEIO_AVISO });
        return;
    }
    const now = Date.now();
    const ts = parseInt(timestamp, 10);
    if (Number.isNaN(ts) || Math.abs(now - ts) > 30000) {
        res.status(401).json({ erro: BLOQUEIO_AVISO });
        return;
    }
    const method = req.method;
    const path = req.path;
    const body = typeof req.body === 'object' ? JSON.stringify(req.body) : '';
    const payload = `${method}:${path}:${timestamp}:${body}`;
    const { verifyRequestSignature: verificarAssinatura } = await import('./crypto.js');
    const valido = verificarAssinatura(payload, signature, API_SECRET);
    if (!valido) {
        res.status(401).json({ erro: BLOQUEIO_AVISO });
        return;
    }
    next();
}
export function mascararRotasApi(req, res, next) {
    if (isRotaPublica(req.path)) {
        next();
        return;
    }
    if (!req.path.startsWith('/api/github')) {
        next();
        return;
    }
    const xRequestedWith = req.headers['x-requested-with'];
    const accept = req.headers.accept;
    const isXHR = xRequestedWith === 'XMLHttpRequest';
    const isFetch = accept?.includes('application/json');
    if (!isXHR && !isFetch) {
        if (req.method === 'GET') {
            res.redirect('/');
            return;
        }
        res.status(404).json({ erro: 'Nao encontrado.' });
        return;
    }
    next();
}
export function createIsolationMiddleware() {
    return [
        bloquearAcessoDireto,
        verificarOrigem,
        verificarAssinaturaApi,
        mascararRotasApi,
    ];
}
export function gerarAssinaturaApi(method, path, body) {
    const timestamp = String(Date.now());
    const bodyStr = typeof body === 'string' ? body : JSON.stringify(body);
    const payload = `${method}:${path}:${timestamp}:${bodyStr}`;
    const signature = crypto.createHmac('sha256', API_SECRET).update(payload).digest('hex');
    return { signature, timestamp };
}
//# sourceMappingURL=isolamento.js.map