// storage/vector-store/migrator.ts — JSON to SQLite migration.
// SPEC-075 AC-05: Idempotent, preserves JSON backup.
import { readJson, projectDataDir } from '../base-store.js';
import { existsSync } from 'node:fs';
import { TFIDFEngine } from '../../engine/vector-store/tfidf.js';
/** Check if a migration marker exists (idempotency). */
function migrationMarkerPath(projectId) {
    return `${projectDataDir(projectId)}/.vector-migrated`;
}
/** Check if migration has already been done. */
export function isMigrated(projectId) {
    return existsSync(migrationMarkerPath(projectId));
}
/** Create migration marker. */
async function markMigrated(projectId) {
    const { writeFile, mkdir } = await import('node:fs/promises');
    const { dirname } = await import('node:path');
    const markerPath = migrationMarkerPath(projectId);
    await mkdir(dirname(markerPath), { recursive: true });
    await writeFile(markerPath, new Date().toISOString(), 'utf-8');
}
/** Load legacy patterns from JSON. */
async function loadPatterns(dataDir) {
    const items = [];
    const patternsPath = `${dataDir}/patterns.json`;
    if (!existsSync(patternsPath)) {
        return items;
    }
    const patterns = await readJson(patternsPath, []);
    for (let i = 0; i < patterns.length; i++) {
        const p = patterns[i];
        if (p?.pattern) {
            items.push({
                type: 'pattern',
                id: `pattern-${String(i)}`,
                text: p.pattern,
                meta: { category: p.category, usageCount: p.usageCount },
            });
        }
    }
    return items;
}
/** Load legacy knowledge from JSON. */
async function loadKnowledge(dataDir) {
    const items = [];
    const knowledgePath = `${dataDir}/knowledge.json`;
    if (!existsSync(knowledgePath)) {
        return items;
    }
    const knowledge = await readJson(knowledgePath, []);
    for (let i = 0; i < knowledge.length; i++) {
        const k = knowledge[i];
        if (k) {
            items.push({
                type: 'knowledge',
                id: `knowledge-${String(i)}`,
                text: `${k.key}: ${k.value}`,
                meta: { source: k.source },
            });
        }
    }
    return items;
}
/** Load legacy decisions from JSON. */
async function loadDecisions(dataDir) {
    const items = [];
    const decisionsPath = `${dataDir}/decisions.json`;
    if (!existsSync(decisionsPath)) {
        return items;
    }
    const decisions = await readJson(decisionsPath, []);
    for (let i = 0; i < decisions.length; i++) {
        const d = decisions[i];
        if (d) {
            items.push({
                type: 'decision',
                id: `decision-${String(i)}`,
                text: `${d.decision} ${d.rationale ?? ''}`.trim(),
                meta: { specId: d.specId },
            });
        }
    }
    return items;
}
/**
 * Migrate legacy JSON data to the vector store backend.
 * Idempotent: skips if migration marker exists.
 * Does NOT delete original JSON files.
 */
export async function migrateJsonToBackend(projectId, backend) {
    if (isMigrated(projectId)) {
        return { documentsProcessed: 0, durationMs: 0, errors: [] };
    }
    const start = Date.now();
    const errors = [];
    let processed = 0;
    const dataDir = projectDataDir(projectId);
    // Collect all texts, catching errors per source
    const allTexts = [];
    for (const loader of [loadPatterns, loadKnowledge, loadDecisions]) {
        try {
            const items = await loader(dataDir);
            allTexts.push(...items);
        }
        catch (err) {
            errors.push(err instanceof Error ? err.message : String(err));
        }
    }
    // Build IDF from all texts
    const tfidf = new TFIDFEngine();
    for (const item of allTexts) {
        tfidf.addDocument(item.text);
    }
    // Insert all entries with embeddings
    const now = new Date().toISOString();
    for (const item of allTexts) {
        try {
            const embedding = tfidf.embed(item.text);
            const entry = {
                id: item.id,
                type: item.type,
                content: item.text,
                embedding,
                metadata: item.meta,
                createdAt: now,
                updatedAt: now,
            };
            await backend.insert(entry);
            processed++;
        }
        catch (err) {
            errors.push(`${item.id}: ${err instanceof Error ? err.message : String(err)}`);
        }
    }
    await markMigrated(projectId);
    const durationMs = Date.now() - start;
    return { documentsProcessed: processed, durationMs, errors };
}
//# sourceMappingURL=migrator.js.map