/**
 * Sheet Engine Pool — manages multiple headless workbooks via @mog-sdk/node.
 *
 * Each workbook is created through the SDK's createWorkbook() function.
 * Uses the full kernel so formulas, undo, and CRDT sync all work correctly.
 *
 * Workbooks are keyed by name (basename):
 * - loadWorkbook("/path/to/Budget.xlsx") → keyed as "Budget.xlsx"
 * - createWorkbook() → auto-named "Book1", "Book2", etc.
 *
 * The pool persists for the entire agent session. Workbook state (cells,
 * formulas, undo history) survives across sandbox executions — same model
 * as Excel staying open in COM mode.
 */
import { createWorkbook } from './sdk-types.js';
export class SheetEnginePool {
    workbooks = new Map();
    /** name → original file path (for loaded workbooks) */
    sourcePaths = new Map();
    nextBookNum = 1;
    /** The most recently created/loaded workbook name. */
    activeWorkbookName = null;
    // ── Pool lifecycle events ─────────────────────────────────────────────
    onAddedCallbacks = [];
    /** Subscribe to workbook-added events. Returns unsubscribe function. */
    onWorkbookAdded(cb) {
        this.onAddedCallbacks.push(cb);
        return () => {
            this.onAddedCallbacks = this.onAddedCallbacks.filter((c) => c !== cb);
        };
    }
    constructor() { }
    /** Create a pool. The SDK resolves its own platform-native dependency. */
    static async init() {
        return new SheetEnginePool();
    }
    // =========================================================================
    // Lifecycle
    // =========================================================================
    /** Create a blank workbook. Auto-named "Book1", "Book2", etc. Returns the name. */
    async createWorkbook(name) {
        const wbName = name ?? `Book${this.nextBookNum++}`;
        if (this.workbooks.has(wbName)) {
            this.activeWorkbookName = wbName;
            return wbName;
        }
        const wb = await createWorkbook();
        this.workbooks.set(wbName, wb);
        this.activeWorkbookName = wbName;
        for (const cb of this.onAddedCallbacks)
            cb(wbName, wb);
        return wbName;
    }
    /**
     * Open a workbook from XLSX bytes, keyed by name.
     * If a workbook with this name is already open, returns the existing one (idempotent).
     */
    async openWorkbook(name, xlsxBuffer) {
        if (this.workbooks.has(name)) {
            this.activeWorkbookName = name;
            return name;
        }
        const wb = await createWorkbook({
            source: { type: 'bytes', data: new Uint8Array(xlsxBuffer) }
        });
        this.workbooks.set(name, wb);
        this.activeWorkbookName = name;
        for (const cb of this.onAddedCallbacks)
            cb(name, wb);
        return name;
    }
    /** Register an externally-created workbook into the pool (e.g. from CRDT sync). */
    registerWorkbook(name, wb) {
        if (this.workbooks.has(name))
            return;
        this.workbooks.set(name, wb);
        this.activeWorkbookName = name;
        for (const cb of this.onAddedCallbacks)
            cb(name, wb);
    }
    /** Close a workbook and free resources. */
    async close(name) {
        const wb = this.workbooks.get(name);
        if (!wb)
            return;
        wb.dispose();
        this.workbooks.delete(name);
        this.sourcePaths.delete(name);
        if (this.activeWorkbookName === name) {
            const remaining = [...this.workbooks.keys()];
            this.activeWorkbookName = remaining.length > 0 ? remaining[remaining.length - 1] : null;
        }
    }
    /** Close all workbooks. */
    async closeAll() {
        const names = [...this.workbooks.keys()];
        await Promise.all(names.map((n) => this.close(n)));
        this.activeWorkbookName = null;
    }
    get size() {
        return this.workbooks.size;
    }
    /** List all open workbook names. */
    listWorkbooks() {
        return [...this.workbooks.keys()];
    }
    /** Check if a workbook is open. */
    has(name) {
        return this.workbooks.has(name);
    }
    // =========================================================================
    // Source path tracking
    // =========================================================================
    /** Record the original file path for a loaded workbook. */
    setSourcePath(name, path) {
        this.sourcePaths.set(name, path);
    }
    /** Get the original file path for a loaded workbook (undefined for created workbooks). */
    getSourcePath(name) {
        return this.sourcePaths.get(name);
    }
    // =========================================================================
    // Raw access
    // =========================================================================
    getWorkbook(name) {
        const wb = this.workbooks.get(name);
        if (!wb)
            throw new Error(`Workbook "${name}" not found. Open workbooks: ${this.listWorkbooks().join(', ') || '(none)'}`);
        return wb;
    }
}
//# sourceMappingURL=sheet-engine.js.map