import * as textoTitulo from '@babel/types';
import { traverse } from '../../../core/config/index.js';
import { messages } from '../../../core/messages/index.js';
import { detectarContextoProjeto } from '../../../shared/index.js';
import { garantirArray, incrementar } from '../../../shared/helpers/index.js';
import { criarOcorrencia, ocorrenciaErroAnalista } from '../../../types/index.js';
export const estatisticasUsoGlobal = {
    requires: {},
    consts: {},
    exports: {},
    vars: {},
    lets: {},
    evals: {},
    withs: {}
};
export const analistaPadroesUso = {
    nome: 'analista-padroes-uso',
    global: false,
    test: (relPath) => relPath.endsWith('.js') || relPath.endsWith('.ts'),
    aplicar: (src, relPath, astInput, _fullPath, contexto) => {
        const contextoArquivo = detectarContextoProjeto({
            arquivo: relPath,
            conteudo: src,
            relPath
        });
        if (contextoArquivo.isTest || contextoArquivo.isConfiguracao || contextoArquivo.frameworks.includes('types')) {
            return null;
        }
        const ocorrencias = [];
        const push = (data) => {
            ocorrencias.push(criarOcorrencia({
                nivel: data.nivel,
                origem: data.origem,
                tipo: data.tipo,
                mensagem: data.mensagem,
                relPath: data.arquivo || data.relPath,
                linha: data.linha,
                coluna: data.coluna
            }));
        };
        const statsFlag = estatisticasUsoGlobal;
        if (!statsFlag.___RESET_DONE___) {
            estatisticasUsoGlobal.requires = {};
            estatisticasUsoGlobal.consts = {};
            estatisticasUsoGlobal.exports = {};
            estatisticasUsoGlobal.vars = {};
            estatisticasUsoGlobal.lets = {};
            estatisticasUsoGlobal.evals = {};
            estatisticasUsoGlobal.withs = {};
            statsFlag.___RESET_DONE___ = true;
        }
        let astWrap = astInput;
        if (!astWrap && contexto?.arquivos) {
            const found = contexto.arquivos?.find((arquivo) => arquivo.relPath === relPath) || contexto.arquivos?.[0];
            astWrap = found?.ast || undefined;
        }
        const hasNodeProp = (valor) => typeof valor === 'object' && valor !== null && 'node' in valor;
        const ast = (astWrap && (hasNodeProp(astWrap) ? astWrap.node : astWrap));
        if (!ast || typeof ast !== 'object')
            return null;
        const tipo = ast.type;
        if (tipo !== 'File' && tipo !== 'Program')
            return null;
        try {
            traverse(ast, {
                enter(path) {
                    const node = path.node;
                    if (textoTitulo.isVariableDeclaration(node) && node.kind === 'var') {
                        incrementar(estatisticasUsoGlobal.vars, relPath);
                        const nivel = contextoArquivo.isTest ? 'info' : 'aviso';
                        push({
                            tipo: 'alerta',
                            nivel,
                            mensagem: messages.PadroesUsoMensagens.varUsage,
                            relPath,
                            linha: node.loc?.start.line,
                            coluna: node.loc?.start.column
                        });
                    }
                    if (textoTitulo.isVariableDeclaration(node) && node.kind === 'let') {
                        incrementar(estatisticasUsoGlobal.lets, relPath);
                        if (!contextoArquivo.isTest) {
                            push({
                                tipo: 'info',
                                mensagem: messages.PadroesUsoMensagens.letUsage,
                                relPath,
                                linha: node.loc?.start.line,
                                coluna: node.loc?.start.column
                            });
                        }
                    }
                    if (textoTitulo.isVariableDeclaration(node) && node.kind === 'const') {
                        incrementar(estatisticasUsoGlobal.consts, relPath);
                    }
                    if (textoTitulo.isCallExpression(node) && textoTitulo.isIdentifier(node.callee)) {
                        const nome = node.callee.name;
                        if (nome === 'require') {
                            incrementar(estatisticasUsoGlobal.requires, relPath);
                            if (relPath.endsWith('.ts') && !contextoArquivo.isTest) {
                                push({
                                    tipo: 'alerta',
                                    mensagem: messages.PadroesUsoMensagens.requireInTs,
                                    relPath,
                                    linha: node.loc?.start.line,
                                    coluna: node.loc?.start.column
                                });
                            }
                        }
                        if (nome === 'eval') {
                            incrementar(estatisticasUsoGlobal.evals, relPath);
                            push({
                                tipo: 'critico',
                                mensagem: messages.PadroesUsoMensagens.evalUsage,
                                relPath,
                                linha: node.loc?.start.line,
                                coluna: node.loc?.start.column
                            });
                        }
                    }
                    if (textoTitulo.isExportNamedDeclaration(node) || textoTitulo.isExportDefaultDeclaration(node)) {
                        incrementar(estatisticasUsoGlobal.exports, relPath);
                    }
                    if (textoTitulo.isAssignmentExpression(node) && textoTitulo.isMemberExpression(node.left) && (textoTitulo.isIdentifier(node.left.object) && node.left.object.name === 'module' && textoTitulo.isIdentifier(node.left.property) && node.left.property.name === 'exports' || textoTitulo.isIdentifier(node.left.object) && node.left.object.name === 'exports') && relPath.endsWith('.ts')) {
                        push({
                            tipo: 'alerta',
                            mensagem: messages.PadroesUsoMensagens.moduleExportsInTs,
                            relPath,
                            linha: node.loc?.start.line,
                            coluna: node.loc?.start.column
                        });
                    }
                    if (textoTitulo.isWithStatement(node)) {
                        incrementar(estatisticasUsoGlobal.withs, relPath);
                        push({
                            tipo: 'critico',
                            mensagem: messages.PadroesUsoMensagens.withUsage,
                            relPath,
                            linha: node.loc?.start.line,
                            coluna: node.loc?.start.column
                        });
                    }
                    if ((textoTitulo.isFunctionExpression(node) || textoTitulo.isFunctionDeclaration(node)) && !node.id && !textoTitulo.isArrowFunctionExpression(node) && !contextoArquivo.isTest) {
                        push({
                            tipo: 'info',
                            mensagem: messages.PadroesUsoMensagens.anonymousFunction,
                            relPath,
                            linha: node.loc?.start.line,
                            coluna: node.loc?.start.column
                        });
                    }
                    if ((node.type === 'ClassProperty' || node.type === 'PropertyDefinition') && 'value' in node && textoTitulo.isArrowFunctionExpression(node.value) && !contextoArquivo.isTest) {
                        push({
                            tipo: 'info',
                            mensagem: messages.PadroesUsoMensagens.arrowAsClassMethod,
                            relPath,
                            linha: node.loc?.start.line,
                            coluna: node.loc?.start.column
                        });
                    }
                }
            });
        }
        catch (erro) {
            ocorrencias.push(ocorrenciaErroAnalista({
                mensagem: messages.PadroesUsoMensagens.erroAnalise(relPath, erro.message),
                relPath,
                origem: 'analista-padroes-uso'
            }));
        }
        return garantirArray(ocorrencias);
    }
};
//# sourceMappingURL=analyst-patterns-usage.js.map