/*
 * History manager 
 * Created by: Michael Pastushkov <michael@pastushkov.com>
 */

const WHOAMI = 'I am a virtual cat helping you to the best of my abilities.';
const ADVICE = 'Prioritize the user\'s latest messages. Use prior turns only as context. Respond in the language of the request.';

class HistoryManager {

    constructor({ maxTurns = 6 } = {}) {
        this.threads = new Map(); // topic -> { turns: [], summary: '' }
        this.maxTurns = maxTurns;
    }

    ensure(topic) {
        if (!this.threads.has(topic))
            this.threads.set(topic, { turns: [], summary: '' });
        return this.threads.get(topic);
    }

    addUser(topic, content) {
        let t = this.ensure(topic); 
        t.turns.push({ role: 'user', content }); 
    }
    
    addAssistant(topic, content) { 
        let t = this.ensure(topic); 
        t.turns.push({ role: 'assistant', content }); 
    }
    
    setSummary(topic, summary) { 
        let t = this.ensure(topic);
        t.summary = summary; 
    }

    pickRelevant(turns, currentPrompt, limit) {
        if (!turns.length) return [];
        // Simple recency + token overlap; language-agnostic
        const needles = new Set(currentPrompt.toLowerCase().split(/\W+/).filter(Boolean));
        const scored = turns.map((m, i) => {
            const words = m.content.toLowerCase().split(/\W+/).filter(Boolean);
            const overlap = words.reduce((acc, w) => acc + (needles.has(w) ? 1 : 0), 0);
            const recency = i / Math.max(1, turns.length);
            return { m, score: overlap + recency * 0.5 };
        });
        return scored.sort((a, b) => b.score - a.score).slice(0, limit)
            .sort((a, b) => turns.indexOf(a.m) - turns.indexOf(b.m))
            .map(s => s.m);
    }

    buildMessages(prompt, topic) {

        const thread = this.ensure(topic);
        const relevant = this.pickRelevant(thread.turns, prompt, this.maxTurns);

        const msgs = [];
        msgs.push({ role: 'system', content: WHOAMI });
        msgs.push({ role: 'system', content: ADVICE });

        if (thread.summary)
            msgs.push({ role: 'system', content: `Context summary (${topic}): ${thread.summary}` });

        msgs.push(...relevant);
        msgs.push({ role: 'user', content: prompt });

        return msgs;
    }
}

module.exports = HistoryManager;

/* Testing * /
(async () => {
    const cm = new ConversationManager({
        model: 'gpt-oss:20b-tuned', // 'llama3:8b',
        embedModel: 'nomic-embed-text', // `ollama pull` this if not present
        maxTurns: 6
    });

    // Prompt 1 — auto-creates a "cats" topic (via embeddings + labeler)
    let r = await cm.ask('How many cat breeds are there?');
    console.log('\n\n[topic]', r.topic, '\n', r.text);

    // Prompt 2 — different wording, same topic picked automatically
    r = await cm.ask('Name the major ones (just names).');
    console.log('\n\n[topic]', r.topic, '\n', r.text);

    // Prompt 3 — likely a new topic
    r = await cm.ask('Configure Nginx as a reverse proxy for an Express app.');
    console.log('\n\n[topic]', r.topic, '\n', r.text);
})();

/**/