import { execSync } from 'node:child_process';
import { readFileSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { applyQuickFix, findQuickFixes, getAutoFixConfig } from '../../../core/config/auto/index.js';
import { cloneRepo, escreverAskpassScript, limparAskpassScript } from '../app/repo-downloader.js';
import { executarAnaliseInterna } from './full-analysis-job.js';
import { atualizarJob, executarJob } from './job-manager.js';
async function getToken(app, installationId) {
    const { data } = await app.octokit.request('POST /app/installations/{installation_id}/access_tokens', {
        installation_id: installationId
    });
    return data.token;
}
export async function iniciarAutoFix(app, jobId, job) {
    await executarJob(jobId, async () => {
        atualizarJob(jobId, { status: 'baixando' });
        const { repoDir, cleanup } = await cloneRepo(app, job.installationId, job.owner, job.repo, job.ref);
        try {
            atualizarJob(jobId, { status: 'analisando' });
            const inicio = Date.now();
            const { totalArquivos, arquivosAnalisados, todasOcorrencias, fileEntriesComAst } = await executarAnaliseInterna(repoDir, job.options);
            const autoFixOcorrencias = todasOcorrencias.filter((o) => o.tipo === 'auto-fix-disponivel' || o.tipo === 'QUICK_FIX_DISPONIVEL');
            const autoFixConfig = getAutoFixConfig(job.options.autoFixMode || 'balanced');
            const fixesPorArquivo = new Map();
            let correcoesAplicadas = 0;
            for (const ocorrencia of autoFixOcorrencias) {
                const entry = fileEntriesComAst?.find((fe) => fe.relPath === ocorrencia.relPath);
                if (!entry)
                    continue;
                const filePath = join(repoDir, entry.relPath);
                const currentCode = readFileSync(filePath, 'utf-8');
                const fixes = findQuickFixes(currentCode, undefined, autoFixConfig, entry.relPath);
                if (fixes.length === 0)
                    continue;
                let modifiedCode = currentCode;
                for (const fix of fixes) {
                    for (const match of fix.matches) {
                        try {
                            modifiedCode = applyQuickFix(modifiedCode, fix, match);
                            correcoesAplicadas++;
                        }
                        catch {
                        }
                    }
                }
                if (modifiedCode !== currentCode) {
                    fixesPorArquivo.set(filePath, modifiedCode);
                }
            }
            const ocorrencias = todasOcorrencias.map(o => ({
                mensagem: typeof o.mensagem === 'string' ? o.mensagem : String(o.mensagem ?? ''),
                relPath: typeof o.relPath === 'string' ? o.relPath : String(o.relPath ?? ''),
                tipo: typeof o.tipo === 'string' ? o.tipo : undefined,
                nivel: typeof o.nivel === 'string' ? o.nivel : undefined,
                linha: typeof o.linha === 'number' ? o.linha : undefined,
                coluna: typeof o.coluna === 'number' ? o.coluna : undefined,
                sugestao: typeof o.sugestao === 'string' ? o.sugestao : undefined
            }));
            let autoFixResultado = {
                arquivosModificados: fixesPorArquivo.size,
                correcoesAplicadas
            };
            if (fixesPorArquivo.size > 0) {
                for (const [filePath, newContent] of fixesPorArquivo) {
                    writeFileSync(filePath, newContent, 'utf-8');
                }
                const octokit = await app.getInstallationOctokit(job.installationId);
                const branchName = `tutanus-fix-${Date.now()}`;
                execSync('git add -A', { cwd: repoDir, stdio: 'pipe' });
                execSync(`git commit -m "fix: correcoes automaticas Tutanus" -m "Total: ${correcoesAplicadas} correcoes em ${fixesPorArquivo.size} arquivos."`, { cwd: repoDir, stdio: 'pipe' });
                const token = await getToken(app, job.installationId);
                const askpassScript = escreverAskpassScript();
                const repoUrl = `https://github.com/${job.owner}/${job.repo}.git`;
                try {
                    execSync(`git push "${repoUrl}" HEAD:${branchName}`, {
                        cwd: repoDir,
                        stdio: 'pipe',
                        timeout: 60000,
                        env: {
                            ...process.env,
                            TUTANUS_GIT_TOKEN: token,
                            GIT_ASKPASS: askpassScript,
                            GIT_TERMINAL_PROMPT: '0'
                        }
                    });
                }
                finally {
                    limparAskpassScript(askpassScript);
                }
                const defaultBranch = job.ref === 'HEAD' ? (await getDefaultBranch(octokit, job.owner, job.repo)) : job.ref;
                const changedFiles = Array.from(fixesPorArquivo.keys())
                    .map(f => `- \`${f.replace(repoDir, '')}\``)
                    .join('\n');
                const { data: pr } = await octokit.request('POST /repos/{owner}/{repo}/pulls', {
                    owner: job.owner,
                    repo: job.repo,
                    title: 'fix: correções automáticas do Tutanus',
                    head: branchName,
                    base: defaultBranch,
                    body: `## Correções Automáticas - Tutanus

          O Tutanus identificou e aplicou **${correcoesAplicadas}** correções em **${fixesPorArquivo.size}** arquivos.

          ### Arquivos modificados

          ${changedFiles}

          ---
          *Este PR foi gerado automaticamente pelo [Tutanus](https://github.com/anomalyco/tutanus).*`
                });
                autoFixResultado = {
                    arquivosModificados: fixesPorArquivo.size,
                    correcoesAplicadas,
                    prUrl: pr.html_url,
                    prNumero: pr.number,
                    branchName
                };
            }
            atualizarJob(jobId, {
                status: 'completo',
                finalizadoEm: Date.now(),
                resultado: {
                    totalArquivos,
                    totalOcorrencias: ocorrencias.length,
                    duracaoMs: Date.now() - inicio,
                    arquivosAnalisados,
                    ocorrencias,
                    scoreGeral: 0,
                    resumoPorTipo: {},
                    resumoPorSeveridade: {},
                    autoFixResultado
                }
            });
        }
        finally {
            cleanup();
        }
    });
}
async function getDefaultBranch(octokit, owner, repo) {
    try {
        const { data } = await octokit.request('GET /repos/{owner}/{repo}', { owner, repo });
        return data.default_branch;
    }
    catch {
        return 'main';
    }
}
//# sourceMappingURL=auto-fix-job.js.map