import { messages } from '../../../core/messages/index.js';
import { createLineLookup, maskGoComments } from '../../../shared/helpers/index.js';
import { criarAnalista, criarOcorrencia } from '../../../types/index.js';
const disableEnv = process.env.TUTANUS_DISABLE_PLUGIN_GO === '1';
function warn(message, relPath, line, nivel) {
    return criarOcorrencia({
        relPath,
        mensagem: message,
        linha: line,
        nivel: nivel ?? messages.SeverityNiveis.warning,
        origem: messages.AnalystOrigens.go,
        tipo: messages.AnalystTipos.go
    });
}
function collectResourceIssues(src, relPath) {
    const ocorrencias = [];
    const lineOf = createLineLookup(src).lineAt;
    const scan = maskGoComments(src);
    for (const match of scan.matchAll(/\b(?:os\.Open|os\.Create|file\.Open|http\.Get|http\.Post|net\.Dial|sql\.Open)\s*\(/g)) {
        const line = lineOf(match.index);
        const snippet = src.slice(match.index, match.index + 200);
        if (!/defer\s+\w+\.Close\(\)/.test(snippet) && !/defer\s+\w+\.Release\(\)/.test(snippet)) {
            ocorrencias.push(warn(messages.GoMensagens.missingDeferClose, relPath, line));
        }
    }
    for (const match of scan.matchAll(/\bos\.Open\s*\(/g)) {
        const line = lineOf(match.index);
        const snippet = src.slice(match.index, match.index + 200);
        if (!/\.Close\(\)/.test(snippet)) {
            ocorrencias.push(warn(messages.GoMensagens.missingDeferClose, relPath, line, messages.SeverityNiveis.error));
        }
    }
    for (const match of scan.matchAll(/resp(?:onse)?\.Body\s*(?!=)/g)) {
        const line = lineOf(match.index);
        const snippet = src.slice(match.index, match.index + 200);
        if (!/\.Close\(\)/.test(snippet)) {
            ocorrencias.push(warn('http response body not closed; potential resource leak', relPath, line, messages.SeverityNiveis.error));
        }
    }
    for (const match of scan.matchAll(/^\s*go\s+func\(/gm)) {
        const line = lineOf(match.index);
        const block = src.slice(match.index, match.index + 300);
        if (!block.includes('sync.WaitGroup') && !block.includes('done') && !block.includes('quit') && !block.includes('ctx.Done')) {
            ocorrencias.push(warn('Goroutine without synchronization mechanism; potential leak', relPath, line, messages.SeverityNiveis.warning));
        }
    }
    return ocorrencias;
}
export const analistaGoRecursos = criarAnalista({
    nome: 'analista-go-recursos',
    categoria: 'recursos',
    descricao: 'Detecta vazamentos de recursos e falta de fechamento em código Go.',
    global: false,
    test: (relPath) => /\.go$/i.test(relPath),
    aplicar: async (src, relPath) => {
        if (disableEnv)
            return null;
        const msgs = collectResourceIssues(src, relPath);
        return msgs.length ? msgs : null;
    }
});
//# sourceMappingURL=analyst-resources.js.map