import fs from "node:fs";
import path from "node:path";
import { z } from "zod";
import { getConfigDir } from "../config/index.js";
const DEFAULT_MAILBOX = {
    activeSession: "general",
    memos: [],
    codingSession: {
        id: null,
        status: "idle",
        taskSummary: "",
    },
};
const MailboxMemoSchema = z.object({
    from: z.enum(["general", "coding"]),
    to: z.enum(["general", "coding"]),
    timestamp: z.string(),
    content: z.string(),
    inFlight: z.boolean().optional(),
});
const CodingSessionInfoSchema = z.object({
    id: z.string().nullable().default(null),
    status: z.enum(["idle", "in_progress", "paused", "completed"]).default("idle"),
    taskSummary: z.string().default(""),
    cwd: z.string().optional(),
});
const MailboxDataSchema = z.object({
    activeSession: z.enum(["general", "coding"]).default("general"),
    memos: z.array(MailboxMemoSchema).default([]),
    codingSession: CodingSessionInfoSchema.default(DEFAULT_MAILBOX.codingSession),
});
function getMailboxFile() {
    return path.join(getConfigDir(), "session-mailbox.json");
}
export function loadMailbox(options) {
    const file = getMailboxFile();
    if (!fs.existsSync(file))
        return { ...DEFAULT_MAILBOX };
    try {
        const raw = JSON.parse(fs.readFileSync(file, "utf-8"));
        const data = MailboxDataSchema.parse(raw);
        if (!options?.preserveInFlight) {
            for (const m of data.memos) {
                m.inFlight = false;
            }
        }
        return data;
    }
    catch {
        return { ...DEFAULT_MAILBOX };
    }
}
export function saveMailbox(data) {
    const file = getMailboxFile();
    const dir = path.dirname(file);
    if (!fs.existsSync(dir))
        fs.mkdirSync(dir, { recursive: true });
    fs.writeFileSync(file, JSON.stringify(data, null, 2), "utf-8");
}
export function addMemo(from, to, content) {
    const data = loadMailbox();
    data.memos.push({
        from,
        to,
        timestamp: new Date().toISOString(),
        content,
    });
    saveMailbox(data);
}
/**
 * Mark memos addressed to the given session as in-flight and return them.
 * The memos remain on disk until explicitly acknowledged via `ackMemos()`.
 * If the process crashes before ack, the memos survive and will be
 * re-delivered on the next call (their `inFlight` flag is cleared on load).
 */
export function consumeMemosFor(target) {
    const data = loadMailbox();
    const forTarget = [];
    for (const m of data.memos) {
        if (m.to === target) {
            m.inFlight = true;
            forTarget.push(m);
        }
    }
    if (forTarget.length > 0) {
        saveMailbox(data);
    }
    return forTarget;
}
/**
 * Acknowledge that memos for the target session have been successfully
 * injected into the agent context. Removes them from the mailbox on disk.
 */
export function ackMemos(target) {
    const data = loadMailbox({ preserveInFlight: true });
    data.memos = data.memos.filter((m) => !(m.to === target && m.inFlight));
    saveMailbox(data);
}
export function setActiveSession(mode) {
    const data = loadMailbox();
    data.activeSession = mode;
    saveMailbox(data);
}
export function getActiveSession() {
    return loadMailbox().activeSession;
}
export function updateCodingSessionInfo(info) {
    const data = loadMailbox();
    data.codingSession = { ...data.codingSession, ...info };
    saveMailbox(data);
}
/**
 * Reset the mailbox to its empty default state.
 *
 * Used by the startup engine-switch boundary: when the agent engine
 * changes between runs we collapse general + coding into a single
 * fresh general session, so any cross-session memos / in-progress
 * coding state would be stale and confusing if carried over.
 */
export function clearMailbox() {
    saveMailbox({ ...DEFAULT_MAILBOX, codingSession: { ...DEFAULT_MAILBOX.codingSession } });
}
//# sourceMappingURL=mailbox.js.map