import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/*
 * Copyright (c) 2023-2025 Datalayer, Inc.
 * Distributed under the terms of the Modified BSD License.
 */
/**
 * OtelTimeline – Horizontal waterfall timeline for trace spans.
 *
 * Each span renders as a coloured bar positioned relative to the trace's
 * overall time window. Uses Primer React components for consistent theming.
 *
 * @module otel/OtelTimeline
 */
import { useMemo } from 'react';
import { Box, Text } from '@primer/react';
import { toMs, formatDuration, serviceColor } from '../utils.js';
export const OtelTimeline = ({ spans, barHeight = 24, selectedSpanId, onSelectSpan, }) => {
    const { minTime, maxTime, sortedSpans } = useMemo(() => {
        if (spans.length === 0)
            return { minTime: 0, maxTime: 1, sortedSpans: [] };
        const sorted = [...spans].sort((a, b) => toMs(a.start_time) - toMs(b.start_time));
        let min = Infinity;
        let max = -Infinity;
        for (const s of sorted) {
            const start = toMs(s.start_time);
            const end = toMs(s.end_time);
            if (start < min)
                min = start;
            if (end > max)
                max = end;
        }
        return {
            minTime: min,
            maxTime: max || min + 1,
            sortedSpans: sorted,
        };
    }, [spans]);
    const totalDuration = maxTime - minTime || 1;
    if (sortedSpans.length === 0) {
        return (_jsx(Box, { sx: { p: 3, color: 'fg.muted', textAlign: 'center' }, children: _jsx(Text, { children: "No spans to display." }) }));
    }
    return (_jsxs(Box, { sx: { width: '100%', overflowX: 'auto', py: 1 }, children: [sortedSpans.map(span => {
                const startOffset = ((toMs(span.start_time) - minTime) / totalDuration) * 100;
                const width = Math.max(((span.duration_ms || toMs(span.end_time) - toMs(span.start_time)) /
                    totalDuration) *
                    100, 0.4);
                const color = serviceColor(span.service_name);
                const isSelected = selectedSpanId === span.span_id;
                const indent = (span.depth ?? 0) * 16;
                return (_jsxs(Box, { sx: {
                        display: 'flex',
                        alignItems: 'center',
                        height: barHeight,
                        mb: '2px',
                        cursor: 'pointer',
                        bg: isSelected ? 'accent.subtle' : 'canvas.default',
                        borderRadius: 1,
                        ':hover': {
                            bg: isSelected ? 'accent.subtle' : 'canvas.subtle',
                        },
                    }, onClick: () => onSelectSpan?.(span), title: `${span.service_name} / ${span.span_name} — ${formatDuration(span.duration_ms)}`, children: [_jsx(Text, { sx: {
                                width: 200,
                                minWidth: 200,
                                pl: `${indent}px`,
                                pr: 2,
                                overflow: 'hidden',
                                textOverflow: 'ellipsis',
                                whiteSpace: 'nowrap',
                                fontSize: 1,
                                fontFamily: 'mono',
                                color: 'fg.muted',
                            }, children: span.span_name }), _jsx(Box, { sx: { flex: 1, position: 'relative', height: '100%' }, children: _jsx(Box, { sx: {
                                    position: 'absolute',
                                    left: `${startOffset}%`,
                                    width: `${width}%`,
                                    height: barHeight - 6,
                                    top: '3px',
                                    bg: color,
                                    borderRadius: 1,
                                    opacity: isSelected ? 1 : 0.8,
                                    border: isSelected ? '2px solid' : 'none',
                                    borderColor: 'accent.emphasis',
                                } }) }), _jsx(Text, { sx: {
                                minWidth: 64,
                                textAlign: 'right',
                                pl: 1,
                                fontSize: 0,
                                fontFamily: 'mono',
                                color: 'fg.muted',
                            }, children: formatDuration(span.duration_ms) })] }, span.span_id));
            }), _jsxs(Box, { sx: {
                    borderTop: '1px solid',
                    borderColor: 'border.default',
                    mt: 2,
                    pt: 2,
                    display: 'flex',
                    justifyContent: 'space-between',
                    fontSize: 0,
                    color: 'fg.muted',
                }, children: [_jsxs(Text, { children: [sortedSpans.length, " span", sortedSpans.length !== 1 ? 's' : ''] }), _jsxs(Text, { sx: { fontFamily: 'mono' }, children: ["Total: ", formatDuration(totalDuration)] })] })] }));
};
