/**
 * ProjectEventBus - Event-Driven Architecture for Project Sync
 *
 * Implements an EventEmitter-based bus for project-related events.
 * Supports async handler execution with error isolation.
 */
import { EventEmitter } from 'events';
import { consoleLogger } from '../../utils/logger.js';
export class ProjectEventBus {
    constructor(options = {}) {
        // Map to track original handlers -> wrapped handlers for proper off() support
        this.handlerMap = new WeakMap();
        this.emitter = new EventEmitter();
        this.logger = options.logger ?? consoleLogger;
        // Increase max listeners to support many adapters
        this.emitter.setMaxListeners(50);
    }
    /**
     * Subscribe to a specific event type
     */
    on(eventType, handler) {
        // Create wrapped handler with error isolation
        const wrappedHandler = async (event) => {
            try {
                await handler(event);
            }
            catch (error) {
                // Error isolation - log but don't propagate
                this.logger.error(`Event handler error for ${eventType}: ${error}`);
            }
        };
        // Store mapping for later removal with off()
        this.handlerMap.set(handler, wrappedHandler);
        this.emitter.on(eventType, wrappedHandler);
        this.logger.debug(`Registered handler for event: ${eventType}`);
    }
    /**
     * Subscribe to an event type (one-time only)
     */
    once(eventType, handler) {
        this.emitter.once(eventType, async (event) => {
            try {
                await handler(event);
            }
            catch (error) {
                this.logger.error(`One-time event handler error for ${eventType}: ${error}`);
            }
        });
    }
    /**
     * Unsubscribe from an event type
     */
    off(eventType, handler) {
        // Get the wrapped handler that was actually registered
        const wrappedHandler = this.handlerMap.get(handler);
        if (wrappedHandler) {
            this.emitter.off(eventType, wrappedHandler);
            this.handlerMap.delete(handler);
            this.logger.debug(`Unregistered handler for event: ${eventType}`);
        }
        else {
            // Fallback: try to remove original handler (in case it was registered directly)
            this.emitter.off(eventType, handler);
            this.logger.debug(`Attempted to unregister handler for event: ${eventType} (no wrapper found)`);
        }
    }
    /**
     * Emit an event
     */
    emit(event) {
        this.logger.debug(`Emitting event: ${event.type}`);
        this.emitter.emit(event.type, event);
    }
    /**
     * Emit and wait for all handlers to complete
     * Useful for testing or synchronous workflows
     */
    async emitAndWait(event) {
        const handlers = this.emitter.listeners(event.type);
        this.logger.debug(`Emitting event (sync): ${event.type} to ${handlers.length} handlers`);
        const results = await Promise.allSettled(handlers.map((handler) => {
            try {
                const result = handler(event);
                return result instanceof Promise ? result : Promise.resolve(result);
            }
            catch (error) {
                return Promise.reject(error);
            }
        }));
        // Log any errors
        for (const result of results) {
            if (result.status === 'rejected') {
                this.logger.error(`Handler failed for ${event.type}: ${result.reason}`);
            }
        }
    }
    /**
     * Get the number of listeners for an event type
     */
    listenerCount(eventType) {
        return this.emitter.listenerCount(eventType);
    }
    /**
     * Remove all listeners for an event type (or all events)
     */
    removeAllListeners(eventType) {
        if (eventType) {
            this.emitter.removeAllListeners(eventType);
            this.logger.debug(`Removed all listeners for: ${eventType}`);
        }
        else {
            this.emitter.removeAllListeners();
            this.logger.debug('Removed all event listeners');
        }
    }
    // ============================================
    // Typed helper methods for common events
    // ============================================
    /**
     * Subscribe to ProjectCreated events
     */
    onProjectCreated(handler) {
        this.on('ProjectCreated', handler);
    }
    /**
     * Subscribe to ProjectUpdated events
     */
    onProjectUpdated(handler) {
        this.on('ProjectUpdated', handler);
    }
    /**
     * Subscribe to ProjectDeleted events
     */
    onProjectDeleted(handler) {
        this.on('ProjectDeleted', handler);
    }
    /**
     * Subscribe to ProjectSyncRequested events
     */
    onProjectSyncRequested(handler) {
        this.on('ProjectSyncRequested', handler);
    }
    /**
     * Subscribe to ExternalProjectDiscovered events
     */
    onExternalProjectDiscovered(handler) {
        this.on('ExternalProjectDiscovered', handler);
    }
}
//# sourceMappingURL=project-event-bus.js.map