"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.semanticSearchMemories = semanticSearchMemories;
exports.getRelatedMemories = getRelatedMemories;
exports.getSemanticTopics = getSemanticTopics;
const database_1 = require("../database/database");
const STOP_WORDS = new Set([
    'the', 'a', 'an', 'and', 'or', 'but', 'if', 'then', 'else', 'for', 'to', 'of', 'in', 'on', 'at', 'by', 'with', 'from', 'is', 'are', 'was', 'were', 'be', 'been', 'it', 'this', 'that', 'these', 'those', 'how', 'what', 'why', 'when', 'where', 'which'
]);
const SYNONYMS = {
    bug: ['error', 'issue', 'failure', 'problem'],
    error: ['bug', 'failure', 'exception'],
    fix: ['resolve', 'patch', 'repair', 'solution'],
    decision: ['choice', 'selected', 'picked'],
    test: ['verification', 'jest', 'spec', 'check'],
    build: ['compile', 'tsc', 'bundle'],
    refactor: ['cleanup', 'restructure', 'extract'],
    auth: ['authentication', 'login', 'signin'],
    db: ['database', 'sqlite', 'postgres', 'mysql'],
    perf: ['performance', 'speed', 'latency'],
};
function semanticSearchMemories(options) {
    const db = (0, database_1.getDb)();
    const queryTerms = expandTerms(tokenize(options.query));
    let sql = 'SELECT id, project, type, topic, summary, importance, created_at FROM memory_events WHERE 1=1';
    const params = [];
    if (options.project) {
        sql += ' AND project = ?';
        params.push(options.project);
    }
    if (options.minImportance !== undefined) {
        sql += ' AND importance >= ?';
        params.push(options.minImportance);
    }
    if (options.days) {
        const since = new Date(Date.now() - options.days * 86400000).toISOString();
        sql += ' AND created_at >= ?';
        params.push(since);
    }
    sql += ' ORDER BY created_at DESC LIMIT 500';
    const rows = db.prepare(sql).all(...params);
    const results = rows.map((row) => scoreSemantic(row, queryTerms))
        .filter((r) => r.semanticScore > 0)
        .sort((a, b) => b.semanticScore - a.semanticScore)
        .slice(0, options.limit || 20);
    return results;
}
function getRelatedMemories(memoryId, limit = 10) {
    const db = (0, database_1.getDb)();
    const row = db.prepare('SELECT id, project, type, topic, summary, importance, created_at FROM memory_events WHERE id = ?').get(memoryId);
    if (!row)
        return [];
    return semanticSearchMemories({ query: `${row.type} ${row.topic || ''} ${row.summary}`, project: row.project, limit: limit + 1 })
        .filter((r) => r.id !== memoryId)
        .slice(0, limit);
}
function getSemanticTopics(project, query) {
    const results = semanticSearchMemories({ query, project, limit: 20 });
    const topics = results.map((r) => r.topic).filter(Boolean);
    return [...new Set(topics)].slice(0, 10);
}
function scoreSemantic(row, queryTerms) {
    const haystack = `${row.type} ${row.topic || ''} ${row.summary}`.toLowerCase();
    let score = 0;
    const matchedTerms = [];
    for (const term of queryTerms) {
        if (haystack.includes(term)) {
            matchedTerms.push(term);
            if ((row.topic || '').toLowerCase().includes(term))
                score += 30;
            else if (row.summary.toLowerCase().includes(term))
                score += 22;
            else if (row.type.toLowerCase().includes(term))
                score += 18;
            else
                score += 10;
        }
    }
    score += row.importance * 4;
    const ageHours = (Date.now() - new Date(row.created_at).getTime()) / 3600000;
    if (ageHours < 24)
        score += 15;
    else if (ageHours < 24 * 7)
        score += 8;
    else if (ageHours < 24 * 30)
        score += 4;
    const typeBoost = { decision: 16, fix: 14, error: 13, pattern: 12, handoff: 10 };
    score += typeBoost[row.type] || 0;
    return {
        ...row,
        semanticScore: score,
        matchedTerms,
        rationale: matchedTerms.length > 0
            ? `Matched ${matchedTerms.join(', ')} with importance ${row.importance}`
            : `Ranked by importance ${row.importance}`,
    };
}
function tokenize(input) {
    return input
        .toLowerCase()
        .split(/[^a-z0-9_]+/)
        .map((t) => t.trim())
        .filter((t) => t.length >= 2 && !STOP_WORDS.has(t));
}
function expandTerms(terms) {
    const out = new Set();
    for (const term of terms) {
        out.add(term);
        for (const [key, vals] of Object.entries(SYNONYMS)) {
            if (term === key || vals.includes(term)) {
                out.add(key);
                for (const v of vals)
                    out.add(v);
            }
        }
    }
    return [...out];
}
//# sourceMappingURL=semantic-memory.js.map