/**
 * Middleware Pipeline
 *
 * Orchestrates middleware execution in priority order.
 * Inspired by Mistral Vibe's elegant middleware architecture.
 */
import { MiddlewareAction, continueResult, } from './types.js';
// ============================================================================
// Middleware Pipeline
// ============================================================================
/**
 * Orchestrates middleware execution in priority order
 */
export class MiddlewarePipeline {
    middlewares = [];
    eventHandlers = [];
    enabled = true;
    constructor(middlewares = []) {
        middlewares.forEach(m => this.add(m));
    }
    /**
     * Add middleware to the pipeline (maintains priority order)
     */
    add(middleware) {
        this.middlewares.push(middleware);
        this.middlewares.sort((a, b) => a.priority - b.priority);
        return this;
    }
    /**
     * Remove middleware by name
     */
    remove(name) {
        const index = this.middlewares.findIndex(m => m.name === name);
        if (index >= 0) {
            this.middlewares.splice(index, 1);
            return true;
        }
        return false;
    }
    /**
     * Get middleware by name
     */
    get(name) {
        return this.middlewares.find(m => m.name === name);
    }
    /**
     * Check if middleware exists
     */
    has(name) {
        return this.middlewares.some(m => m.name === name);
    }
    /**
     * Get all middleware names in priority order
     */
    getNames() {
        return this.middlewares.map(m => m.name);
    }
    /**
     * Enable/disable the entire pipeline
     */
    setEnabled(enabled) {
        this.enabled = enabled;
    }
    /**
     * Check if pipeline is enabled
     */
    isEnabled() {
        return this.enabled;
    }
    /**
     * Subscribe to pipeline events
     */
    on(handler) {
        this.eventHandlers.push(handler);
        return () => {
            const index = this.eventHandlers.indexOf(handler);
            if (index >= 0) {
                this.eventHandlers.splice(index, 1);
            }
        };
    }
    /**
     * Emit an event to all handlers
     */
    emit(event) {
        const fullEvent = { ...event, timestamp: new Date() };
        this.eventHandlers.forEach(handler => {
            try {
                handler(fullEvent);
            }
            catch {
                // Ignore handler errors
            }
        });
    }
    /**
     * Run beforeTurn on all middlewares
     * Stops at first non-continue result
     */
    async runBefore(context) {
        if (!this.enabled) {
            return continueResult();
        }
        for (const middleware of this.middlewares) {
            try {
                this.emit({
                    type: 'middleware:before',
                    middlewareName: middleware.name,
                });
                const result = await middleware.beforeTurn(context);
                if (result.action !== MiddlewareAction.CONTINUE) {
                    this.emit({
                        type: 'middleware:action',
                        middlewareName: middleware.name,
                        action: result.action,
                        message: result.message,
                    });
                    return result;
                }
            }
            catch (error) {
                this.emit({
                    type: 'middleware:error',
                    middlewareName: middleware.name,
                    error: error instanceof Error ? error : new Error(String(error)),
                });
                // Continue on error - don't let one middleware break the pipeline
            }
        }
        return continueResult();
    }
    /**
     * Run afterTurn on all middlewares
     * Stops at first non-continue result
     */
    async runAfter(context) {
        if (!this.enabled) {
            return continueResult();
        }
        for (const middleware of this.middlewares) {
            try {
                this.emit({
                    type: 'middleware:after',
                    middlewareName: middleware.name,
                });
                const result = await middleware.afterTurn(context);
                if (result.action !== MiddlewareAction.CONTINUE) {
                    this.emit({
                        type: 'middleware:action',
                        middlewareName: middleware.name,
                        action: result.action,
                        message: result.message,
                    });
                    return result;
                }
            }
            catch (error) {
                this.emit({
                    type: 'middleware:error',
                    middlewareName: middleware.name,
                    error: error instanceof Error ? error : new Error(String(error)),
                });
                // Continue on error
            }
        }
        return continueResult();
    }
    /**
     * Reset all middlewares
     */
    reset() {
        this.middlewares.forEach(m => m.reset());
        this.emit({ type: 'pipeline:reset' });
    }
    /**
     * Clear all middlewares
     */
    clear() {
        this.middlewares = [];
    }
    /**
     * Get middleware count
     */
    get count() {
        return this.middlewares.length;
    }
}
// ============================================================================
// Pipeline Builder
// ============================================================================
/**
 * Fluent builder for creating middleware pipelines
 */
export class PipelineBuilder {
    middlewares = [];
    /**
     * Add middleware to the pipeline
     */
    use(middleware) {
        this.middlewares.push(middleware);
        return this;
    }
    /**
     * Add multiple middlewares
     */
    useAll(middlewares) {
        middlewares.forEach(m => this.use(m));
        return this;
    }
    /**
     * Conditionally add middleware
     */
    useIf(condition, middleware) {
        if (condition) {
            this.use(middleware);
        }
        return this;
    }
    /**
     * Build the pipeline
     */
    build() {
        return new MiddlewarePipeline(this.middlewares);
    }
}
/**
 * Create a new pipeline builder
 */
export function createPipeline() {
    return new PipelineBuilder();
}
//# sourceMappingURL=pipeline.js.map