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.
 */
/**
 * OtelSqlView – Ad-hoc DataFusion SQL query panel for the OTEL service.
 *
 * Features:
 *  - Preset query dropdown (spans, logs, metrics)
 *  - Query history persisted to cookie `otel_sql_history` (max 10 entries)
 *  - ⌘/Ctrl + Enter to run
 *
 * Available tables: `spans`, `metrics`, `logs`.
 */
import { useState, useCallback } from 'react';
import { ActionList, ActionMenu, Box, Button, Text, Textarea, Spinner, } from '@primer/react';
import { HistoryIcon, TableIcon, XCircleIcon, DownloadIcon, } from '@primer/octicons-react';
import { useOtelQuery } from '../hooks/index.js';
// ── Cookie helpers ────────────────────────────────────────────────
const HISTORY_COOKIE = 'otel_sql_history';
const HISTORY_MAX = 10;
function readHistory() {
    try {
        const m = document.cookie.match(/(?:^|;\s*)otel_sql_history=([^;]+)/);
        if (m)
            return JSON.parse(decodeURIComponent(m[1]));
    }
    catch {
        // ignore
    }
    return [];
}
function writeHistory(entries) {
    try {
        document.cookie = `${HISTORY_COOKIE}=${encodeURIComponent(JSON.stringify(entries))};path=/;max-age=31536000`;
    }
    catch {
        // ignore
    }
}
function pushHistory(sql, prev) {
    const deduped = prev.filter(s => s !== sql);
    return [sql, ...deduped].slice(0, HISTORY_MAX);
}
const PRESETS = [
    {
        group: 'Spans',
        label: 'Recent spans',
        sql: 'SELECT trace_id, operation_name, service_name, start_time_unix_nano\nFROM spans\nORDER BY start_time_unix_nano DESC\nLIMIT 20',
    },
    {
        group: 'Spans',
        label: 'Error spans',
        sql: "SELECT trace_id, operation_name, service_name, status_code, status_message\nFROM spans\nWHERE status_code = 'ERROR'\nLIMIT 20",
    },
    {
        group: 'Spans',
        label: 'Span count by service',
        sql: 'SELECT service_name, COUNT(*) AS span_count\nFROM spans\nGROUP BY service_name\nORDER BY span_count DESC',
    },
    {
        group: 'Logs',
        label: 'Recent logs',
        sql: 'SELECT timestamp_unix_nano, severity_text, body, service_name\nFROM logs\nORDER BY timestamp_unix_nano DESC\nLIMIT 20',
    },
    {
        group: 'Logs',
        label: 'Error logs',
        sql: "SELECT timestamp_unix_nano, severity_text, body, service_name\nFROM logs\nWHERE severity_text IN ('ERROR', 'FATAL')\nLIMIT 20",
    },
    {
        group: 'Metrics',
        label: 'Recent metrics',
        sql: 'SELECT metric_name, value_double, metric_unit, service_name, timestamp_unix_nano\nFROM metrics\nORDER BY timestamp_unix_nano DESC\nLIMIT 20',
    },
    {
        group: 'Metrics',
        label: 'Distinct metric names',
        sql: 'SELECT DISTINCT metric_name, metric_unit\nFROM metrics\nORDER BY metric_name',
    },
];
const PRESET_GROUPS = Array.from(new Set(PRESETS.map(p => p.group)));
export const OtelSqlView = ({ token, baseUrl = '', }) => {
    const [sql, setSql] = useState(PRESETS[0].sql);
    const [history, setHistory] = useState(() => readHistory());
    const { rows, loading, error, execute, clear } = useOtelQuery({
        token,
        baseUrl,
    });
    const handleRun = useCallback(() => {
        const trimmed = sql.trim();
        if (!trimmed)
            return;
        const next = pushHistory(trimmed, history);
        setHistory(next);
        writeHistory(next);
        execute(trimmed);
    }, [sql, history, execute]);
    const handleKeyDown = (e) => {
        if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {
            e.preventDefault();
            handleRun();
        }
    };
    const columns = rows.length > 0 ? Object.keys(rows[0]) : [];
    return (_jsxs(Box, { sx: {
            display: 'flex',
            flexDirection: 'column',
            flex: 1,
            minHeight: 0,
            height: '100%',
            gap: 3,
            p: 4,
            bg: 'canvas.default',
            color: 'fg.default',
            overflow: 'auto',
        }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2, flexWrap: 'wrap' }, children: [_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Button, { size: "small", children: "Preset queries" }), _jsx(ActionMenu.Overlay, { width: "large", children: _jsx(ActionList, { children: PRESET_GROUPS.map(group => (_jsx(ActionList.Group, { title: group, children: PRESETS.filter(p => p.group === group).map(p => (_jsx(ActionList.Item, { onSelect: () => setSql(p.sql), children: p.label }, p.label))) }, group))) }) })] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["\u2318 Enter to run \u00B7 Tables:", ' ', _jsx(Box, { as: "code", sx: { fontFamily: 'mono', fontSize: 0 }, children: "spans" }), ', ', _jsx(Box, { as: "code", sx: { fontFamily: 'mono', fontSize: 0 }, children: "metrics" }), ', ', _jsx(Box, { as: "code", sx: { fontFamily: 'mono', fontSize: 0 }, children: "logs" })] })] }), _jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx(Textarea, { "aria-label": "SQL query", value: sql, onChange: e => setSql(e.target.value), onKeyDown: handleKeyDown, placeholder: "SELECT \u2026 FROM spans LIMIT 20", rows: 5, resize: "vertical", sx: { fontFamily: 'mono', fontSize: 1, width: '100%' } }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Button, { variant: "primary", onClick: handleRun, disabled: loading, size: "small", children: loading ? 'Running…' : 'Run' }), loading && _jsx(Spinner, { size: "small" })] })] }), error && (_jsx(Box, { sx: {
                    p: 3,
                    bg: 'danger.subtle',
                    borderRadius: 2,
                    border: '1px solid',
                    borderColor: 'danger.muted',
                }, children: _jsx(Text, { sx: { color: 'danger.fg', fontFamily: 'mono', fontSize: 1 }, children: error }) })), !error && rows.length > 0 && (_jsxs(Box, { children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1, mb: 1 }, children: [_jsx(TableIcon, { size: 14 }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold', color: 'fg.default' }, children: "Results" }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted', ml: 1 }, children: ["(", rows.length, " row", rows.length !== 1 ? 's' : '', ")"] }), _jsxs(Box, { as: "button", onClick: clear, title: "Clear results", sx: {
                                    ml: 'auto',
                                    display: 'flex',
                                    alignItems: 'center',
                                    gap: 1,
                                    px: 2,
                                    py: '2px',
                                    border: 'none',
                                    borderRadius: 2,
                                    bg: 'transparent',
                                    color: 'fg.muted',
                                    cursor: 'pointer',
                                    fontSize: 0,
                                    '&:hover': { color: 'danger.fg', bg: 'danger.subtle' },
                                }, children: [_jsx(XCircleIcon, { size: 12 }), _jsx(Text, { sx: { fontSize: 0 }, children: "Clear" })] }), _jsxs(Box, { as: "button", onClick: () => {
                                    const header = columns.join(',');
                                    const body = rows
                                        .map(row => columns
                                        .map(col => {
                                        const v = String(row[col] ?? '');
                                        return v.includes(',') ||
                                            v.includes('"') ||
                                            v.includes('\n')
                                            ? `"${v.replace(/"/g, '""')}"`
                                            : v;
                                    })
                                        .join(','))
                                        .join('\n');
                                    const blob = new Blob([header + '\n' + body], {
                                        type: 'text/csv',
                                    });
                                    const url = URL.createObjectURL(blob);
                                    const a = document.createElement('a');
                                    a.href = url;
                                    a.download = 'otel-query-result.csv';
                                    a.click();
                                    URL.revokeObjectURL(url);
                                }, title: "Download as CSV", sx: {
                                    display: 'flex',
                                    alignItems: 'center',
                                    gap: 1,
                                    px: 2,
                                    py: '2px',
                                    border: 'none',
                                    borderRadius: 2,
                                    bg: 'transparent',
                                    color: 'fg.muted',
                                    cursor: 'pointer',
                                    fontSize: 0,
                                    '&:hover': { color: 'accent.fg', bg: 'accent.subtle' },
                                }, children: [_jsx(DownloadIcon, { size: 12 }), _jsx(Text, { sx: { fontSize: 0 }, children: "CSV" })] })] }), _jsx(Box, { sx: {
                            flex: 1,
                            minHeight: 200,
                            overflow: 'auto',
                            border: '1px solid',
                            borderColor: 'border.default',
                            borderRadius: 2,
                        }, children: _jsxs(Box, { as: "table", sx: { width: '100%', borderCollapse: 'collapse' }, children: [_jsx(Box, { as: "thead", children: _jsx(Box, { as: "tr", sx: { bg: 'canvas.subtle' }, children: columns.map(col => (_jsx(Box, { as: "th", sx: {
                                                px: 3,
                                                py: 2,
                                                textAlign: 'left',
                                                fontWeight: 'bold',
                                                fontSize: 0,
                                                color: 'fg.muted',
                                                borderBottom: '1px solid',
                                                borderColor: 'border.default',
                                                whiteSpace: 'nowrap',
                                            }, children: col }, col))) }) }), _jsx(Box, { as: "tbody", children: rows.map((row, ri) => (_jsx(Box, { as: "tr", sx: {
                                            '&:hover': { bg: 'canvas.subtle' },
                                            '&:not(:last-child) td': {
                                                borderBottom: '1px solid',
                                                borderColor: 'border.muted',
                                            },
                                        }, children: columns.map(col => (_jsx(Box, { as: "td", sx: {
                                                px: 3,
                                                py: 2,
                                                fontSize: 0,
                                                fontFamily: 'mono',
                                                maxWidth: '300px',
                                                overflow: 'hidden',
                                                textOverflow: 'ellipsis',
                                                whiteSpace: 'nowrap',
                                            }, children: String(row[col] ?? '') }, col))) }, ri))) })] }) })] })), !error && !loading && rows.length === 0 && (_jsx(Box, { sx: {
                    flex: 1,
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    color: 'fg.muted',
                }, children: _jsx(Text, { sx: { fontSize: 1 }, children: "Run a query to see results." }) })), history.length > 0 && (_jsxs(Box, { children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1, mb: 1 }, children: [_jsx(HistoryIcon, { size: 12 }), _jsx(Text, { sx: { fontSize: 0, fontWeight: 'bold', color: 'fg.muted' }, children: "History" })] }), _jsx(Box, { sx: {
                            display: 'flex',
                            flexDirection: 'column',
                            border: '1px solid',
                            borderColor: 'border.default',
                            borderRadius: 2,
                            overflow: 'hidden',
                        }, children: history.map((entry, i) => (_jsxs(Box, { sx: {
                                display: 'flex',
                                alignItems: 'center',
                                gap: 2,
                                px: 3,
                                py: '6px',
                                cursor: 'pointer',
                                bg: i % 2 === 0 ? 'canvas.default' : 'canvas.subtle',
                                borderTop: i > 0 ? '1px solid' : 'none',
                                borderColor: 'border.muted',
                                '&:hover': { bg: 'accent.subtle' },
                            }, onClick: () => setSql(entry), children: [_jsx(Text, { sx: {
                                        fontFamily: 'mono',
                                        fontSize: 0,
                                        color: 'fg.default',
                                        flex: 1,
                                        overflow: 'hidden',
                                        textOverflow: 'ellipsis',
                                        whiteSpace: 'nowrap',
                                    }, children: entry.replace(/\s+/g, ' ') }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.subtle', flexShrink: 0 }, children: "restore \u2191" })] }, i))) })] }))] }));
};
