import { promises as fs } from 'node:fs';
import path from 'node:path';
import { config, resolverPluginSeguro } from '../../core/config/index.js';
import { getMessages } from '../../core/messages/index.js';
import { importarModuloSeguro } from '../../core/utils/index.js';
import { reescreverImports } from '../../shared/helpers/index.js';
import pLimit from 'p-limit';
import { mapaReversao } from './map-reversion.js';
const { log, logAuto, CorretorEstruturaExtraMensagens } = getMessages();
export async function corrigirEstrutura(mapa, fileEntries, baseDir = process.cwd()) {
    const CONCORRENCIA = Number(config.STRUCTURE_CONCURRENCY ?? 5);
    const AUTO_CORRECAO = Boolean(config.STRUCTURE_AUTO_FIX);
    const PLUGINS = config.STRUCTURE_PLUGINS || [];
    const ESTRUTURA_CAMADAS = config.ESTRUTURA_CAMADAS;
    const limit = pLimit(CONCORRENCIA);
    await Promise.all(mapa.map(entry => limit(async () => {
        const { arquivo, ideal, atual } = entry;
        if (!ideal || ideal === atual)
            return;
        const origem = path.join(baseDir, arquivo);
        const nomeArquivo = path.basename(arquivo);
        const destino = path.join(baseDir, ideal, nomeArquivo);
        if (!AUTO_CORRECAO) {
            log.info(CorretorEstruturaExtraMensagens.simular.replace('{arquivo}', arquivo).replace('{destino}', path.relative(baseDir, destino)));
            return;
        }
        try {
            await fs.mkdir(path.dirname(destino), {
                recursive: true
            });
        }
        catch (err) {
            const msg = err && typeof err === 'object' && 'message' in err ? String(err.message) : String(err);
            logAuto.corretorErroCriarDiretorio(destino, msg);
            return;
        }
        try {
            const conteudo = await fs.readFile(origem, 'utf-8');
            const { novoConteudo } = reescreverImports(conteudo, path.posix.normalize(arquivo.replace(/\\/g, '/')), path.posix.normalize(path.relative(baseDir, destino).replace(/\\/g, '/')));
            await mapaReversao.registrarMove(arquivo, path.relative(baseDir, destino), entry.motivo || 'Reorganização estrutural', conteudo, novoConteudo, true);
            try {
                await fs.writeFile(destino, novoConteudo, { encoding: 'utf-8', flag: 'wx' });
            }
            catch (err) {
                const code = err.code;
                if (code === 'EEXIST') {
                    logAuto.corretorDestinoExiste(arquivo, path.relative(baseDir, destino));
                    return;
                }
                throw err;
            }
            await fs.unlink(origem);
            log.sucesso(CorretorEstruturaExtraMensagens.movido.replace('{arquivo}', arquivo).replace('{destino}', path.relative(baseDir, destino)));
        }
        catch (err) {
            const msg = err && typeof err === 'object' && 'message' in err ? String(err.message) : String(err);
            logAuto.corretorErroMover(arquivo, msg);
        }
    })));
    for (const pluginRel of PLUGINS) {
        try {
            const resolvido = resolverPluginSeguro(baseDir, String(pluginRel));
            if (resolvido.erro) {
                logAuto.pluginIgnorado(String(pluginRel), resolvido.erro);
                continue;
            }
            const caminhoPlugin = resolvido.caminho;
            if (!caminhoPlugin) {
                logAuto.caminhoNaoResolvido(String(pluginRel));
                continue;
            }
            const pluginModule = await importarModuloSeguro(baseDir, String(pluginRel));
            let pluginFn;
            if (pluginModule && typeof pluginModule === 'object' && 'default' in pluginModule && typeof pluginModule.default === 'function') {
                pluginFn = pluginModule.default;
            }
            else if (typeof pluginModule === 'function') {
                pluginFn = pluginModule;
            }
            if (typeof pluginFn === 'function') {
                await pluginFn({
                    mapa,
                    baseDir,
                    layers: ESTRUTURA_CAMADAS,
                    fileEntries
                });
            }
        }
        catch (err) {
            let msg = 'erro desconhecido';
            if (err && typeof err === 'object' && 'message' in err && typeof err.message === 'string') {
                msg = String(err.message);
            }
            else if (typeof err === 'string') {
                msg = err;
            }
            logAuto.pluginFalhou(String(pluginRel), String(msg));
        }
    }
}
//# sourceMappingURL=corrector-structure.js.map