import { access, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { readNdjsonFile, readSectionedCodeIndex, writeNdjsonFile, writeSectionedCodeIndex } from '../code/index-io.js';
import { abortIfNeeded } from '../utils.js';
function bundleMetaPath(directory) {
    return path.join(directory, 'bundle.json');
}
function codeIndexPath(directory) {
    return path.join(directory, 'code-index');
}
function codeChunksPath(directory) {
    return path.join(directory, 'code-chunks.ndjson');
}
function documentChunksPath(directory) {
    return path.join(directory, 'document-chunks.ndjson');
}
function corpusChunksPath(directory) {
    return path.join(directory, 'corpus-chunks.ndjson');
}
function referencesPath(directory) {
    return path.join(directory, 'code-document-references.ndjson');
}
async function exists(filePath) {
    try {
        await access(filePath);
        return true;
    }
    catch {
        return false;
    }
}
async function timedSection(section, read, onTiming) {
    const startedAt = Date.now();
    try {
        const result = await read();
        const finishedAt = Date.now();
        onTiming?.({
            section,
            startedAt,
            finishedAt,
            durationMs: finishedAt - startedAt,
            present: result.present,
        });
        return result.value;
    }
    catch (error) {
        const finishedAt = Date.now();
        onTiming?.({
            section,
            startedAt,
            finishedAt,
            durationMs: finishedAt - startedAt,
            present: false,
        });
        throw error;
    }
}
export async function writeSectionedWorkspaceBundle(directory, bundle, signal) {
    await rm(directory, { recursive: true, force: true });
    await mkdir(directory, { recursive: true });
    abortIfNeeded(signal);
    const { codeIndex, codeChunks, documentChunks, corpusChunks, codeDocumentReferences, ...boundedBundle } = bundle;
    await writeFile(bundleMetaPath(directory), JSON.stringify(boundedBundle, null, 2), 'utf8');
    abortIfNeeded(signal);
    if (codeIndex) {
        await writeSectionedCodeIndex(codeIndexPath(directory), codeIndex, {}, signal);
    }
    if (codeChunks) {
        await writeNdjsonFile(codeChunksPath(directory), codeChunks, signal);
    }
    if (documentChunks) {
        await writeNdjsonFile(documentChunksPath(directory), documentChunks, signal);
    }
    if (corpusChunks) {
        await writeNdjsonFile(corpusChunksPath(directory), corpusChunks, signal);
    }
    await writeNdjsonFile(referencesPath(directory), codeDocumentReferences ?? [], signal);
}
export async function readSectionedWorkspaceBundle(directory, signal, yielder, onTiming) {
    abortIfNeeded(signal);
    const boundedBundle = await timedSection('bundle', async () => {
        const rawBundle = await readFile(bundleMetaPath(directory), 'utf8');
        return {
            value: JSON.parse(rawBundle),
            present: true,
        };
    }, onTiming);
    await yielder?.tick();
    const codeIndex = await timedSection('codeIndex', async () => {
        if (!(await exists(codeIndexPath(directory))))
            return { value: undefined, present: false };
        return { value: (await readSectionedCodeIndex(codeIndexPath(directory), signal)).index, present: true };
    }, onTiming);
    await yielder?.tick();
    const codeChunks = await timedSection('codeChunks', async () => {
        if (!(await exists(codeChunksPath(directory))))
            return { value: undefined, present: false };
        return { value: await readNdjsonFile(codeChunksPath(directory), signal), present: true };
    }, onTiming);
    await yielder?.tick();
    const documentChunks = await timedSection('documentChunks', async () => {
        if (!(await exists(documentChunksPath(directory))))
            return { value: undefined, present: false };
        return { value: await readNdjsonFile(documentChunksPath(directory), signal), present: true };
    }, onTiming);
    await yielder?.tick();
    const corpusChunks = await timedSection('corpusChunks', async () => {
        if (!(await exists(corpusChunksPath(directory))))
            return { value: undefined, present: false };
        return { value: await readNdjsonFile(corpusChunksPath(directory), signal), present: true };
    }, onTiming);
    await yielder?.tick();
    const codeDocumentReferences = await timedSection('codeDocumentReferences', async () => {
        if (!(await exists(referencesPath(directory))))
            return { value: [], present: false };
        return { value: await readNdjsonFile(referencesPath(directory), signal), present: true };
    }, onTiming);
    await yielder?.tick();
    return {
        ...boundedBundle,
        codeIndex,
        codeChunks,
        documentChunks,
        corpusChunks,
        codeDocumentReferences,
    };
}
//# sourceMappingURL=bundle-io.js.map