import { structuralShare } from "./structural-share";
const IDLE_STATE = { stage: "idle" };
/**
 * Framework-agnostic store that holds the active execution snapshot
 * with structural sharing. Implements the contract required by
 * React's `useSyncExternalStore`.
 *
 * - `ingestSnapshot` applies structural sharing so unchanged nested
 *   entities keep their previous reference.
 * - Listeners are notified only when state actually changes.
 * - `getExecution` and `getStreamState` return stable references
 *   suitable as `useSyncExternalStore` snapshot selectors.
 */
export class ConversationStore {
    _execution = null;
    _streamState = IDLE_STATE;
    _listeners = new Set();
    // -- Ingestion -----------------------------------------------------------
    /**
     * Ingest a new execution snapshot. Applies structural sharing
     * against the previous snapshot and notifies listeners only if
     * the resulting reference changed.
     */
    ingestSnapshot(snapshot) {
        const shared = structuralShare(this._execution, snapshot);
        if (shared === this._execution)
            return;
        this._execution = shared;
        this._notify();
    }
    /**
     * Transition the stream lifecycle state. Notifies listeners only
     * when the stage or executionId actually changes.
     */
    setStreamState(state) {
        if (streamStateEqual(this._streamState, state))
            return;
        this._streamState = state;
        this._notify();
    }
    /**
     * Reset to initial state. Used when the session identity changes
     * or the hook unmounts.
     */
    reset() {
        const wasIdle = this._execution === null && this._streamState.stage === "idle";
        this._execution = null;
        this._streamState = IDLE_STATE;
        if (!wasIdle)
            this._notify();
    }
    // -- useSyncExternalStore contract ---------------------------------------
    /**
     * Subscribe a listener that is called whenever any store state
     * changes. Returns an unsubscribe function.
     */
    subscribe = (listener) => {
        this._listeners.add(listener);
        return () => {
            this._listeners.delete(listener);
        };
    };
    /** Stable snapshot selector for the current execution. */
    getExecution = () => {
        return this._execution;
    };
    /** Stable snapshot selector for the stream lifecycle state. */
    getStreamState = () => {
        return this._streamState;
    };
    // -- Internal ------------------------------------------------------------
    _notify() {
        for (const listener of this._listeners) {
            listener();
        }
    }
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function streamStateEqual(a, b) {
    if (a.stage !== b.stage)
        return false;
    if (a.stage === "idle")
        return true;
    if (a.stage === "error" &&
        b.stage === "error" &&
        a.executionId === b.executionId &&
        a.error === b.error)
        return true;
    if ("executionId" in a && "executionId" in b)
        return a.executionId === b.executionId;
    return false;
}
//# sourceMappingURL=conversation-store.js.map