import { categorizarUnknown, extractVariableName, isAnyInGenericFunction, isInStringOrComment, isLegacyOrVendorFile, isTypeScriptContext, isUnknownInGenericContext } from '../../corrections/type-safety/index.js';
import { config } from '../../../core/config/index.js';
import { messages } from '../../../core/messages/index.js';
import { isTestArquivo, shouldSuppressOccurrence, splitLines } from '../../../shared/helpers/index.js';
const ANALISTA = {
    nome: 'detector-tipos-inseguros',
    categoria: 'code-quality',
    descricao: 'Detecta uso de any e unknown que podem ser substituídos por tipos específicos',
    test: (relPath) => {
        return relPath.endsWith('.ts') || relPath.endsWith('.tsx');
    },
    aplicar: async (srcParam, relPath, _ast, fullCaminho) => {
        const ocorrencias = [];
        const src = srcParam.replace(/\r\n/g, '\n');
        const allowAnyInTests = Boolean(config.testPadroes?.allowAnyType);
        if (allowAnyInTests && isTestArquivo(fullCaminho || relPath)) {
            return ocorrencias;
        }
        if (isLegacyOrVendorFile(fullCaminho || relPath)) {
            return ocorrencias;
        }
        const anyPadrao = /:\s*(any|NonNullable<any>|Partial<any>|Omit<any,\s*[^>]+>|Pick<any,\s*[^>]+>)\b/g;
        let anyMatch;
        while ((anyMatch = anyPadrao.exec(src)) !== null) {
            const position = anyMatch.index || 0;
            if (isInStringOrComment(src, position)) {
                continue;
            }
            if (isTypeScriptContext(src, position)) {
                continue;
            }
            if (isAnyInGenericFunction(src, position)) {
                continue;
            }
            const varNome = extractVariableName(anyMatch, src);
            const linha = splitLines(src.substring(0, position)).length;
            const lineContext = splitLines(src)[linha - 1]?.trim() || '';
            let mensagem = '';
            let sugestao = '';
            if (anyMatch[1] !== 'any') {
                mensagem = messages.DetectorJsTsMensagens.tipoAnyComUtilidade(varNome ?? '', anyMatch[1] ?? 'any');
                sugestao = messages.DetectorJsTsMensagens.tipoAnyComUtilidadeSugestao(anyMatch[1] ?? 'any');
            }
            else if (/catch\s*\(\s*\w+\s*:\s*any\s*\)/.test(lineContext)) {
                mensagem = messages.DetectorJsTsMensagens.anyCatchBlock(varNome || undefined);
                sugestao = messages.DetectorJsTsMensagens.anyCatchBlockSugestao;
            }
            else if (/callback\s*:\s*\([^)]*:\s*any/.test(lineContext)) {
                mensagem = messages.DetectorJsTsMensagens.callbackAny(varNome || undefined);
                sugestao = messages.DetectorJsTsMensagens.callbackAnySugestao;
            }
            else if (/event\s*:\s*any|e\s*:\s*any/.test(lineContext)) {
                mensagem = messages.DetectorJsTsMensagens.eventHandlerAny(varNome || undefined);
                sugestao = messages.DetectorJsTsMensagens.eventHandlerAnySugestao;
            }
            else if (/\[\s*key\s*:\s*string\s*\]\s*:\s*any/.test(lineContext)) {
                mensagem = messages.DetectorJsTsMensagens.indexSignatureAny;
                sugestao = messages.DetectorJsTsMensagens.indexSignatureAnySugestao;
            }
            else if (/Record<[^,]+,\s*any>/.test(lineContext)) {
                mensagem = messages.DetectorJsTsMensagens.recordAny(varNome || undefined);
                sugestao = messages.DetectorJsTsMensagens.recordAnySugestao;
            }
            else if (/Array<any>/.test(lineContext) || /any\[\]/.test(lineContext)) {
                mensagem = messages.DetectorJsTsMensagens.arrayAny(varNome || undefined);
                sugestao = messages.DetectorJsTsMensagens.arrayAnySugestao;
            }
            else {
                mensagem = messages.DetectorJsTsMensagens.tipoAnyGenerico(varNome || undefined);
                sugestao = messages.DetectorJsTsMensagens.tipoAnyGenericoSugestao;
            }
            let contextoAdicional = '';
            if (fullCaminho?.includes('tipos/')) {
                contextoAdicional = messages.DetectorJsTsMensagens.contextoAdicionalTipos;
            }
            else if (fullCaminho?.includes('core/') || fullCaminho?.includes('shared/')) {
                contextoAdicional = messages.DetectorJsTsMensagens.contextoAdicionalCore;
            }
            const mensagemCompleta = `${mensagem} | [IDEIA] ${sugestao}${contextoAdicional}${messages.DetectorJsTsMensagens.revisaoManual}`;
            if (shouldSuppressOccurrence('tipo-inseguro-any', relPath)) {
                continue;
            }
            ocorrencias.push({
                tipo: 'tipo-inseguro-any',
                nivel: 'aviso',
                mensagem: mensagemCompleta,
                relPath,
                linha,
                contexto: lineContext
            });
        }
        const tiposFracosPadrao = /:\s*(Object|\{\})(?![a-zA-Z0-9_$])/g;
        let matchFraco;
        while ((matchFraco = tiposFracosPadrao.exec(src)) !== null) {
            const position = matchFraco.index || 0;
            if (isInStringOrComment(src, position))
                continue;
            const antesObj = src.substring(Math.max(0, position - 10), position);
            if (/Object\s*\.\s*$/.test(antesObj))
                continue;
            const linha = splitLines(src.substring(0, position)).length;
            const lineContext = splitLines(src)[linha - 1]?.trim() || '';
            const tipo = matchFraco[1];
            const antes = src.substring(Math.max(0, position - 30), position);
            const depois = lineContext.substring(lineContext.indexOf(':') + 1);
            if (/\?\s*:\s*\{\}\s*=/.test(`${antes}: {}`))
                continue;
            if (/\?\s*:\s*\{\}\s*[=,)]/.test(antes))
                continue;
            if (/Partial<|Required<|Readonly<|\}\?$/.test(antes))
                continue;
            if (/catch\s*\([^)]*:\s*\{\}/.test(lineContext))
                continue;
            if (depois.trim().startsWith('='))
                continue;
            if (/^\s*\{?\s*\}\s*[,=)]/.test(depois))
                continue;
            if (/\w+\s*:\s*\{\}\s*$/.test(lineContext))
                continue;
            if (/\?\s*\{[^}]*\}\s*:\s*\{\}/.test(lineContext))
                continue;
            if (/:\s*\{\}\s*$/.test(lineContext.trim()))
                continue;
            const mensagem = messages.DetectorJsTsMensagens.tipoPermissivo(tipo);
            const sugestao = tipo === 'Object' ? messages.DetectorJsTsMensagens.tipoObjectSugestao : messages.DetectorJsTsMensagens.tipoVazioSugestao;
            if (shouldSuppressOccurrence('tipo-permissivo-object', relPath))
                continue;
            ocorrencias.push({
                tipo: 'tipo-permissivo-object',
                nivel: 'aviso',
                mensagem: `${mensagem} | [IDEIA] ${sugestao}`,
                relPath,
                linha,
                contexto: lineContext
            });
        }
        const asAnyPadrao = /\b(as\s+any)\b/g;
        let asAnyMatch;
        while ((asAnyMatch = asAnyPadrao.exec(src)) !== null) {
            const position = asAnyMatch.index || 0;
            if (isInStringOrComment(src, position)) {
                continue;
            }
            const linha = splitLines(src.substring(0, position)).length;
            const lineContext = splitLines(src)[linha - 1]?.trim() || '';
            const after = src.substring(position, Math.min(src.length, position + 50));
            const mensagem = messages.DetectorJsTsMensagens.typeAssertionAny;
            let sugestao = '';
            if (/\)\s*as\s+any/.test(lineContext)) {
                sugestao = messages.DetectorJsTsMensagens.assertionCastFuncaoSugestao;
            }
            else if (/\.\w+\s+as\s+any/.test(lineContext)) {
                sugestao = messages.DetectorJsTsMensagens.assertionCastPropriedadeSugestao;
            }
            else if (/\bas\s+any\s*\)/.test(after)) {
                sugestao = messages.DetectorJsTsMensagens.assertionCastParametroSugestao;
            }
            else {
                sugestao = messages.DetectorJsTsMensagens.assertionCastGenericoSugestao;
            }
            const mensagemCompleta = `${mensagem} | [IDEIA] ${sugestao}${messages.DetectorJsTsMensagens.assertionCritico}${messages.DetectorJsTsMensagens.revisaoManual}`;
            if (shouldSuppressOccurrence('tipo-inseguro-any-assertion', relPath)) {
                continue;
            }
            ocorrencias.push({
                tipo: 'tipo-inseguro-any-assertion',
                nivel: 'erro',
                mensagem: mensagemCompleta,
                relPath,
                linha,
                contexto: lineContext
            });
        }
        const angleBracketPadrao = /<any>/g;
        let angleBracketMatch;
        while ((angleBracketMatch = angleBracketPadrao.exec(src)) !== null) {
            const position = angleBracketMatch.index || 0;
            if (isInStringOrComment(src, position)) {
                continue;
            }
            const linha = splitLines(src.substring(0, position)).length;
            const lineContext = splitLines(src)[linha - 1]?.trim() || '';
            const mensagemCompleta = `${messages.DetectorJsTsMensagens.angleBracketCast}${messages.DetectorJsTsMensagens.revisaoManual}`;
            if (shouldSuppressOccurrence('tipo-inseguro-any-cast', relPath)) {
                continue;
            }
            ocorrencias.push({
                tipo: 'tipo-inseguro-any-cast',
                nivel: 'erro',
                mensagem: mensagemCompleta,
                relPath,
                linha,
                contexto: lineContext
            });
        }
        const unknownPadrao = /:\s*unknown\b/g;
        let unknownMatch;
        while ((unknownMatch = unknownPadrao.exec(src)) !== null) {
            const position = unknownMatch.index || 0;
            if (isInStringOrComment(src, position)) {
                continue;
            }
            if (isUnknownInGenericContext(src, position)) {
                continue;
            }
            const linha = splitLines(src.substring(0, position)).length;
            const lineContext = splitLines(src)[linha - 1]?.trim() || '';
            const categorizacao = categorizarUnknown(src, fullCaminho || relPath, lineContext);
            const varNome = extractVariableName(unknownMatch, src);
            let mensagem = '';
            let nivel;
            if (categorizacao.categoria === 'legitimo') {
                if (categorizacao.confianca >= 95) {
                    continue;
                }
                mensagem = messages.DetectorJsTsMensagens.unknownLegitimo(varNome || undefined, categorizacao.motivo);
                nivel = 'info';
                if (categorizacao.sugestao) {
                    mensagem += ` | [IDEIA] ${categorizacao.sugestao}`;
                }
            }
            else if (categorizacao.categoria === 'melhoravel') {
                nivel = 'aviso';
                mensagem = messages.DetectorJsTsMensagens.unknownMelhoravel(varNome || undefined, categorizacao.confianca);
                mensagem += ` | ${categorizacao.motivo}`;
                if (categorizacao.sugestao) {
                    mensagem += ` | [IDEIA] ${categorizacao.sugestao}`;
                }
                else {
                    mensagem += ` | [IDEIA] Revisar uso para inferir tipo mais específico`;
                }
                mensagem += messages.DetectorJsTsMensagens.unknownRevisaoManual;
            }
            else {
                nivel = 'erro';
                mensagem = messages.DetectorJsTsMensagens.unknownCorrigir(varNome || undefined, categorizacao.confianca);
                mensagem += ` | ${categorizacao.motivo}`;
                if (categorizacao.sugestao) {
                    mensagem += ` | [EDIT]  ${categorizacao.sugestao}`;
                }
                mensagem += messages.DetectorJsTsMensagens.unknownRevisaoObrigatoria;
            }
            if (shouldSuppressOccurrence('tipo-inseguro-unknown', relPath)) {
                continue;
            }
            ocorrencias.push({
                tipo: 'tipo-inseguro-unknown',
                nivel,
                mensagem,
                relPath,
                linha,
                contexto: lineContext
            });
        }
        return ocorrencias;
    }
};
export const detectorTiposInseguros = ANALISTA;
//# sourceMappingURL=detector-types-unsafe.js.map