import { recordHealthCascadeSpan } from '../spans/health.js';
import { attachAgentDomain, attachCompactionDomain, attachPermissionDomain, attachSessionDomain } from './domain-bridge-agent-session.js';
import { attachPluginDomain, attachMcpDomain } from './domain-bridge-plugin-mcp.js';
import {} from './domain-bridge-shared.js';
import { attachTaskDomain, attachTransportDomain } from './domain-bridge-transport-task.js';
import { summarizeError } from '../../../utils/error-display.js';
import { logger } from '../../../utils/logger.js';
/**
 * DomainBridge wires the RuntimeEventBus to the OTel span system.
 *
 * Usage:
 * ```ts
 * const bridge = new DomainBridge(tracer);
 * const detach = bridge.attach(bus);
 * // later:
 * detach();
 * ```
 */
export class DomainBridge {
    _tracer;
    /** Active spans per domain, keyed by entity ID. */
    _pluginSpans = new Map();
    _mcpSpans = new Map();
    _transportSpans = new Map();
    _taskSpans = new Map();
    _agentSpans = new Map();
    _permissionSpans = new Map();
    _sessionSpans = new Map();
    _compactionSpans = new Map();
    constructor(tracer) {
        this._tracer = tracer;
    }
    /**
     * Attach the bridge to the given event bus.
     *
     * Subscribes to all domain channels. Returns a cleanup function that
     * unsubscribes all listeners when called.
     *
     * @param bus - The RuntimeEventBus to subscribe to.
     * @returns A `detach` function that unsubscribes all domain listeners.
     */
    attach(bus) {
        const helpers = this._helpers();
        const unsubs = [
            attachPluginDomain({ bus, helpers }, this._pluginSpans),
            attachMcpDomain({ bus, helpers }, this._mcpSpans),
            attachTransportDomain({ bus, helpers }, this._transportSpans),
            attachTaskDomain({ bus, helpers }, this._taskSpans),
            attachAgentDomain({ bus, helpers }, this._agentSpans),
            attachPermissionDomain({ bus, helpers }, this._permissionSpans),
            attachSessionDomain({ bus, helpers }, this._sessionSpans),
            attachCompactionDomain({ bus, helpers }, this._compactionSpans),
        ];
        return () => {
            for (const unsub of unsubs) {
                unsub();
            }
        };
    }
    /**
     * Record a health cascade event as a point-in-time span.
     *
     * Called by the caller when CASCADE_APPLIED events are produced by the
     * CascadeEngine. The caller is responsible for providing the trace ID
     * from their current operational context.
     *
     * @param event - The CASCADE_APPLIED event.
     * @param traceId - Trace ID to use for correlation.
     */
    recordCascade(event, traceId) {
        this._safe(() => {
            recordHealthCascadeSpan(this._tracer, event, { traceId });
        });
    }
    _safe(action) {
        try {
            action();
        }
        catch (error) {
            logger.warn('Telemetry domain bridge action failed', {
                error: summarizeError(error),
            });
        }
    }
    _withSpan(map, key, action) {
        const span = map.get(key);
        if (span)
            action(span);
    }
    _closeSpan(map, key, action) {
        const span = map.get(key);
        if (!span)
            return;
        action(span);
        map.delete(key);
    }
    _helpers() {
        return {
            tracer: this._tracer,
            safe: (action) => this._safe(action),
            withSpan: (map, key, action) => this._withSpan(map, key, action),
            closeSpan: (map, key, action) => this._closeSpan(map, key, action),
        };
    }
}
