import type { BaseMessage, ISrpcServerOptions, SrpcDisconnectCause, SrpcMeta, SrpcStream } from '../../srpc/types';
import type { MeshBroadcastMap, MeshBroadcastOptions, MeshServiceOptions } from '../mesh';
import { SrpcServer } from '../../srpc/SrpcServer';
import { MeshClientRegistry } from './mesh-client-registry';
import { type MeshClientRegistryBackend, type RegisteredClient } from './types';
export interface MeshSrpcServerOptions<TMeta, TRegistryMeta = TMeta> {
    meshKey: string;
    meshOptions?: MeshServiceOptions;
    registryBackend?: MeshClientRegistryBackend<TRegistryMeta>;
    extractMetadata?: (stream: SrpcStream<TMeta>) => TRegistryMeta;
}
export declare class MeshSrpcServer<TMeta extends SrpcMeta = SrpcMeta, TClientOutput extends BaseMessage = BaseMessage, TServerOutput extends BaseMessage = BaseMessage, TRegistryMeta = TMeta, TBroadcasts extends MeshBroadcastMap = {}> extends SrpcServer<TMeta, TClientOutput, TServerOutput> {
    private meshClientService;
    private meshLogger;
    private extractMetadataFn?;
    private connectedCallbacks;
    private disconnectedCallbacks;
    private orphanedCallbacks;
    private clientMetadata;
    private lifecycleConnectedStreams;
    private clientRegistryChains;
    private clientCallbackChains;
    private pendingSyncs;
    constructor(options: ISrpcServerOptions<TClientOutput, TServerOutput> & MeshSrpcServerOptions<TMeta, TRegistryMeta>);
    /**
     * Defers stream activation until mesh reservation succeeds.
     * Installs meta proxy and reserves the client atomically in Redis
     * (respecting allowSupersede for v2), all serialized in the per-client
     * registry chain. Reserved clients remain hidden from lookup/invoke until
     * onStreamActivated promotes them to active.
     *
     * If registration returns a conflict, cleanupStream is called
     * (which fires onStreamDisconnected and drains the queue) so
     * no connection handlers or RPCs ever run on the rejected stream.
     */
    protected postEstablishCheck(stream: SrpcStream<TMeta>): Promise<boolean>;
    private extractMeta;
    private static readonly PROXIED;
    /**
     * Install a Proxy on stream.meta that schedules a microtask-debounced
     * sync to Redis whenever any property is mutated.
     *
     * This means handler code, connection handlers, and external code
     * (e.g. FreeSwitch controller) can all mutate stream.meta directly
     * and the mesh registry stays in sync - no manual sync calls needed.
     *
     * **Limitation:** Only top-level property mutations are tracked.
     * Nested mutations (e.g. `stream.meta.user.name = 'Bob'`) do NOT
     * trigger a sync. For nested metadata, either reassign the top-level
     * property (`stream.meta.user = { ...stream.meta.user, name: 'Bob' }`)
     * or call `updateClientMetadata()` explicitly.
     */
    private installMetaProxy;
    /**
     * Schedule a microtask-debounced sync for a client.
     * Multiple synchronous mutations are batched into a single sync.
     */
    private scheduleSyncStreamMeta;
    protected onStreamConnected(stream: SrpcStream<TMeta>): Promise<void>;
    protected onStreamActivated(stream: SrpcStream<TMeta>): Promise<void>;
    protected onStreamDisconnected(stream: SrpcStream<TMeta>, cause: SrpcDisconnectCause): void;
    /**
     * Sync the current stream.meta to the mesh registry.
     * Called automatically by the meta proxy's microtask debounce.
     * Routed through enqueueClientRegistry so updates are serialized
     * after initial registration (prevents lost updates if registration
     * hasn't completed yet).
     */
    private syncStreamMeta;
    private enqueueClientRegistry;
    private enqueueClientCallback;
    get meshInstanceId(): number;
    get clientRegistry(): MeshClientRegistry<TRegistryMeta>;
    /**
     * Update metadata for a client, regardless of which node owns it.
     * Routes through the mesh to the owning node so that stream.meta
     * reflects the change immediately and the proxy auto-syncs to Redis.
     * For local streams, you can also mutate stream.meta directly.
     */
    updateClientMetadata(clientId: string, metadata: TRegistryMeta): Promise<boolean>;
    onClientConnected(handler: (clientId: string, metadata: TRegistryMeta) => void | Promise<void>): void;
    onClientDisconnected(handler: (clientId: string, metadata: TRegistryMeta) => void | Promise<void>): void;
    onNodeClientsOrphaned(handler: (nodeId: number, clients: RegisteredClient<TRegistryMeta>[]) => void | Promise<void>): void;
    registerBroadcastHandler<K extends keyof TBroadcasts & string>(type: K, handler: (data: TBroadcasts[K], senderInstanceId: number) => void | Promise<void>): void;
    broadcast<K extends keyof TBroadcasts & string>(type: K, data: TBroadcasts[K], options?: MeshBroadcastOptions): Promise<void>;
    /**
     * Invoke a client method across any node in the mesh.
     * Overloaded: when called with a stream, delegates to SrpcServer.invoke.
     * When called with a clientId string, routes through the mesh.
     */
    invoke(streamOrClientId: SrpcStream<TMeta> | string, prefix: any, data: any, timeoutMs?: number): Promise<any>;
    meshStart(): Promise<void>;
    meshStop(): Promise<void>;
}
//# sourceMappingURL=mesh-srpc-server.d.ts.map