import { mkdir, readdir, readFile, unlink, writeFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { Session } from "@sean.holung/minicode-sdk";
let sessionsDir = path.join(os.homedir(), ".minicode", "sessions");
export class DuplicateSessionLabelError extends Error {
    label;
    existingSessionId;
    constructor(label, existingSessionId) {
        super(`A saved session named "${label}" already exists. Choose a different name or load that session to update it.`);
        this.label = label;
        this.existingSessionId = existingSessionId;
        this.name = "DuplicateSessionLabelError";
    }
}
/** Override sessions directory (for testing). */
export function setSessionsDir(dir) {
    sessionsDir = dir;
}
function normalizeSessionLabel(label) {
    return label.trim().toLowerCase();
}
export async function saveSession(session, label, annotations) {
    await mkdir(sessionsDir, { recursive: true });
    const savedAt = new Date().toISOString();
    const snapshot = session.toJSON();
    const resolvedLabel = label && label.trim().length > 0
        ? label.trim()
        : new Date().toLocaleString();
    const duplicate = (await listSessions()).find((savedSession) => savedSession.id !== snapshot.id &&
        normalizeSessionLabel(savedSession.label) === normalizeSessionLabel(resolvedLabel));
    if (duplicate) {
        throw new DuplicateSessionLabelError(resolvedLabel, duplicate.id);
    }
    const data = {
        label: resolvedLabel,
        savedAt,
        session: snapshot,
        ...(annotations && Object.keys(annotations).length > 0 ? { annotations } : {}),
    };
    const filePath = path.join(sessionsDir, `${snapshot.id}.json`);
    await writeFile(filePath, JSON.stringify(data, null, 2), "utf8");
    return {
        id: snapshot.id,
        label: resolvedLabel,
        createdAt: snapshot.createdAt,
        savedAt,
        messageCount: snapshot.messages.length,
    };
}
export async function listSessions() {
    let files;
    try {
        files = await readdir(sessionsDir);
    }
    catch {
        return [];
    }
    const results = [];
    for (const file of files) {
        if (!file.endsWith(".json"))
            continue;
        try {
            const raw = await readFile(path.join(sessionsDir, file), "utf8");
            const data = JSON.parse(raw);
            results.push({
                id: data.session.id,
                label: data.label,
                createdAt: data.session.createdAt,
                savedAt: data.savedAt,
                messageCount: data.session.messages.length,
            });
        }
        catch {
            // skip corrupt files
        }
    }
    results.sort((a, b) => b.savedAt.localeCompare(a.savedAt));
    return results;
}
export async function loadSession(sessionId) {
    const filePath = path.join(sessionsDir, `${sessionId}.json`);
    try {
        const raw = await readFile(filePath, "utf8");
        const data = JSON.parse(raw);
        return {
            session: Session.fromJSON(data.session),
            label: data.label,
            ...(data.annotations ? { annotations: data.annotations } : {}),
        };
    }
    catch {
        return undefined;
    }
}
export async function loadSessionByLabel(label) {
    const sessions = await listSessions();
    const match = sessions.find((s) => s.label.toLowerCase() === label.toLowerCase());
    if (!match)
        return undefined;
    return loadSession(match.id);
}
export async function deleteSession(sessionId) {
    const filePath = path.join(sessionsDir, `${sessionId}.json`);
    try {
        await unlink(filePath);
        return true;
    }
    catch {
        return false;
    }
}
