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 collectConcurrencyIssues(src, relPath) {
    const ocorrencias = [];
    const lineOf = createLineLookup(src).lineAt;
    const scan = maskGoComments(src);
    for (const match of scan.matchAll(/^\s*defer\s+/gm)) {
        const line = lineOf(match.index);
        const lines = scan.split('\n');
        const forLoopAbove = lines.slice(Math.max(0, line - 3), line).some(l => /^\s*for\s+/.test(l));
        if (forLoopAbove) {
            ocorrencias.push(warn(messages.GoMensagens.deferInLoop, relPath, line));
        }
    }
    for (const match of scan.matchAll(/(\w+)\s*<-\s*(\w+)/g)) {
        const line = lineOf(match.index);
        const chanDeclPattern = new RegExp(`make\\s*\\(\\s*chan\\s+\\w+\\s*\\)`);
        if (chanDeclPattern.test(src)) {
            ocorrencias.push(warn(messages.GoMensagens.unbufferedChanSend, relPath, line));
        }
    }
    for (const match of scan.matchAll(/\bselect\s*\{/g)) {
        const blockStart = match.index ?? 0;
        const block = src.slice(blockStart, blockStart + 500);
        if (!/\bdefault\s*:/m.test(block)) {
            const line = lineOf(blockStart);
            ocorrencias.push(warn('select without default case may block indefinitely', relPath, line, messages.SeverityNiveis.warning));
        }
    }
    for (const match of scan.matchAll(/(\w+)\.Lock\s*\(\)/g)) {
        const line = lineOf(match.index);
        const varName = match[1];
        const snippet = src.slice(match.index, match.index + 300);
        if (!new RegExp(`defer\\s+${varName}\\.Unlock\\s*\\(\\)`).test(snippet)) {
            ocorrencias.push(warn(`Mutex '${varName}'.Lock() without deferred Unlock; risk of deadlock`, relPath, line, messages.SeverityNiveis.error));
        }
    }
    return ocorrencias;
}
export const analistaGoConcorrencia = criarAnalista({
    nome: 'analista-go-concorrencia',
    categoria: 'concorrencia',
    descricao: 'Detecta problemas de concorrência em código Go.',
    global: false,
    test: (relPath) => /\.go$/i.test(relPath),
    aplicar: async (src, relPath) => {
        if (disableEnv)
            return null;
        const msgs = collectConcurrencyIssues(src, relPath);
        return msgs.length ? msgs : null;
    }
});
//# sourceMappingURL=analyst-concurrency.js.map