import { appendFileSync, mkdirSync } from 'fs';
import { homedir } from 'os';
import { join } from 'path';
const RING_BY_AGENT = new Map();
const LAST_BY_AGENT = new Map();
const MAX_PER_AGENT = 80;
const LOG_DIR = join(homedir(), '.cursorconnect');
const LOG_FILE = join(LOG_DIR, 'lenta-seq.jsonl');
export function messagesFingerprint(messages) {
    return messages
        .map((m) => {
        const t = String(m.text ?? '')
            .replace(/\s+/g, ' ')
            .trim()
            .slice(0, 80);
        return `${m.role}|${m.id ?? ''}|${t.length}|${t}`;
    })
        .join(';;');
}
export function tailPreview(messages, n = 3) {
    return messages
        .slice(-n)
        .map((m) => `${m.role}:${(m.text ?? '').replace(/\s+/g, ' ').trim().slice(0, 48)}`)
        .join(' | ');
}
export function detectSeqTransition(prev, next) {
    if (!prev)
        return 'none';
    if (prev.liveLen > 0 && next.liveLen === 0 && next.historyLen >= prev.historyLen) {
        return 'dom_to_jsonl';
    }
    if (next.liveLen > prev.liveLen && next.historyLen === prev.historyLen) {
        return 'overlay_grow';
    }
    if (next.liveLen < prev.liveLen && next.historyLen >= prev.historyLen) {
        return 'overlay_shrink';
    }
    if (next.historyLen > prev.historyLen)
        return 'jsonl_grow';
    return 'none';
}
export function recordLentaSeqEmit(agentId, seq, prevSeq, seqHeld, messages, meta) {
    const prev = LAST_BY_AGENT.get(agentId);
    const messagesSig = messagesFingerprint(messages);
    const transition = detectSeqTransition(prev, {
        historyLen: meta.historyLen,
        liveLen: meta.liveLen,
        source: meta.source,
    });
    const entry = {
        at: Date.now(),
        agentId,
        seq,
        prevSeq,
        seqHeld,
        reason: meta.reason,
        transition,
        source: meta.source,
        historyLen: meta.historyLen,
        liveLen: meta.liveLen,
        messagesLen: meta.messagesLen,
        messagesSig: messagesSig.slice(0, 400),
        tailPreview: tailPreview(messages),
        append: meta.append,
    };
    LAST_BY_AGENT.set(agentId, {
        seq,
        messagesSig,
        historyLen: meta.historyLen,
        liveLen: meta.liveLen,
        source: meta.source,
    });
    let ring = RING_BY_AGENT.get(agentId);
    if (!ring) {
        ring = [];
        RING_BY_AGENT.set(agentId, ring);
    }
    ring.push(entry);
    while (ring.length > MAX_PER_AGENT)
        ring.shift();
    try {
        mkdirSync(LOG_DIR, { recursive: true });
        appendFileSync(LOG_FILE, `${JSON.stringify(entry)}\n`);
    }
    catch {
        /* non-fatal */
    }
    if (process.env.LENTA_SEQ_ASSERT === '1') {
        if (!seqHeld && prev && prev.messagesSig === messagesSig) {
            console.warn(`[lenta-seq] seq bump without lenta change agent=${agentId.slice(0, 8)} seq ${prevSeq}→${seq} transition=${transition}`);
        }
        if (transition === 'dom_to_jsonl' && !seqHeld && prevSeq === seq) {
            console.warn(`[lenta-seq] dom→jsonl handoff but seq held agent=${agentId.slice(0, 8)} seq=${seq}`);
        }
    }
    return entry;
}
export function getLastLentaEmit(agentId) {
    return LAST_BY_AGENT.get(agentId);
}
export function getLentaSeqJournal(agentId) {
    if (!agentId) {
        return [...RING_BY_AGENT.values()].flat().sort((a, b) => a.at - b.at).slice(-MAX_PER_AGENT);
    }
    return [...(RING_BY_AGENT.get(agentId) ?? [])];
}
export function getLentaSeqLogPath() {
    return LOG_FILE;
}
