import { DEFAULT_COMPONENT_CONFIG, applyFilter, appendBounded, } from '../types.js';
import { summarizeError } from '../../../utils/error-display.js';
import { logger } from '../../../utils/logger.js';
/**
 * TasksPanel — diagnostic data provider for runtime task telemetry.
 *
 * Active tasks are tracked in a live map; terminal tasks are moved
 * to the history buffer for filtering and display.
 */
export class TasksPanel {
    _config;
    _eventBus;
    /** Active tasks keyed by taskId. */
    _active = new Map();
    /** Completed task history (oldest first). */
    _history = [];
    /** Registered change notification callbacks. */
    _subscribers = new Set();
    /** Unsubscribe function from the event bus. */
    _unsub = null;
    constructor(eventBus, config = DEFAULT_COMPONENT_CONFIG) {
        this._eventBus = eventBus;
        this._config = config;
        this._start();
    }
    _start() {
        const handler = (envelope) => {
            this._handleEnvelope(envelope);
        };
        this._unsub = this._eventBus.onDomain('tasks', handler);
    }
    _handleEnvelope(envelope) {
        const p = envelope.payload;
        if (!('type' in p))
            return;
        const type = p.type;
        const traceId = envelope.traceId ?? '';
        const sessionId = envelope.sessionId ?? '';
        switch (type) {
            case 'TASK_CREATED': {
                const evt = p;
                this._active.set(evt.taskId, {
                    taskId: evt.taskId,
                    agentId: evt.agentId,
                    description: evt.description,
                    priority: evt.priority,
                    state: 'created',
                    createdAt: envelope.ts,
                    traceId,
                    sessionId,
                });
                this._notify();
                break;
            }
            case 'TASK_STARTED': {
                const evt = p;
                const record = this._active.get(evt.taskId);
                if (record) {
                    record.state = 'running';
                    this._notify();
                }
                break;
            }
            case 'TASK_BLOCKED': {
                const evt = p;
                const record = this._active.get(evt.taskId);
                if (record) {
                    record.state = 'blocked';
                    record.blockReason = evt.reason;
                    this._notify();
                }
                break;
            }
            case 'TASK_PROGRESS': {
                const evt = p;
                const record = this._active.get(evt.taskId);
                if (record) {
                    record.state = 'progressing';
                    record.progress = evt.progress;
                    record.progressMessage = evt.message;
                    this._notify();
                }
                break;
            }
            case 'TASK_COMPLETED': {
                const evt = p;
                const record = this._active.get(evt.taskId);
                if (record) {
                    record.state = 'completed';
                    record.completedAt = envelope.ts;
                    record.durationMs = evt.durationMs;
                    this._finalize(record);
                }
                break;
            }
            case 'TASK_FAILED': {
                const evt = p;
                const record = this._active.get(evt.taskId);
                if (record) {
                    record.state = 'failed';
                    record.completedAt = envelope.ts;
                    record.durationMs = evt.durationMs;
                    record.error = evt.error;
                    this._finalize(record);
                }
                break;
            }
            case 'TASK_CANCELLED': {
                const evt = p;
                const record = this._active.get(evt.taskId);
                if (record) {
                    record.state = 'cancelled';
                    record.completedAt = envelope.ts;
                    record.error = evt.reason;
                    this._finalize(record);
                }
                break;
            }
            default:
                break;
        }
    }
    _finalize(record) {
        this._active.delete(record.taskId);
        const entry = {
            taskId: record.taskId,
            agentId: record.agentId,
            description: record.description,
            priority: record.priority,
            state: record.state,
            createdAt: record.createdAt,
            completedAt: record.completedAt,
            durationMs: record.durationMs,
            progress: record.progress,
            progressMessage: record.progressMessage,
            blockReason: record.blockReason,
            error: record.error,
            traceId: record.traceId,
            sessionId: record.sessionId,
        };
        appendBounded(this._history, entry, this._config.bufferLimit);
        this._notify();
    }
    /**
     * Return a filtered snapshot combining active tasks and completed history.
     * Ordered most-recent first.
     *
     * @param filter - Optional filter to restrict entries.
     */
    getSnapshot(filter) {
        const activeEntries = [];
        for (const record of this._active.values()) {
            activeEntries.push({
                taskId: record.taskId,
                agentId: record.agentId,
                description: record.description,
                priority: record.priority,
                state: record.state,
                createdAt: record.createdAt,
                completedAt: record.completedAt,
                durationMs: record.durationMs,
                progress: record.progress,
                progressMessage: record.progressMessage,
                blockReason: record.blockReason,
                error: record.error,
                traceId: record.traceId,
                sessionId: record.sessionId,
            });
        }
        const combined = [...this._history, ...activeEntries];
        return applyFilter(combined, filter, (e) => e.createdAt);
    }
    /**
     * Register a callback invoked whenever the data changes.
     * @returns An unsubscribe function.
     */
    subscribe(callback) {
        this._subscribers.add(callback);
        return () => this._subscribers.delete(callback);
    }
    /**
     * Release all event bus subscriptions and clear internal state.
     */
    dispose() {
        if (this._unsub) {
            this._unsub();
            this._unsub = null;
        }
        this._subscribers.clear();
    }
    _notify() {
        for (const cb of this._subscribers) {
            try {
                cb();
            }
            catch (error) {
                logger.warn('[TasksPanel] subscriber error', { error: summarizeError(error) });
            }
        }
    }
}
