import { readJson, writeJson, projectDataDir } from './base-store.js';
import { withFileLock } from './file-mutex.js';
import { readdir, unlink } from 'node:fs/promises';
// --- internal helpers ---
function sanitizeId(id) {
    const sanitized = id.replace(/[/\\]/g, '_').replace(/\.\./g, '_');
    if (!sanitized || sanitized === '.' || sanitized === '..') {
        throw new Error(`Invalid ID: ${id}`);
    }
    return sanitized;
}
function sessionsDir(projectId) {
    return `${projectDataDir(projectId)}/sessions`;
}
function sessionFile(projectId, sessionId) {
    return `${sessionsDir(projectId)}/session-${sanitizeId(sessionId)}.json`;
}
function memoryFile(projectId) {
    return `${projectDataDir(projectId)}/session-memory.json`;
}
async function listSessionFiles(projectId) {
    try {
        const dir = sessionsDir(projectId);
        const entries = await readdir(dir);
        return entries.filter((f) => f.startsWith('session-') && f.endsWith('.json'));
    }
    catch {
        return [];
    }
}
// --- public API ---
/** Save a session to disk. */
export async function save(session) {
    const file = sessionFile(session.projectId, session.id);
    await withFileLock(file, () => writeJson(file, session));
}
/** Load a session by ID. Returns null if not found. */
export async function load(projectId, sessionId) {
    return readJson(sessionFile(projectId, sessionId), null);
}
/** List sessions for a project, ordered by lastSavedAt desc. */
export async function list(projectId) {
    const files = await listSessionFiles(projectId);
    const sessions = [];
    for (const f of files) {
        const id = f.replace('session-', '').replace('.json', '');
        const s = await load(projectId, id);
        if (s) {
            sessions.push(s);
        }
    }
    sessions.sort((a, b) => b.lastSavedAt.localeCompare(a.lastSavedAt));
    return sessions;
}
/** Get the most recent session for a project. */
export async function getLatest(projectId) {
    const all = await list(projectId);
    return all[0] ?? null;
}
/** Delete a session by ID. Returns true if removed. */
export async function deleteSession(projectId, sessionId) {
    try {
        await unlink(sessionFile(projectId, sessionId));
        return true;
    }
    catch {
        return false;
    }
}
/** List sessions as lightweight items for display. */
export async function listItems(projectId, limit = 10) {
    const all = await list(projectId);
    return all.slice(0, limit).map((s) => ({
        id: s.id,
        startedAt: s.startedAt,
        lastSavedAt: s.lastSavedAt,
        contextSummary: s.contextSummary.slice(0, 200),
        toolCallCount: s.toolCallCount,
    }));
}
// --- cleanup (AC-10) ---
const MAX_SESSIONS = 50;
const MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
/** Clean up old sessions: keep max 50, remove sessions older than 30 days. */
export async function cleanup(projectId) {
    const all = await list(projectId);
    let removed = 0;
    const now = Date.now();
    // Remove sessions older than 30 days
    for (const s of all) {
        const age = now - new Date(s.lastSavedAt).getTime();
        if (age > MAX_AGE_MS) {
            await deleteSession(projectId, s.id);
            removed++;
        }
    }
    // Remove excess beyond MAX_SESSIONS (oldest first, list is already desc)
    const remaining = all.length - removed;
    if (remaining > MAX_SESSIONS) {
        const toRemove = all.slice(MAX_SESSIONS).filter((s) => {
            const age = now - new Date(s.lastSavedAt).getTime();
            return age <= MAX_AGE_MS; // not already removed above
        });
        for (const s of toRemove) {
            await deleteSession(projectId, s.id);
            removed++;
        }
    }
    if (removed > 0) {
        console.warn(`[Planu] Cleaned up ${String(removed)} old sessions for project ${projectId}`);
    }
    return removed;
}
// --- session memory (AC-11) ---
/** Load cross-conversation memory for a project. */
export async function loadMemory(projectId) {
    return readJson(memoryFile(projectId), {
        projectId,
        decisions: [],
        updatedAt: new Date().toISOString(),
    });
}
/** Save cross-conversation memory. */
export async function saveMemory(memory) {
    const file = memoryFile(memory.projectId);
    await withFileLock(file, () => writeJson(file, memory));
}
//# sourceMappingURL=session-store.js.map