import { OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { IEventBus, DomainEvent, DrizzleTransaction } from './event-bus.protocol.js';
import '../../types/drizzle.js';
import 'drizzle-orm/node-postgres';

/**
 * RedisEventBus — Redis Pub/Sub backend for the event bus.
 *
 * Publishes events to Redis channels and dispatches incoming messages to
 * registered in-process subscribers. Events are serialized as JSON strings.
 *
 * Channel naming:
 *   - Per-type channel:  events:{event.type}   (e.g. events:contact_created)
 *   - Catch-all channel: events:*
 *
 * Transactional semantics:
 *   The `tx` parameter (Drizzle transaction) is accepted to satisfy the
 *   IEventBus interface but has no effect — Redis Pub/Sub is not transactional.
 *   Events published with a `tx` argument are dispatched immediately without
 *   waiting for the surrounding transaction to commit. If you need
 *   at-least-once delivery tied to a database transaction, use DrizzleEventBus.
 *
 * Connection model:
 *   ioredis requires a dedicated connection for subscribers (a client in
 *   subscribe mode cannot issue regular commands). This backend creates two
 *   clients: one for publishing (`publisher`) and one for subscribing
 *   (`subscriber`). Both are connected on module init and disconnected on
 *   module destroy.
 *
 * Usage:
 *   EventsModule.forRoot({ backend: 'redis', redisUrl: 'redis://localhost:6379' })
 *
 * Requires `ioredis` — install it separately if you use this backend:
 *   npm install ioredis   /   bun add ioredis
 */

declare class RedisEventBus implements IEventBus, OnModuleInit, OnModuleDestroy {
    private readonly redisUrl;
    private readonly logger;
    private publisher;
    private subscriber;
    private connected;
    /**
     * In-process subscriber registry. Handlers registered here are called when
     * a message arrives on the subscriber client — keeping fan-out within the
     * same process without an extra round-trip through Redis.
     */
    private readonly handlers;
    /**
     * Track which event types have active Redis subscriptions.
     * Used to avoid subscribing multiple times to the same type channel.
     */
    private readonly subscribedTypes;
    constructor(redisUrl: string);
    onModuleInit(): Promise<void>;
    onModuleDestroy(): Promise<void>;
    /**
     * Publish a single event.
     *
     * `tx` is accepted but ignored — see module-level JSDoc for details.
     */
    publish(event: DomainEvent, tx?: DrizzleTransaction): Promise<void>;
    /**
     * Publish multiple events using a pipeline so all PUBLISH commands are sent
     * in a single round-trip.
     *
     * `tx` is accepted but ignored — see module-level JSDoc for details.
     */
    publishMany(events: DomainEvent[], tx?: DrizzleTransaction): Promise<void>;
    /**
     * Register a handler for a specific event type.
     * Returns an unsubscribe function — call it to remove the handler.
     *
     * On first handler for a type, subscribes to the per-type Redis channel.
     * On removal of the last handler for a type, unsubscribes from the channel.
     */
    /**
     * Lookup by id is unsupported on the Redis Pub/Sub backend — Pub/Sub
     * does not retain history. Always returns `null`. Logs a warning the
     * first time it's called so a misconfiguration surfaces visibly. Using
     * the bridge with the Redis backend is unsupported (the bridge requires
     * a durable event store).
     */
    private warnedFindById;
    findById(_eventId: string): Promise<DomainEvent | null>;
    subscribe<T extends DomainEvent = DomainEvent>(eventType: string, handler: (event: T) => Promise<void>): () => void;
    private assertConnected;
    private serialize;
    private deserialize;
    private handleMessage;
    private dispatch;
    /**
     * Subscribe to a per-type Redis channel.
     * Called lazily when the first handler is registered for a type.
     */
    private subscribeToType;
    /**
     * Unsubscribe from a per-type Redis channel.
     * Called when the last handler for a type is removed.
     */
    private unsubscribeFromType;
}

export { RedisEventBus };
