/**
 * Session catalog index — persistent metadata index for faster session search.
 * Index file: ~/.owlcoda/sessions/.index.json
 */
import { readFile, writeFile, readdir } from 'node:fs/promises';
import { existsSync } from 'node:fs';
import { join } from 'node:path';
import { getOwlcodaDir } from '../paths.js';
// ─── Paths ───
function getSessionsDir() {
    return join(getOwlcodaDir(), 'sessions');
}
function getIndexPath() {
    return join(getSessionsDir(), '.index.json');
}
// ─── In-memory cache ───
let cachedIndex = null;
let cachedIndexMtime = 0;
// ─── Core operations ───
/**
 * Build or rebuild the full catalog index by scanning all session files.
 */
export async function buildIndex() {
    const dir = getSessionsDir();
    if (!existsSync(dir)) {
        const empty = { version: 1, builtAt: new Date().toISOString(), entries: {} };
        cachedIndex = empty;
        return empty;
    }
    const files = await readdir(dir);
    const jsonFiles = files.filter(f => f.endsWith('.json') && !f.startsWith('.'));
    const entries = {};
    for (const f of jsonFiles) {
        try {
            const raw = await readFile(join(dir, f), 'utf-8');
            const session = JSON.parse(raw);
            entries[session.meta.id] = session.meta;
        }
        catch {
            // Skip corrupt files
        }
    }
    const index = {
        version: 1,
        builtAt: new Date().toISOString(),
        entries,
    };
    // Persist to disk
    try {
        await writeFile(getIndexPath(), JSON.stringify(index), 'utf-8');
    }
    catch {
        // Non-fatal — index is still usable in memory
    }
    cachedIndex = index;
    cachedIndexMtime = Date.now();
    return index;
}
/**
 * Load index from disk if available and not stale.
 */
export async function loadIndex() {
    // Check if cached index is fresh (< 60s old)
    if (cachedIndex && (Date.now() - cachedIndexMtime) < 60_000) {
        return cachedIndex;
    }
    const indexPath = getIndexPath();
    if (existsSync(indexPath)) {
        try {
            const raw = await readFile(indexPath, 'utf-8');
            const index = JSON.parse(raw);
            if (index.version === 1 && index.entries) {
                cachedIndex = index;
                cachedIndexMtime = Date.now();
                return index;
            }
        }
        catch {
            // Corrupt index — rebuild
        }
    }
    return buildIndex();
}
/**
 * Update a single entry in the index.
 */
export async function updateIndexEntry(id, meta) {
    const index = await loadIndex();
    index.entries[id] = meta;
    index.builtAt = new Date().toISOString();
    cachedIndex = index;
    cachedIndexMtime = Date.now();
    try {
        await writeFile(getIndexPath(), JSON.stringify(index), 'utf-8');
    }
    catch {
        // Non-fatal
    }
}
/**
 * Remove an entry from the index.
 */
export async function removeIndexEntry(id) {
    const index = await loadIndex();
    delete index.entries[id];
    cachedIndex = index;
    try {
        await writeFile(getIndexPath(), JSON.stringify(index), 'utf-8');
    }
    catch {
        // Non-fatal
    }
}
/**
 * Search index by metadata fields (fast — no file I/O per session).
 */
export async function searchIndex(query, limit = 20) {
    const index = await loadIndex();
    const lower = query.toLowerCase();
    const results = [];
    for (const meta of Object.values(index.entries)) {
        if (results.length >= limit)
            break;
        const searchable = [meta.id, meta.model, meta.preview, ...(meta.tags ?? [])].join(' ').toLowerCase();
        if (searchable.includes(lower)) {
            results.push(meta);
        }
    }
    return results;
}
/**
 * Get all entries from the index as sorted array.
 */
export async function getAllIndexed(limit = 100) {
    const index = await loadIndex();
    return Object.values(index.entries)
        .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))
        .slice(0, limit);
}
/**
 * Get index stats.
 */
export async function getIndexStats() {
    const index = await loadIndex();
    return { count: Object.keys(index.entries).length, builtAt: index.builtAt };
}
/**
 * Clear cached index (for testing).
 */
export function clearIndexCache() {
    cachedIndex = null;
    cachedIndexMtime = 0;
}
//# sourceMappingURL=catalog.js.map