import { readFile } from "node:fs/promises";
import { atomicWriteFile } from "./_shared.js";
// ---------------------------------------------------------------------------
// Path helpers
// ---------------------------------------------------------------------------
/**
 * Derive the chunk ndjson path from the index path.
 * {hash}.index.json → {hash}.chunks.ndjson
 */
export function getChunkPath(indexPath) {
    return indexPath.replace(/\.index\.json$/, ".chunks.ndjson");
}
/**
 * Derive the chunk-embedding ndjson path from the index path.
 * {hash}.index.json → {hash}.chunk-embeddings.ndjson
 */
export function getChunkEmbeddingPath(indexPath) {
    return indexPath.replace(/\.index\.json$/, ".chunk-embeddings.ndjson");
}
function isChunkLine(value) {
    if (typeof value !== "object" || value === null)
        return false;
    const obj = value;
    return (typeof obj["id"] === "string" &&
        typeof obj["file"] === "string" &&
        typeof obj["startLine"] === "number" &&
        typeof obj["endLine"] === "number" &&
        typeof obj["text"] === "string" &&
        typeof obj["tokenCount"] === "number");
}
/**
 * Save all chunks atomically as ndjson.
 * File: ~/.codesift/{hash}.chunks.ndjson
 */
export async function saveChunks(chunkPath, chunks) {
    const lines = chunks.map((c) => JSON.stringify({
        id: c.id,
        file: c.file,
        startLine: c.startLine,
        endLine: c.endLine,
        text: c.text,
        tokenCount: c.tokenCount,
    }));
    const data = lines.join("\n") + "\n";
    await atomicWriteFile(chunkPath, data);
}
/** Generic NDJSON loader — reads file, parses each line, filters with a type guard, maps to value. */
async function loadNdjsonMap(filePath, guard, toEntry) {
    try {
        const raw = await readFile(filePath, "utf-8");
        const map = new Map();
        for (const line of raw.split("\n")) {
            const trimmed = line.trim();
            if (!trimmed)
                continue;
            try {
                const parsed = JSON.parse(trimmed);
                if (guard(parsed)) {
                    const [key, value] = toEntry(parsed);
                    map.set(key, value);
                }
            }
            catch {
                // Skip malformed lines
            }
        }
        return map.size > 0 ? map : null;
    }
    catch {
        return null;
    }
}
/**
 * Load all chunks from an ndjson file.
 * Returns a Map of chunkId → CodeChunk, or null if file not found.
 */
export async function loadChunks(chunkPath) {
    return loadNdjsonMap(chunkPath, isChunkLine, (parsed) => [parsed.id, parsed]);
}
/**
 * Save all chunk embeddings atomically as ndjson.
 * File: ~/.codesift/{hash}.chunk-embeddings.ndjson
 */
export async function saveChunkEmbeddings(embeddingPath, embeddings) {
    const lines = [];
    for (const [id, vec] of embeddings) {
        lines.push(JSON.stringify({ id, vec: Array.from(vec) }));
    }
    const data = lines.join("\n") + "\n";
    await atomicWriteFile(embeddingPath, data);
}
function isChunkEmbeddingLine(parsed) {
    return typeof parsed === "object" && parsed !== null &&
        typeof parsed["id"] === "string" &&
        Array.isArray(parsed["vec"]);
}
/**
 * Load all chunk embeddings from an ndjson file.
 * Returns a Map of chunkId → Float32Array, or null if file not found / empty.
 */
export async function loadChunkEmbeddings(embeddingPath) {
    return loadNdjsonMap(embeddingPath, isChunkEmbeddingLine, (parsed) => [parsed.id, new Float32Array(parsed.vec)]);
}
//# sourceMappingURL=chunk-store.js.map