"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.postProcessExecution = postProcessExecution;
/**
 * Post-process execution events to improve timeline visualization:
 *
 * 1. Fire-and-forget child starts (`startChild`): set duration_ms = 0
 *    so they render as a narrow completed band instead of pending.
 *
 * 2. Completed signals (`waitFor` that received a signal): split into
 *    signal_wait_started + workflow_execution_signaled pair so the
 *    timeline can show the full wait duration as a band.
 *
 * 3. Running workflows: inject a pending signal_wait_started event
 *    after any fire-and-forget start that lacks a matching signal,
 *    so the timeline shows a growing orange "pending" band.
 */
function postProcessExecution(execution) {
    const events = execution.events.map((e) => ({
        ...e,
        attributes: { ...e.attributes },
    }));
    const isRunning = !events.some((e) => e.event_type === 'workflow_execution_completed' ||
        e.event_type === 'workflow_execution_failed');
    let nextId = events.length > 0 ? Math.max(...events.map((e) => e.event_id)) + 1 : 1;
    const toAdd = [];
    // Enrich ltSignalParent activities with the workflow result as their payload.
    // The activity returns void, but it sends execution.result to the parent --
    // surfacing this makes the signal content visible in the UI.
    let enriched = false;
    if (execution.result) {
        for (const evt of events) {
            const attrs = evt.attributes;
            if (evt.event_type === 'activity_task_completed' &&
                attrs.activity_type === 'ltSignalParent' &&
                (attrs.result === undefined || attrs.result === null)) {
                attrs.result = execution.result;
                enriched = true;
            }
        }
    }
    // Existing signal completions and wait-start events (keyed by timeline_key)
    const signalKeys = new Set(events
        .filter((e) => e.event_type === 'workflow_execution_signaled')
        .map((e) => e.attributes.timeline_key)
        .filter(Boolean));
    const existingWaitStarts = new Set(events
        .filter((e) => e.event_type === 'signal_wait_started')
        .map((e) => e.attributes.timeline_key)
        .filter(Boolean));
    for (const evt of events) {
        const attrs = evt.attributes;
        // 1. Fire-and-forget starts: completed instantly
        if (evt.event_type === 'child_workflow_execution_started' &&
            attrs.awaited === false &&
            evt.duration_ms === null) {
            evt.duration_ms = 0;
        }
        // 2. Completed signals: inject signal_wait_started before completion
        if (evt.event_type === 'workflow_execution_signaled' &&
            evt.duration_ms != null &&
            evt.duration_ms > 0 &&
            attrs.timeline_key &&
            !existingWaitStarts.has(attrs.timeline_key)) {
            const waitStartTime = new Date(new Date(evt.event_time).getTime() - evt.duration_ms).toISOString();
            toAdd.push({
                event_id: nextId++,
                event_type: 'signal_wait_started',
                category: 'signal',
                event_time: waitStartTime,
                duration_ms: null,
                is_system: false,
                attributes: {
                    kind: 'signal_wait_started',
                    signal_name: attrs.signal_name,
                    timeline_key: attrs.timeline_key,
                    execution_index: attrs.execution_index,
                },
            });
        }
    }
    // 3. Running workflows: inject pending waits after unmatched fire-and-forget starts
    if (isRunning) {
        for (const evt of events) {
            const attrs = evt.attributes;
            if (evt.event_type === 'child_workflow_execution_started' &&
                attrs.awaited === false) {
                const startIndex = attrs.execution_index;
                const childId = attrs.child_workflow_id;
                const waitIndex = startIndex + 1;
                const waitKey = `-wait-${waitIndex}-`;
                if (!signalKeys.has(waitKey) && !existingWaitStarts.has(waitKey)) {
                    toAdd.push({
                        event_id: nextId++,
                        event_type: 'signal_wait_started',
                        category: 'signal',
                        event_time: evt.event_time,
                        duration_ms: null,
                        is_system: false,
                        attributes: {
                            kind: 'signal_wait_started',
                            signal_name: `lt-result-${childId}`,
                            timeline_key: waitKey,
                            execution_index: waitIndex,
                        },
                    });
                }
            }
        }
    }
    if (toAdd.length > 0) {
        events.push(...toAdd);
    }
    // Sort by execution_index first — it reflects the true workflow sequence.
    // Timestamps are unreliable for ordering (e.g. signal_wait_started gets
    // the workflow start time). Fall back to timestamp only when index is absent.
    events.sort((a, b) => {
        const idxA = a.attributes.execution_index ?? -1;
        const idxB = b.attributes.execution_index ?? -1;
        if (idxA !== -1 && idxB !== -1 && idxA !== idxB)
            return idxA - idxB;
        if (idxA !== -1 && idxB === -1)
            return 1; // indexed after non-indexed (workflow_started)
        if (idxA === -1 && idxB !== -1)
            return -1;
        // Same index (scheduled/completed pairs) — sort by timestamp
        const cmp = a.event_time.localeCompare(b.event_time);
        return cmp !== 0 ? cmp : a.event_id - b.event_id;
    });
    for (let i = 0; i < events.length; i++) {
        events[i].event_id = i + 1;
    }
    return {
        ...execution,
        events,
        summary: {
            ...execution.summary,
            total_events: events.length,
        },
    };
}
