import path from 'node:path';
import { gzipSync } from 'node:zlib';
import { config } from '../../core/config/index.js';
import { salvarBinario, salvarEstado } from '../persistence/index.js';
function chunkArray(arr, size) {
    const out = [];
    for (let indice = 0; indice < arr.length; indice += size)
        out.push(arr.slice(indice, indice + size));
    return out;
}
export async function fragmentarRelatorio(relatorioFull, dir, ts, options) {
    const maxOcorrencias = options?.maxOcorrenciasPerShard ?? config.REPORT_FRAGMENT_OCCURRENCES ?? 2000;
    const maxArquivoEntries = options?.maxFileEntriesPerShard ?? config.REPORT_FRAGMENT_FILEENTRIES ?? 500;
    const topN = config.REPORT_FRAGMENT_SUMMARY_TOPN ?? 5;
    const rel = relatorioFull;
    const resultado = rel && 'resultado' in rel ? rel.resultado : rel;
    const ocorrencias = resultado && Array.isArray(resultado.ocorrencias) ? resultado.ocorrencias : [];
    const fileEntries = resultado && Array.isArray(resultado.fileEntries) ? resultado.fileEntries : [];
    const salvar = salvarEstado;
    const manifest = {
        generatedAt: new Date().toISOString(),
        baseNome: `tutanus-relatorio-full-${ts}`,
        parts: []
    };
    const meta = {
        ...rel
    };
    if (meta.resultado && typeof meta.resultado === 'object') {
        const raiz = meta.resultado;
        delete raiz.ocorrencias;
        delete raiz.fileEntries;
    }
    const metaFilename = `tutanus-relatorio-full-${ts}-meta.json.gz`;
    const metaBuf = Buffer.from(JSON.stringify(meta, null, 2), 'utf-8');
    const metaGz = gzipSync(metaBuf);
    await salvarBinario(path.join(dir, metaFilename), metaGz);
    manifest.parts.push({
        kind: 'meta',
        file: metaFilename,
        bytes: metaGz.length
    });
    if (ocorrencias.length > 0) {
        const occPedacos = chunkArray(ocorrencias, maxOcorrencias);
        for (let indice = 0; indice < occPedacos.length; indice++) {
            const fname = `tutanus-relatorio-full-${ts}-ocorrencias-part-${indice + 1}.json.gz`;
            const payload = {
                shard: {
                    kind: 'ocorrencias',
                    index: indice + 1,
                    total: occPedacos.length
                },
                count: occPedacos[indice].length,
                ocorrencias: occPedacos[indice]
            };
            const buf = Buffer.from(JSON.stringify(payload, null, 2), 'utf-8');
            const gz = gzipSync(buf);
            await salvarBinario(path.join(dir, fname), gz);
            const tiposContagem = {};
            const arquivosContagem = {};
            for (const ocorrencia of occPedacos[indice]) {
                const oLegacy = ocorrencia;
                const tipoOcorrencia = ocorrencia && (ocorrencia.tipo || oLegacy.type) ? String(ocorrencia.tipo ?? oLegacy.type) : 'desconhecido';
                tiposContagem[tipoOcorrencia] = (tiposContagem[tipoOcorrencia] || 0) + 1;
                const relp = ocorrencia && (ocorrencia.relPath || oLegacy.path) ? String(ocorrencia.relPath ?? oLegacy.path) : 'desconhecido';
                arquivosContagem[relp] = (arquivosContagem[relp] || 0) + 1;
            }
            const topTipos = Object.entries(tiposContagem).sort((arquivo, base) => base[1] - arquivo[1]).slice(0, topN).map(([chave, valor]) => ({
                tipo: chave,
                count: valor
            }));
            const topArquivos = Object.entries(arquivosContagem).sort((arquivo, base) => base[1] - arquivo[1]).slice(0, topN).map(([chave, valor]) => ({
                arquivo: chave,
                count: valor
            }));
            manifest.parts.push({
                kind: 'ocorrencias',
                file: fname,
                index: indice + 1,
                total: occPedacos.length,
                count: occPedacos[indice].length,
                bytes: gz.length,
                summary: {
                    topTipos,
                    topArquivos
                }
            });
        }
    }
    if (fileEntries.length > 0) {
        const fePedacos = chunkArray(fileEntries, maxArquivoEntries);
        for (let indice = 0; indice < fePedacos.length; indice++) {
            const fname = `tutanus-relatorio-full-${ts}-fileentries-part-${indice + 1}.json.gz`;
            const payload = {
                shard: {
                    kind: 'fileEntries',
                    index: indice + 1,
                    total: fePedacos.length
                },
                count: fePedacos[indice].length,
                fileEntries: fePedacos[indice]
            };
            const buf = Buffer.from(JSON.stringify(payload, null, 2), 'utf-8');
            const gz = gzipSync(buf);
            await salvarBinario(path.join(dir, fname), gz);
            const arquivosResumo = [];
            for (const fe of fePedacos[indice]) {
                const feLegacy = fe;
                const rel = fe && (fe.relPath || fe.fullCaminho || feLegacy.path) ? String(fe.relPath ?? fe.fullCaminho ?? feLegacy.path) : 'desconhecido';
                let linhas = undefined;
                try {
                    if (fe && typeof fe.content === 'string')
                        linhas = fe.content.split(/\r?\n/).length;
                }
                catch { }
                arquivosResumo.push({
                    arquivo: rel,
                    linhas
                });
            }
            const topArquivosByLinhas = arquivosResumo.filter(arquivo => typeof arquivo.linhas === 'number').sort((arquivo, base) => (base.linhas ?? 0) - (arquivo.linhas ?? 0)).slice(0, topN);
            manifest.parts.push({
                kind: 'fileEntries',
                file: fname,
                index: indice + 1,
                total: fePedacos.length,
                count: fePedacos[indice].length,
                bytes: gz.length,
                summary: {
                    topArquivosByLinhas
                }
            });
        }
    }
    const manifestFilename = `tutanus-relatorio-full-${ts}-manifest.json`;
    await salvar(path.join(dir, manifestFilename), manifest);
    return {
        manifestFile: manifestFilename,
        manifest
    };
}
//# sourceMappingURL=fragment-report.js.map