import { exportarRelatoriosFixTypes } from '../handlers/index.js';
import { ExitCode, expandIncludePatterns, processPatternList, sair } from '../helpers/index.js';
import { config } from '../../core/config/index.js';
import { getMessages } from '../../core/messages/index.js';
import { PROJETO_RAIZ } from '../../core/registry/index.js';
import { Command } from 'commander';
import { asTecnicas, extrairMensagemErro } from '../../types/index.js';
const { CliComandoFixTypesMensagens, DICAS, formatarTipoInseguro, gerarResumoCategoria, ICONES_FIX_TYPES: ICONES, log, MENSAGENS_AUTOFIX, MENSAGENS_CLI_CORRECAO_TIPOS, MENSAGENS_ERRO_FIX_TYPES: MENSAGENS_ERRO, MENSAGENS_INICIO_FIX_TYPES: MENSAGENS_INICIO, MENSAGENS_PROGRESSO_FIX_TYPES: MENSAGENS_PROGRESSO, MENSAGENS_RESUMO, MENSAGENS_SUCESSO_FIX_TYPES: MENSAGENS_SUCESSO, TEMPLATE_RESUMO_FINAL, TEXTOS_CATEGORIZACAO_CORRECAO_TIPOS, } = getMessages();
function mostrarErroDev(err) {
    if (!config.DEV_MODE)
        return;
    console.error(extrairMensagemErro(err));
    if (err && typeof err === 'object' && 'stack' in err) {
        const errWithStack = err;
        console.error(errWithStack.stack);
    }
}
let registroAnalistasCache = [];
async function carregarInquisicao() {
    const modInq = await import('../../core/execution/index.js');
    const modReg = await import('../../analysts/registry/index.js');
    registroAnalistasCache = modReg.registroAnalistas;
    const analistaTiposInseguros = registroAnalistasCache?.find((arquivo) => {
        return typeof arquivo === 'object' && arquivo !== null && arquivo.nome === 'detector-tipos-inseguros';
    });
    return {
        iniciarInquisicao: modInq.iniciarInquisicao,
        analistaTiposInseguros,
        tecnicas: asTecnicas(registroAnalistasCache)
    };
}
async function processarCategorizacao(porArquivo, verbose) {
    const { categorizarUnknown, extractLineContext } = await import('../../analysts/corrections/type-safety/index.js');
    const stats = { legitimo: 0, melhoravel: 0, corrigir: 0, totalConfianca: 0 };
    const ocorrenciasCategorizadas = [];
    for (const [arquivo, ocorrenciasArquivo] of Object.entries(porArquivo)) {
        if (verbose) {
            log.info(MENSAGENS_PROGRESSO.arquivoAtual(arquivo, ocorrenciasArquivo.length));
        }
        for (const ocorrencia of ocorrenciasArquivo) {
            const tipo = ocorrencia.tipo;
            if (tipo === 'tipo-inseguro-any') {
                ocorrenciasCategorizadas.push({
                    ocorrencia,
                    categoria: 'corrigir',
                    confianca: 95,
                    motivo: TEXTOS_CATEGORIZACAO_CORRECAO_TIPOS.anyMotivo,
                    sugestao: TEXTOS_CATEGORIZACAO_CORRECAO_TIPOS.anySugestao
                });
                stats.corrigir++;
                stats.totalConfianca += 95;
                if (verbose) {
                    log.aviso(MENSAGENS_CLI_CORRECAO_TIPOS.verboseAnyDetectado(arquivo, String(ocorrencia.linha || '?')));
                }
                continue;
            }
            if (tipo === 'tipo-inseguro-any-assertion') {
                ocorrenciasCategorizadas.push({
                    ocorrencia,
                    categoria: 'corrigir',
                    confianca: 100,
                    motivo: TEXTOS_CATEGORIZACAO_CORRECAO_TIPOS.asAnyMotivo,
                    sugestao: TEXTOS_CATEGORIZACAO_CORRECAO_TIPOS.asAnySugestao
                });
                stats.corrigir++;
                stats.totalConfianca += 100;
                if (verbose) {
                    log.erro(MENSAGENS_CLI_CORRECAO_TIPOS.verboseAsAnyCritico(arquivo, String(ocorrencia.linha || '?')));
                }
                continue;
            }
            if (tipo === 'tipo-inseguro-any-cast') {
                ocorrenciasCategorizadas.push({
                    ocorrencia,
                    categoria: 'corrigir',
                    confianca: 100,
                    motivo: TEXTOS_CATEGORIZACAO_CORRECAO_TIPOS.angleAnyMotivo,
                    sugestao: TEXTOS_CATEGORIZACAO_CORRECAO_TIPOS.angleAnySugestao
                });
                stats.corrigir++;
                stats.totalConfianca += 100;
                if (verbose) {
                    log.erro(MENSAGENS_CLI_CORRECAO_TIPOS.verboseAngleAnyCritico(arquivo, String(ocorrencia.linha || '?')));
                }
                continue;
            }
            if (tipo === 'tipo-inseguro-unknown') {
                const fs = await import('node:fs/promises');
                const path = await import('node:path');
                try {
                    const fullCaminho = path.join(PROJETO_RAIZ, arquivo);
                    const codigo = await fs.readFile(fullCaminho, 'utf-8');
                    const lineContext = extractLineContext(codigo, (ocorrencia.linha || 1) * 80);
                    const categorizacao = categorizarUnknown(codigo, arquivo, lineContext);
                    ocorrenciasCategorizadas.push({
                        ocorrencia,
                        ...categorizacao
                    });
                    const catKey = categorizacao.categoria;
                    stats[catKey]++;
                    stats.totalConfianca += categorizacao.confianca;
                    if (verbose) {
                        const prefixos = { legitimo: '[SUCESSO]', melhoravel: '[AVISO]', corrigir: '[ERRO]' };
                        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.verboseUnknownCategoria(prefixos[categorizacao.categoria], arquivo, String(ocorrencia.linha || '?'), categorizacao.categoria, categorizacao.confianca));
                        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.verboseMotivo(categorizacao.motivo));
                        if (categorizacao.sugestao) {
                            log.info(MENSAGENS_CLI_CORRECAO_TIPOS.verboseSugestao(categorizacao.sugestao));
                        }
                        if (categorizacao.variantes && categorizacao.confianca < 80) {
                            log.info(MENSAGENS_CLI_CORRECAO_TIPOS.verboseVariantesTitulo);
                            categorizacao.variantes.forEach((variante, idx) => {
                                log.info(MENSAGENS_CLI_CORRECAO_TIPOS.verboseVarianteItem(idx + 1, variante));
                            });
                        }
                    }
                }
                catch {
                    ocorrenciasCategorizadas.push({
                        ocorrencia,
                        categoria: 'melhoravel',
                        confianca: 60,
                        motivo: TEXTOS_CATEGORIZACAO_CORRECAO_TIPOS.semContextoMotivo,
                        sugestao: TEXTOS_CATEGORIZACAO_CORRECAO_TIPOS.semContextoSugestao
                    });
                    stats.melhoravel++;
                    stats.totalConfianca += 60;
                }
            }
        }
    }
    return { ocorrenciasCategorizadas, stats };
}
function mostrarResumo(stats) {
    const total = stats.legitimo + stats.melhoravel + stats.corrigir;
    const mediaConfianca = total > 0 ? Math.round(stats.totalConfianca / total) : 0;
    const linhasLegitimo = gerarResumoCategoria('LEGITIMO', stats.legitimo, total);
    log.sucesso(linhasLegitimo[0]);
    log.info(linhasLegitimo[1]);
    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    const linhasMelhoravel = gerarResumoCategoria('MELHORAVEL', stats.melhoravel, total);
    log.aviso(linhasMelhoravel[0]);
    log.info(linhasMelhoravel[1]);
    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    const linhasCorrigir = gerarResumoCategoria('CORRIGIR', stats.corrigir, total);
    log.erro(linhasCorrigir[0]);
    log.info(linhasCorrigir[1]);
    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    log.info(MENSAGENS_RESUMO.confianciaMedia(mediaConfianca));
    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    return mediaConfianca;
}
function mostrarAltaPrioridade(ocorrenciasCategorizadas) {
    const altaPrioridade = ocorrenciasCategorizadas.filter(elem => elem.categoria === 'corrigir' && elem.confianca >= 85);
    if (altaPrioridade.length === 0)
        return;
    log.fase?.(MENSAGENS_CLI_CORRECAO_TIPOS.altaConfiancaTitulo(altaPrioridade.length));
    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    for (const item of altaPrioridade.slice(0, 5)) {
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.altaConfiancaLinha(item.ocorrencia.relPath, String(item.ocorrencia.linha || '?'), item.confianca));
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.altaConfiancaDetalhe(item.sugestao || item.motivo));
    }
    if (altaPrioridade.length > 5) {
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.altaConfiancaMais(altaPrioridade.length - 5));
    }
    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
}
function mostrarCasosIncertos(ocorrenciasCategorizadas, verbose) {
    const casosIncertos = ocorrenciasCategorizadas.filter(elem => elem.confianca < 70 && elem.variantes && elem.variantes.length > 0);
    if (!casosIncertos.length || !verbose)
        return;
    log.fase?.(MENSAGENS_CLI_CORRECAO_TIPOS.incertosTitulo(casosIncertos.length));
    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.incertosIntro);
    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    for (const item of casosIncertos.slice(0, 3)) {
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.incertosLinha(item.ocorrencia.relPath, String(item.ocorrencia.linha || '?'), item.confianca));
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.verboseMotivo(item.motivo));
        if (item.variantes) {
            log.info(MENSAGENS_CLI_CORRECAO_TIPOS.verboseVariantesTitulo);
            item.variantes.forEach((variante, idx) => {
                log.info(MENSAGENS_CLI_CORRECAO_TIPOS.verboseVarianteItem(idx + 1, variante));
            });
        }
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    }
    if (casosIncertos.length > 3) {
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.incertosMais(casosIncertos.length - 3));
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    }
}
async function aplicarCorrecoesAutomaticas(ocorrenciasCategorizadas, verbose) {
    const altaPrioridade = ocorrenciasCategorizadas.filter(elem => elem.categoria === 'corrigir' && elem.confianca >= 85);
    if (altaPrioridade.length === 0) {
        log.info(MENSAGENS_SUCESSO.nenhumAltaConfianca);
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
        log.info(MENSAGENS_AUTOFIX.dicas.ajustarConfianca);
        return;
    }
    console.log();
    log.fase?.(MENSAGENS_CLI_CORRECAO_TIPOS.aplicandoCorrecoesAuto);
    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    try {
        const { aplicarCorrecoesEmLote } = await import('../../analysts/corrections/auto-fix-engine.js');
        const porArquivo = {};
        for (const item of ocorrenciasCategorizadas) {
            const arquivo = item.ocorrencia.relPath || 'desconhecido';
            if (!porArquivo[arquivo]) {
                porArquivo[arquivo] = [];
            }
            porArquivo[arquivo].push(item);
        }
        const resultado = await aplicarCorrecoesEmLote(porArquivo, {
            dryRun: false,
            minConfianca: 85,
            verbose: Boolean(verbose),
            interactive: false
        });
        console.log();
        if (resultado.sucesso > 0) {
            log.sucesso(MENSAGENS_CLI_CORRECAO_TIPOS.correcoesResumoSucesso(resultado.sucesso));
            for (const res of resultado.resultados) {
                if (res.sucesso && res.linhasModificadas > 0) {
                    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.correcoesResumoLinhaOk(res.arquivo, res.linhasModificadas));
                }
                else if (!res.sucesso) {
                    log.erro(MENSAGENS_CLI_CORRECAO_TIPOS.correcoesResumoLinhaErro(res.arquivo, res.erro));
                }
            }
        }
        else {
            log.info(MENSAGENS_SUCESSO.nenhumaCorrecao);
        }
        if (resultado.falhas > 0) {
            console.log();
            log.erro(MENSAGENS_CLI_CORRECAO_TIPOS.correcoesResumoFalhas(resultado.falhas));
        }
        console.log();
        log.info(MENSAGENS_AUTOFIX.dicas.executarLint);
        log.info(MENSAGENS_AUTOFIX.dicas.executarBuild);
    }
    catch (err) {
        log.erro(CliComandoFixTypesMensagens.erroAplicarCorrecoes(err instanceof Error ? err.message : String(err)));
        sair(ExitCode.Failure);
    }
}
function mostrarExemplosDryRun(tiposInseguros, verbose, minConfidence) {
    log.fase?.(MENSAGENS_CLI_CORRECAO_TIPOS.exemplosDryRunTitulo);
    const exemplos = tiposInseguros.slice(0, 10);
    for (const ocorrencia of exemplos) {
        const prefixo = ocorrencia.tipo === 'tipo-inseguro-any' ? '[ERRO]' : '[AVISO]';
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.exemploLinha(prefixo, ocorrencia.relPath, String(ocorrencia.linha || '?')));
        if (ocorrencia.mensagem) {
            log.info(MENSAGENS_CLI_CORRECAO_TIPOS.exemploMensagem(ocorrencia.mensagem));
        }
        if (verbose && ocorrencia.mensagem) {
            const match = ocorrencia.mensagem.match(/variável '([^']+)'/);
            if (match) {
                log.debug(MENSAGENS_CLI_CORRECAO_TIPOS.debugVariavel(match[1]));
            }
        }
    }
    if (tiposInseguros.length > 10) {
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.maisOcorrencias(tiposInseguros.length - 10));
    }
    console.log();
    log.info(DICAS.removerDryRun);
    log.info(DICAS.usarInterativo);
    log.info(DICAS.ajustarConfianca(minConfidence));
}
function mostrarMensagemDryRun() {
    console.log();
    log.aviso(MENSAGENS_CLI_CORRECAO_TIPOS.dryRunAviso(ICONES.inicio));
    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    log.info(TEMPLATE_RESUMO_FINAL.titulo);
    for (const passo of TEMPLATE_RESUMO_FINAL.passos) {
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.templatePasso(passo));
    }
    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    log.info(MENSAGENS_AUTOFIX.dicas.removerDryRun);
}
export function criarComandoFixTypes() {
    const cmd = new Command('fix-types');
    cmd.description(CliComandoFixTypesMensagens.descricao).option('--dry-run', 'Mostra o que seria corrigido sem aplicar mudanças', false).option('--target <path>', 'Diretório ou arquivo específico para analisar', 'src').option('--confidence <number>', 'Nível mínimo de confiança para aplicar correções (0-100)', '85').option('--verbose', 'Mostra detalhes de cada correção', false).option('--interactive', 'Modo interativo: confirma cada correção', false).option('--export', 'Exporta relatórios JSON e Markdown para pasta relatorios/', false).option('--include <padrao>', 'Glob pattern a INCLUIR (pode repetir a flag ou usar vírgulas / espaços para múltiplos)', (val, prev) => {
        prev.push(val);
        return prev;
    }, []).option('--exclude <padrao>', 'Glob pattern a EXCLUIR adicionalmente (pode repetir a flag ou usar vírgulas / espaços)', (val, prev) => {
        prev.push(val);
        return prev;
    }, []).action(async (options) => {
        try {
            await executarFixTypes(options);
        }
        catch (err) {
            const mensagem = err instanceof Error ? err.message : String(err);
            log.erro(MENSAGENS_CLI_CORRECAO_TIPOS.erroExecutar(mensagem));
            mostrarErroDev(err);
            sair(ExitCode.Failure);
        }
    });
    return cmd;
}
async function executarFixTypes(options) {
    const isDryRun = options.dryRun || false;
    const minConfidence = Number(options.confidence) || 85;
    const target = options.target || 'src';
    const verbose = options.verbose || false;
    log.fase?.(MENSAGENS_INICIO.titulo);
    const includeListRaw = processPatternList(options.include);
    const includeList = includeListRaw.length ? expandIncludePatterns(includeListRaw) : [];
    const excludeList = processPatternList(options.exclude);
    if (includeList.length)
        config.CLI_INCLUDE_PATTERNS = includeList;
    if (excludeList.length)
        config.CLI_EXCLUDE_PATTERNS = excludeList;
    const { iniciarInquisicao, analistaTiposInseguros, tecnicas: tecnicasParaExec } = await carregarInquisicao();
    if (!analistaTiposInseguros) {
        log.erro(MENSAGENS_ERRO.detectorNaoEncontrado);
        sair(ExitCode.Failure);
        return;
    }
    log.info(MENSAGENS_INICIO.analisando(target));
    log.info(MENSAGENS_INICIO.confianciaMin(minConfidence));
    log.info(MENSAGENS_INICIO.modo(isDryRun));
    let resultado;
    try {
        resultado = await iniciarInquisicao(process.cwd(), {
            includeContent: true,
            incluirMetadados: false,
            skipExec: false
        }, tecnicasParaExec);
    }
    catch (err) {
        log.erro(CliComandoFixTypesMensagens.erroExecutarAnalise(err instanceof Error ? err.message : String(err)));
        sair(ExitCode.Failure);
        return;
    }
    const ocorrencias = resultado.ocorrencias || [];
    const tiposInseguros = ocorrencias.filter((ocorrencia) => ocorrencia.tipo && ['tipo-inseguro-any', 'tipo-inseguro-any-assertion', 'tipo-inseguro-any-cast', 'tipo-inseguro-unknown'].includes(ocorrencia.tipo));
    if (tiposInseguros.length === 0) {
        log.sucesso(MENSAGENS_SUCESSO.nenhumTipoInseguro);
        return;
    }
    log.aviso(MENSAGENS_RESUMO.encontrados(tiposInseguros.length));
    const porTipo = tiposInseguros.reduce((acc, ocorrencia) => {
        const tipo = ocorrencia.tipo || 'desconhecido';
        if (!acc[tipo])
            acc[tipo] = [];
        acc[tipo].push(ocorrencia);
        return acc;
    }, {});
    for (const [tipo, ocorrenciasTipo] of Object.entries(porTipo)) {
        const count = ocorrenciasTipo.length;
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaResumoTipo(formatarTipoInseguro(tipo, count)));
    }
    console.log();
    if (isDryRun) {
        mostrarExemplosDryRun(tiposInseguros, verbose, minConfidence);
        return;
    }
    log.fase?.(MENSAGENS_CLI_CORRECAO_TIPOS.aplicandoCorrecoesAuto);
    const { fixAnyToProperTipo, fixUnknownToSpecificTipo } = await import('../../analysts/corrections/quick-fixes/index.js');
    if (!fixAnyToProperTipo || !fixUnknownToSpecificTipo) {
        log.erro(MENSAGENS_ERRO.modulosNaoEncontrados);
        sair(ExitCode.Failure);
        return;
    }
    const porArquivo = tiposInseguros.reduce((acc, ocorrencia) => {
        const arquivo = ocorrencia.relPath || 'desconhecido';
        if (!acc[arquivo])
            acc[arquivo] = [];
        acc[arquivo].push(ocorrencia);
        return acc;
    }, {});
    log.info(MENSAGENS_PROGRESSO.processandoArquivos(Object.keys(porArquivo).length));
    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    const { ocorrenciasCategorizadas, stats } = await processarCategorizacao(porArquivo, verbose);
    console.log();
    log.fase?.(MENSAGENS_RESUMO.tituloCategorizacao);
    log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    const mediaConfianca = mostrarResumo(stats);
    await salvarAnaliseDetalhada(ocorrenciasCategorizadas, stats, mediaConfianca, verbose);
    mostrarAltaPrioridade(ocorrenciasCategorizadas);
    mostrarCasosIncertos(ocorrenciasCategorizadas, verbose);
    const casosAltaPrioridade = ocorrenciasCategorizadas.filter(elem => elem.categoria === 'corrigir' && elem.confianca >= 85);
    if (casosAltaPrioridade.length > 0) {
        await aplicarCorrecoesAutomaticas(ocorrenciasCategorizadas, verbose);
    }
    else if (isDryRun) {
        mostrarMensagemDryRun();
    }
    else {
        console.log();
        log.info(MENSAGENS_SUCESSO.nenhumAltaConfianca);
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
        log.info(MENSAGENS_AUTOFIX.dicas.ajustarConfianca);
    }
    if (options.export || config.REPORT_EXPORT_ENABLED) {
        await exportarRelatoriosFixTypes({
            baseDir: PROJETO_RAIZ,
            casos: ocorrenciasCategorizadas.map(item => ({
                arquivo: item.ocorrencia.relPath || 'desconhecido',
                linha: item.ocorrencia.linha,
                tipo: item.ocorrencia.tipo,
                categoria: item.categoria,
                confianca: item.confianca,
                motivo: item.motivo,
                sugestao: item.sugestao,
                variantes: item.variantes,
                contexto: 'contexto' in item.ocorrencia ? item.ocorrencia.contexto : undefined
            })),
            stats,
            minConfidence,
            verbose: Boolean(verbose)
        });
    }
    const temAny = porTipo['tipo-inseguro-any']?.length > 0;
    if (temAny && !isDryRun) {
        sair(ExitCode.Failure);
    }
}
async function salvarAnaliseDetalhada(ocorrenciasCategorizadas, stats, mediaConfianca, verbose) {
    if (!verbose)
        return;
    try {
        const fs = await import('node:fs/promises');
        const path = await import('node:path');
        const total = stats.legitimo + stats.melhoravel + stats.corrigir;
        const reportCaminho = path.join(PROJETO_RAIZ, '.tutanus', 'fix-types-analise.json');
        await fs.mkdir(path.dirname(reportCaminho), { recursive: true });
        await fs.writeFile(reportCaminho, JSON.stringify({
            timestamp: new Date().toISOString(),
            stats,
            mediaConfianca,
            total,
            casos: ocorrenciasCategorizadas.map(elem => ({
                arquivo: elem.ocorrencia.relPath,
                linha: elem.ocorrencia.linha,
                categoria: elem.categoria,
                confianca: elem.confianca,
                motivo: elem.motivo,
                sugestao: elem.sugestao,
                variantes: elem.variantes || []
            }))
        }, null, 2));
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.analiseDetalhadaSalva);
        log.info(MENSAGENS_CLI_CORRECAO_TIPOS.linhaEmBranco);
    }
    catch (err) {
        log.aviso(`Não foi possível salvar análise detalhada: ${err instanceof Error ? err.message : String(err)}`);
    }
}
//# sourceMappingURL=command-fix-types.js.map