import { EventEmitter } from 'node:events';

/**
 * In-process EventEmitter for graph mutation events (issue #691 PR 5/5).
 *
 * The singleton is keyed by memoryDir so multiple orchestrator instances in
 * the same process get distinct event buses (CLAUDE.md rule 11: scope globals
 * per service).  The SSE handler in access-http.ts subscribes to the bus for
 * the resolved namespace and fans out to connected clients.
 *
 * Event types mirror the five mutations the graph layer can produce:
 *   node-added    — a memory file was referenced for the first time
 *   node-updated  — a memory file's metadata changed
 *   edge-added    — a new edge was appended
 *   edge-updated  — an existing edge's confidence/weight was modified
 *   edge-removed  — an edge was pruned (e.g. by decay maintenance)
 *
 * The `GraphEventBus` interface is intentionally narrow so nothing outside
 * this module needs to import Node.js EventEmitter directly.
 */

type GraphEventType = "node-added" | "node-updated" | "edge-added" | "edge-updated" | "edge-removed";
interface GraphEvent {
    type: GraphEventType;
    /** Memory dir that owns this event (absolute path). */
    memoryDir: string;
    /** ISO timestamp of the event. */
    ts: string;
    /** Payload depends on event type — always serialisable to JSON. */
    payload: Record<string, unknown>;
}
interface NodeAddedPayload {
    nodeId: string;
    kind: string;
    label: string;
    lastUpdated: string;
}
interface NodeUpdatedPayload {
    nodeId: string;
    kind: string;
    label: string;
    lastUpdated: string;
}
interface EdgeAddedPayload {
    source: string;
    target: string;
    kind: string;
    weight: number;
    label: string;
    confidence: number;
}
interface EdgeUpdatedPayload {
    source: string;
    target: string;
    kind: string;
    weight: number;
    confidence: number;
}
interface EdgeRemovedPayload {
    source: string;
    target: string;
    kind: string;
}
/**
 * Return (or lazily create) the event bus for the given memoryDir.
 * The same bus is shared by the write side (graph.ts → appendEdge hooks) and
 * the read side (EngramAccessHttpServer SSE handler).
 */
declare function getGraphEventBus(memoryDir: string): EventEmitter;
/**
 * Emit a single graph event onto the bus for memoryDir.
 * Fails open: any listener that throws is caught so one bad client can't
 * crash the extraction pipeline.
 */
declare function emitGraphEvent(memoryDir: string, type: GraphEventType, payload: Record<string, unknown>): void;
/**
 * Subscribe to graph events for a given memoryDir.
 * Returns an unsubscribe function.
 */
declare function subscribeGraphEvents(memoryDir: string, listener: (event: GraphEvent) => void): () => void;
/**
 * Remove all listeners and the bus entry for a memoryDir.
 * Useful for tests that spin up isolated memory dirs.
 */
declare function destroyGraphEventBus(memoryDir: string): void;

export { type EdgeAddedPayload, type EdgeRemovedPayload, type EdgeUpdatedPayload, type GraphEvent, type GraphEventType, type NodeAddedPayload, type NodeUpdatedPayload, destroyGraphEventBus, emitGraphEvent, getGraphEventBus, subscribeGraphEvents };
