import React, { useCallback, useEffect, useMemo, useRef, useState, } from "react";
import ModelAPI from "../../Utils/ModelAPI/ModelAPI";
import URL from "../../../Types/API/URL";
import HTTPErrorResponse from "../../../Types/API/HTTPErrorResponse";
import API from "../../Utils/API/API";
import { APP_API_URL } from "../../Config";
import PageLoader from "../Loader/PageLoader";
import ErrorMessage from "../ErrorMessage/ErrorMessage";
import Service from "../../../Models/DatabaseModels/Service";
import Host from "../../../Models/DatabaseModels/Host";
import DockerHost from "../../../Models/DatabaseModels/DockerHost";
import KubernetesCluster from "../../../Models/DatabaseModels/KubernetesCluster";
import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
import SortOrder from "../../../Types/BaseDatabase/SortOrder";
import LogsFilterCard from "./components/LogsFilterCard";
import LogsViewerToolbar from "./components/LogsViewerToolbar";
import LogsTable, { resolveLogIdentifier, } from "./components/LogsTable";
import LogsPagination from "./components/LogsPagination";
import LogDetailsPanel from "./components/LogDetailsPanel";
import LogsHistogram from "./components/LogsHistogram";
import LogsFacetSidebar from "./components/LogsFacetSidebar";
import ActiveFilterChips from "./components/ActiveFilterChips";
import { CORE_LOGS_TABLE_COLUMN_OPTIONS, DEFAULT_LOGS_TABLE_COLUMNS, getLogsAttributeColumnId, normalizeLogsTableColumns, } from "./types";
import LogsAnalyticsView from "./components/LogsAnalyticsView";
import { queryStringToFilter } from "../../../Types/Log/LogQueryToFilter";
import TimeRange from "../../../Types/Time/TimeRange";
import { exportLogs, LogExportFormat } from "../../Utils/LogExport";
import ProjectUtil from "../../Utils/Project";
import TelemetryServiceUtil from "../../Utils/TelemetryService";
import OneUptimeDate from "../../../Types/Date";
const DEFAULT_PAGE_SIZE = 100;
const PAGE_SIZE_OPTIONS = [100, 250, 500, 1000];
const severityWeight = {
    fatal: 6,
    error: 5,
    warn: 4,
    warning: 4,
    info: 3,
    notice: 3,
    debug: 2,
    trace: 1,
};
function getEmptyMessageWithTimeRange(timeRange) {
    if (!timeRange) {
        return "Adjust filters or check again later.";
    }
    if (timeRange.range === TimeRange.CUSTOM && timeRange.startAndEndDate) {
        const startDate = timeRange.startAndEndDate.startValue;
        const endDate = timeRange.startAndEndDate.endValue;
        const fmt = (d) => {
            return d.toLocaleString("en-US", {
                month: "short",
                day: "numeric",
                hour: "2-digit",
                minute: "2-digit",
            });
        };
        return `Time range: ${fmt(startDate)} – ${fmt(endDate)}. Try adjusting filters or expanding the time range.`;
    }
    const rangeLabel = timeRange.range.toLowerCase();
    return `Time range: ${rangeLabel}. Try adjusting filters or expanding the time range.`;
}
const getSeverityWeight = (severity) => {
    if (!severity) {
        return 0;
    }
    const normalized = severity.toString().toLowerCase();
    return severityWeight[normalized] || 0;
};
// Resolve a human-readable service name to its UUID using the serviceMap.
function resolveServiceNameToId(name, serviceMap) {
    const lowerName = name.toLowerCase();
    for (const [id, service] of Object.entries(serviceMap)) {
        if ((service === null || service === void 0 ? void 0 : service.name) && service.name.toLowerCase() === lowerName) {
            return id;
        }
    }
    return undefined;
}
const LogsViewer = (props) => {
    var _a, _b, _c, _d, _e, _f;
    const [filterData, setFilterData] = useState(props.filterData);
    const [searchQuery, setSearchQuery] = useState("");
    const [logAttributes, setLogAttributes] = useState([]);
    const [attributesLoaded, setAttributesLoaded] = useState(false);
    const [attributesLoading, setAttributesLoading] = useState(false);
    // Per-attribute value suggestions, populated lazily as the user types `@key:`.
    const [attributeValueSuggestions, setAttributeValueSuggestions] = useState({});
    const [attributeValuesLoading, setAttributeValuesLoading] = useState(false);
    const lastValueSuggestionKeyRef = useRef("");
    const [isPageLoading, setIsPageLoading] = useState(true);
    const [pageError, setPageError] = useState("");
    const [serviceMap, setServiceMap] = useState({});
    const [hostMap, setHostMap] = useState({});
    const [dockerHostMap, setDockerHostMap] = useState({});
    const [kubernetesClusterMap, setKubernetesClusterMap] = useState({});
    const [selectedLogId, setSelectedLogId] = useState(null);
    const [focusedRowIndex, setFocusedRowIndex] = useState(-1);
    const searchBarRef = useRef(null);
    const [internalPage, setInternalPage] = useState(1);
    const [internalPageSize, setInternalPageSize] = useState(DEFAULT_PAGE_SIZE);
    const [localSortField, setLocalSortField] = useState("time");
    const [localSortOrder, setLocalSortOrder] = useState(SortOrder.Descending);
    const [internalSelectedColumns, setInternalSelectedColumns] = useState(DEFAULT_LOGS_TABLE_COLUMNS);
    const [internalViewMode, setInternalViewMode] = useState("list");
    const [showKeyboardShortcuts, setShowKeyboardShortcuts] = useState(false);
    useEffect(() => {
        setFilterData(props.filterData);
    }, [props.filterData]);
    useEffect(() => {
        if (props.sortField) {
            setLocalSortField(props.sortField);
        }
    }, [props.sortField]);
    useEffect(() => {
        if (props.sortOrder) {
            setLocalSortOrder(props.sortOrder);
        }
    }, [props.sortOrder]);
    useEffect(() => {
        if (props.pageSize) {
            setInternalPageSize(props.pageSize);
        }
    }, [props.pageSize]);
    useEffect(() => {
        if (props.selectedColumns) {
            setInternalSelectedColumns(normalizeLogsTableColumns(props.selectedColumns));
        }
    }, [props.selectedColumns]);
    const currentPage = (_a = props.page) !== null && _a !== void 0 ? _a : internalPage;
    const pageSize = (_b = props.pageSize) !== null && _b !== void 0 ? _b : internalPageSize;
    const totalItems = (_c = props.totalCount) !== null && _c !== void 0 ? _c : props.logs.length;
    const totalPages = Math.max(1, Math.ceil(totalItems / Math.max(pageSize, 1)));
    const sortField = (_d = props.sortField) !== null && _d !== void 0 ? _d : localSortField;
    const sortOrder = (_e = props.sortOrder) !== null && _e !== void 0 ? _e : localSortOrder;
    const shouldClientSort = !props.onSortChange;
    const sortedLogs = useMemo(() => {
        if (!shouldClientSort) {
            return props.logs;
        }
        const cloned = [...props.logs];
        cloned.sort((a, b) => {
            var _a, _b;
            if (sortField === "time") {
                const aTime = Number(a.timeUnixNano) ||
                    (a.time ? OneUptimeDate.fromString(a.time).getTime() : 0);
                const bTime = Number(b.timeUnixNano) ||
                    (b.time ? OneUptimeDate.fromString(b.time).getTime() : 0);
                if (aTime === bTime) {
                    return 0;
                }
                return sortOrder === SortOrder.Descending
                    ? bTime - aTime
                    : aTime - bTime;
            }
            const aSeverity = getSeverityWeight((_a = a.severityText) === null || _a === void 0 ? void 0 : _a.toString());
            const bSeverity = getSeverityWeight((_b = b.severityText) === null || _b === void 0 ? void 0 : _b.toString());
            if (aSeverity === bSeverity) {
                return 0;
            }
            return sortOrder === SortOrder.Descending
                ? bSeverity - aSeverity
                : aSeverity - bSeverity;
        });
        return cloned;
    }, [props.logs, shouldClientSort, sortField, sortOrder]);
    const shouldClientPaginate = props.totalCount === undefined;
    const paginatedLogs = useMemo(() => {
        if (!shouldClientPaginate) {
            return sortedLogs;
        }
        if (sortedLogs.length === 0) {
            return [];
        }
        const safePage = Math.min(Math.max(currentPage, 1), totalPages);
        const startIndex = (safePage - 1) * pageSize;
        return sortedLogs.slice(startIndex, startIndex + pageSize);
    }, [sortedLogs, shouldClientPaginate, currentPage, totalPages, pageSize]);
    const displayedLogs = shouldClientPaginate
        ? paginatedLogs
        : sortedLogs;
    useEffect(() => {
        if (!shouldClientPaginate || props.page !== undefined) {
            return;
        }
        const safePage = Math.min(Math.max(internalPage, 1), totalPages);
        if (safePage !== internalPage) {
            setInternalPage(safePage);
        }
    }, [shouldClientPaginate, props.page, internalPage, totalPages]);
    useEffect(() => {
        if (!selectedLogId) {
            return;
        }
        const stillExists = displayedLogs.some((log, index) => {
            return resolveLogIdentifier(log, index) === selectedLogId;
        });
        if (!stillExists) {
            setSelectedLogId(null);
        }
    }, [displayedLogs, selectedLogId]);
    const loadServices = useCallback(async () => {
        try {
            setIsPageLoading(true);
            setPageError("");
            const [telemetryServices, hosts, dockerHosts, kubernetesClusters] = await Promise.all([
                ModelAPI.getList({
                    modelType: Service,
                    query: {},
                    select: {
                        name: true,
                        serviceColor: true,
                    },
                    limit: LIMIT_PER_PROJECT,
                    skip: 0,
                    sort: {
                        name: SortOrder.Ascending,
                    },
                }),
                ModelAPI.getList({
                    modelType: Host,
                    query: {},
                    select: {
                        name: true,
                        hostIdentifier: true,
                    },
                    limit: LIMIT_PER_PROJECT,
                    skip: 0,
                    sort: {
                        name: SortOrder.Ascending,
                    },
                }),
                ModelAPI.getList({
                    modelType: DockerHost,
                    query: {},
                    select: {
                        name: true,
                        hostIdentifier: true,
                    },
                    limit: LIMIT_PER_PROJECT,
                    skip: 0,
                    sort: {
                        name: SortOrder.Ascending,
                    },
                }),
                ModelAPI.getList({
                    modelType: KubernetesCluster,
                    query: {},
                    select: {
                        name: true,
                        clusterIdentifier: true,
                    },
                    limit: LIMIT_PER_PROJECT,
                    skip: 0,
                    sort: {
                        name: SortOrder.Ascending,
                    },
                }),
            ]);
            const services = {};
            telemetryServices.data.forEach((service) => {
                if (!service.id) {
                    return;
                }
                services[service.id.toString()] = service;
            });
            /*
             * Logs without a service.name are tagged with the projectId
             * (ServiceType.Unknown) and have no Service row. Register a
             * synthetic "Unknown Service" keyed by the projectId so the
             * primaryEntityId -> name resolution and the service facet render
             * "Unknown Service" instead of a raw id. Harmless when no logs
             * are unattributed — nothing resolves against it.
             */
            const projectId = ProjectUtil.getCurrentProjectId();
            if (projectId) {
                services[projectId.toString()] =
                    TelemetryServiceUtil.getUnknownService(projectId);
            }
            const hostsById = {};
            hosts.data.forEach((host) => {
                if (!host.id) {
                    return;
                }
                hostsById[host.id.toString()] = host;
            });
            const dockerHostsById = {};
            dockerHosts.data.forEach((dockerHost) => {
                if (!dockerHost.id) {
                    return;
                }
                dockerHostsById[dockerHost.id.toString()] = dockerHost;
            });
            const clustersById = {};
            kubernetesClusters.data.forEach((cluster) => {
                if (!cluster.id) {
                    return;
                }
                clustersById[cluster.id.toString()] = cluster;
            });
            setServiceMap(services);
            setHostMap(hostsById);
            setDockerHostMap(dockerHostsById);
            setKubernetesClusterMap(clustersById);
        }
        catch (err) {
            setPageError(`We couldn't load telemetry resource metadata. ${API.getFriendlyErrorMessage(err)}`);
        }
        finally {
            setIsPageLoading(false);
        }
    }, []);
    const loadAttributes = useCallback(async () => {
        try {
            setAttributesLoading(true);
            const attributeResponse = await API.post({
                url: URL.fromString(APP_API_URL.toString()).addRoute("/telemetry/logs/get-attributes"),
                data: {},
                headers: Object.assign({}, ModelAPI.getCommonHeaders()),
            });
            if (attributeResponse instanceof HTTPErrorResponse) {
                throw attributeResponse;
            }
            const attributes = (attributeResponse.data["attributes"] || []);
            setLogAttributes(attributes);
            setAttributesLoaded(true);
        }
        catch (_a) {
            setLogAttributes([]);
            setAttributesLoaded(false);
        }
        finally {
            setAttributesLoading(false);
        }
    }, []);
    useEffect(() => {
        void loadServices();
    }, [loadServices]);
    // Load attributes eagerly for search bar suggestions
    useEffect(() => {
        if (!attributesLoaded && !attributesLoading) {
            void loadAttributes();
        }
    }, [attributesLoaded, attributesLoading, loadAttributes]);
    /*
     * Lazily fetch values for the attribute the user is currently typing.
     * Triggered by `@key:` patterns in the search bar — the same approach
     * used by Traces/Metrics so the value dropdown can populate.
     */
    useEffect(() => {
        const currentWord = (searchQuery.split(/\s+/).pop() || "").trim();
        if (!currentWord.startsWith("@") || !currentWord.includes(":")) {
            return;
        }
        const colonIdx = currentWord.indexOf(":");
        const attrKey = currentWord.substring(1, colonIdx);
        if (!attrKey || attrKey === lastValueSuggestionKeyRef.current) {
            return;
        }
        lastValueSuggestionKeyRef.current = attrKey;
        const loadValues = async () => {
            try {
                setAttributeValuesLoading(true);
                const response = await API.post({
                    url: URL.fromString(APP_API_URL.toString()).addRoute("/telemetry/logs/get-attribute-values"),
                    data: { attributeKey: attrKey },
                    headers: Object.assign({}, ModelAPI.getCommonHeaders()),
                });
                if (response instanceof HTTPErrorResponse) {
                    throw response;
                }
                const values = (response.data["values"] ||
                    []);
                setAttributeValueSuggestions((prev) => {
                    return Object.assign(Object.assign({}, prev), { [attrKey]: values });
                });
            }
            catch (_a) {
                // non-critical — leave the dropdown empty so users can still free-type
            }
            finally {
                setAttributeValuesLoading(false);
            }
        };
        void loadValues();
    }, [searchQuery]);
    // Reset focused row when displayed logs change
    useEffect(() => {
        setFocusedRowIndex(-1);
    }, [displayedLogs]);
    const resetPage = useCallback(() => {
        if (props.onPageChange) {
            props.onPageChange(1);
        }
        if (props.page === undefined) {
            setInternalPage(1);
        }
    }, [props.onPageChange, props.page]);
    const handleSearchSubmit = useCallback(() => {
        const queryFilter = queryStringToFilter(searchQuery);
        // Resolve human-readable service name to UUID if needed
        if (queryFilter["primaryEntityId"] &&
            typeof queryFilter["primaryEntityId"] === "string") {
            const serviceName = queryFilter["primaryEntityId"];
            const resolvedId = resolveServiceNameToId(serviceName, serviceMap);
            if (resolvedId) {
                queryFilter["primaryEntityId"] = resolvedId;
            }
        }
        const mergedFilter = Object.assign(Object.assign({}, filterData), queryFilter);
        resetPage();
        setSelectedLogId(null);
        props.onFilterChanged(mergedFilter);
    }, [searchQuery, serviceMap, filterData, resetPage, props]);
    // Scroll focused row into view
    useEffect(() => {
        if (focusedRowIndex < 0) {
            return;
        }
        // Use requestAnimationFrame to ensure the DOM has updated with data-focused
        requestAnimationFrame(() => {
            const focusedRow = document.querySelector(`tr[data-focused="true"]`);
            if (focusedRow) {
                focusedRow.scrollIntoView({ block: "nearest" });
            }
        });
    }, [focusedRowIndex]);
    // Keyboard shortcuts: j/k navigate, Enter expand/collapse, Escape close, / focus search, Ctrl+Enter apply
    useEffect(() => {
        const handleKeyDown = (e) => {
            var _a;
            const target = e.target;
            const isInputFocused = target instanceof HTMLInputElement ||
                target instanceof HTMLTextAreaElement ||
                target instanceof HTMLSelectElement ||
                (target instanceof HTMLElement && target.isContentEditable);
            // Ctrl+Enter applies filters even when search bar is focused
            if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
                e.preventDefault();
                handleSearchSubmit();
                return;
            }
            // Skip other shortcuts when an input is focused
            if (isInputFocused) {
                return;
            }
            if (e.key === "/") {
                e.preventDefault();
                (_a = searchBarRef.current) === null || _a === void 0 ? void 0 : _a.focus();
                return;
            }
            if (e.key === "?") {
                e.preventDefault();
                setShowKeyboardShortcuts((prev) => {
                    return !prev;
                });
                return;
            }
            if (e.key === "Escape") {
                if (showKeyboardShortcuts) {
                    setShowKeyboardShortcuts(false);
                    return;
                }
                if (selectedLogId) {
                    setSelectedLogId(null);
                }
                return;
            }
            const logCount = displayedLogs.length;
            if (logCount === 0) {
                return;
            }
            if (e.key === "j") {
                e.preventDefault();
                setFocusedRowIndex((prev) => {
                    return Math.min(prev + 1, logCount - 1);
                });
                return;
            }
            if (e.key === "k") {
                e.preventDefault();
                setFocusedRowIndex((prev) => {
                    return Math.max(prev - 1, 0);
                });
                return;
            }
            if (e.key === "Enter") {
                if (focusedRowIndex >= 0 && focusedRowIndex < logCount) {
                    const log = displayedLogs[focusedRowIndex];
                    const rowId = resolveLogIdentifier(log, focusedRowIndex);
                    setSelectedLogId((currentSelected) => {
                        if (currentSelected === rowId) {
                            return null;
                        }
                        return rowId;
                    });
                }
                return;
            }
        };
        document.addEventListener("keydown", handleKeyDown);
        return () => {
            document.removeEventListener("keydown", handleKeyDown);
        };
    }, [
        displayedLogs,
        focusedRowIndex,
        selectedLogId,
        showKeyboardShortcuts,
        handleSearchSubmit,
    ]);
    const handlePageChange = (page) => {
        if (props.onPageChange) {
            props.onPageChange(page);
        }
        if (props.page === undefined) {
            setInternalPage(page);
        }
        setSelectedLogId(null);
    };
    const handlePageSizeChange = (size) => {
        if (props.onPageSizeChange) {
            props.onPageSizeChange(size);
        }
        if (props.pageSize === undefined) {
            setInternalPageSize(size);
        }
        resetPage();
        setSelectedLogId(null);
    };
    const handleSortChange = (field) => {
        var _a;
        const isSameField = sortField === field;
        const nextOrder = isSameField
            ? sortOrder === SortOrder.Descending
                ? SortOrder.Ascending
                : SortOrder.Descending
            : SortOrder.Descending;
        setLocalSortField(field);
        setLocalSortOrder(nextOrder);
        (_a = props.onSortChange) === null || _a === void 0 ? void 0 : _a.call(props, field, nextOrder);
        resetPage();
        setSelectedLogId(null);
    };
    /*
     * Enrich active filters with resolved display values (e.g. service names)
     * Must be before early returns to maintain consistent hook call order.
     */
    const enrichedActiveFilters = useMemo(() => {
        if (!props.activeFilters) {
            return [];
        }
        return props.activeFilters.map((filter) => {
            if (filter.facetKey === "primaryEntityId" && serviceMap[filter.value]) {
                const service = serviceMap[filter.value];
                return Object.assign(Object.assign({}, filter), { displayValue: (service === null || service === void 0 ? void 0 : service.name) || filter.value });
            }
            if (filter.facetKey === "hostId" && hostMap[filter.value]) {
                const host = hostMap[filter.value];
                return Object.assign(Object.assign({}, filter), { displayValue: (host === null || host === void 0 ? void 0 : host.name) || (host === null || host === void 0 ? void 0 : host.hostIdentifier) || filter.value });
            }
            if (filter.facetKey === "dockerHostId" && dockerHostMap[filter.value]) {
                const dockerHost = dockerHostMap[filter.value];
                return Object.assign(Object.assign({}, filter), { displayValue: (dockerHost === null || dockerHost === void 0 ? void 0 : dockerHost.name) || (dockerHost === null || dockerHost === void 0 ? void 0 : dockerHost.hostIdentifier) || filter.value });
            }
            if (filter.facetKey === "kubernetesClusterId" &&
                kubernetesClusterMap[filter.value]) {
                const cluster = kubernetesClusterMap[filter.value];
                return Object.assign(Object.assign({}, filter), { displayValue: (cluster === null || cluster === void 0 ? void 0 : cluster.name) || (cluster === null || cluster === void 0 ? void 0 : cluster.clusterIdentifier) || filter.value });
            }
            return filter;
        });
    }, [
        props.activeFilters,
        serviceMap,
        hostMap,
        dockerHostMap,
        kubernetesClusterMap,
    ]);
    /*
     * Replace primaryEntityId UUIDs with human-readable names in value suggestions,
     * and merge in the lazily-fetched attribute value suggestions.
     * Must be before early returns to maintain consistent hook call order.
     */
    const resolvedValueSuggestions = useMemo(() => {
        const hasParentSuggestions = Boolean(props.valueSuggestions);
        const hasAttributeSuggestions = Object.keys(attributeValueSuggestions).length > 0;
        if (!hasParentSuggestions && !hasAttributeSuggestions) {
            return undefined;
        }
        const suggestions = Object.assign(Object.assign({}, (props.valueSuggestions || {})), attributeValueSuggestions);
        if (suggestions["primaryEntityId"] &&
            Object.keys(serviceMap).length > 0) {
            suggestions["primaryEntityId"] = suggestions["primaryEntityId"].map((id) => {
                const service = serviceMap[id];
                return (service === null || service === void 0 ? void 0 : service.name) || id;
            });
        }
        return suggestions;
    }, [props.valueSuggestions, serviceMap, attributeValueSuggestions]);
    /*
     * Wrap onFieldValueSelect to resolve service names back to UUIDs
     * Must be before early returns to maintain consistent hook call order.
     */
    const handleFieldValueSelectWithServiceResolve = useMemo(() => {
        if (!props.onFieldValueSelect) {
            return undefined;
        }
        return (fieldKey, value) => {
            if (fieldKey === "service") {
                const resolvedId = resolveServiceNameToId(value, serviceMap);
                if (resolvedId) {
                    props.onFieldValueSelect(fieldKey, resolvedId);
                    return;
                }
            }
            props.onFieldValueSelect(fieldKey, value);
        };
    }, [props.onFieldValueSelect, serviceMap]);
    const selectedColumns = props.selectedColumns
        ? normalizeLogsTableColumns(props.selectedColumns)
        : internalSelectedColumns;
    const availableColumns = useMemo(() => {
        const attributeColumns = [...logAttributes]
            .sort((left, right) => {
            return left.localeCompare(right);
        })
            .map((attributeKey) => {
            return {
                id: getLogsAttributeColumnId(attributeKey),
                label: attributeKey,
                attributeKey,
            };
        });
        return [...CORE_LOGS_TABLE_COLUMN_OPTIONS, ...attributeColumns];
    }, [logAttributes]);
    if (isPageLoading) {
        return React.createElement(PageLoader, { isVisible: true });
    }
    if (pageError) {
        return React.createElement(ErrorMessage, { message: pageError });
    }
    const currentViewMode = (_f = props.viewMode) !== null && _f !== void 0 ? _f : internalViewMode;
    const handleViewModeChange = (mode) => {
        var _a;
        if (!props.viewMode) {
            setInternalViewMode(mode);
        }
        (_a = props.onViewModeChange) === null || _a === void 0 ? void 0 : _a.call(props, mode);
    };
    const toolbarProps = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ resultCount: totalItems, currentPage,
        totalPages, viewMode: currentViewMode, onViewModeChange: handleViewModeChange, savedViews: props.savedViews, selectedSavedViewId: props.selectedSavedViewId, onSavedViewSelect: props.onSavedViewSelect, onCreateSavedView: props.onCreateSavedView, onEditSavedView: props.onEditSavedView, onDeleteSavedView: props.onDeleteSavedView, onUpdateCurrentSavedView: props.onUpdateCurrentSavedView }, (props.onSelectedColumnsChange || props.selectedColumns
        ? {
            availableColumns,
            selectedColumns,
            onSelectedColumnsChange: (columns) => {
                var _a;
                const nextColumns = normalizeLogsTableColumns(columns);
                if (!props.selectedColumns) {
                    setInternalSelectedColumns(nextColumns);
                }
                (_a = props.onSelectedColumnsChange) === null || _a === void 0 ? void 0 : _a.call(props, nextColumns);
            },
        }
        : {})), { onExportCSV: () => {
            exportLogs(displayedLogs, LogExportFormat.CSV, selectedColumns);
        }, onExportJSON: () => {
            exportLogs(displayedLogs, LogExportFormat.JSON, selectedColumns);
        } }), (props.liveOptions ? { liveOptions: props.liveOptions } : {})), (props.timeRange && props.onTimeRangeChange
        ? {
            timeRange: props.timeRange,
            onTimeRangeChange: props.onTimeRangeChange,
        }
        : {})), { showKeyboardShortcuts, onToggleKeyboardShortcuts: () => {
            setShowKeyboardShortcuts((prev) => {
                return !prev;
            });
        }, onShowDocumentation: props.onShowDocumentation });
    const showSidebar = props.showFacetSidebar !== false && Boolean(props.facetData);
    return (React.createElement("div", { className: "space-y-2" },
        props.showFilters && (React.createElement("div", null,
            React.createElement(LogsFilterCard, { ref: searchBarRef, logAttributes: logAttributes, searchQuery: searchQuery, onSearchQueryChange: setSearchQuery, onSearchSubmit: handleSearchSubmit, valueSuggestions: resolvedValueSuggestions, onFieldValueSelect: handleFieldValueSelectWithServiceResolve, isAttributesLoading: attributesLoading, isValuesLoading: attributeValuesLoading, toolbar: React.createElement(LogsViewerToolbar, Object.assign({}, toolbarProps)) }))),
        ((props.baseActiveFilters && props.baseActiveFilters.length > 0) ||
            (enrichedActiveFilters.length > 0 && props.onRemoveFilter)) && (React.createElement(ActiveFilterChips, { filters: [
                ...(props.baseActiveFilters || []),
                ...enrichedActiveFilters,
            ], onRemove: props.onRemoveFilter || (() => { }), onClearAll: props.onClearAllFilters || (() => { }) })),
        props.histogramBuckets && (React.createElement(LogsHistogram, { buckets: props.histogramBuckets, isLoading: props.histogramLoading || false, onTimeRangeSelect: props.onHistogramTimeRangeSelect })),
        currentViewMode === "analytics" ? (React.createElement(LogsAnalyticsView, { timeRange: props.timeRange || { range: TimeRange.PAST_ONE_HOUR }, serviceIds: props.analyticsServiceIds, appliedFacetFilters: props.analyticsAppliedFacetFilters || new Map(), logAttributes: logAttributes })) : (React.createElement("div", { className: "flex gap-3" },
            showSidebar && props.facetData && (React.createElement(LogsFacetSidebar, { facetData: props.facetData, isLoading: props.facetLoading || false, serviceMap: serviceMap, hostMap: hostMap, dockerHostMap: dockerHostMap, kubernetesClusterMap: kubernetesClusterMap, onIncludeFilter: props.onFacetInclude || (() => { }), onExcludeFilter: props.onFacetExclude || (() => { }), activeFilters: props.activeFilters, savedViews: props.savedViews, selectedSavedViewId: props.selectedSavedViewId, onSavedViewSelect: props.onSavedViewSelect, onFacetSearchChange: props.onFacetSearchChange })),
            React.createElement("div", { className: "min-w-0 flex-1" },
                React.createElement("div", { className: "overflow-hidden rounded-lg border border-gray-200 bg-white shadow-sm" },
                    !props.showFilters && (React.createElement("div", { className: "border-b border-gray-100 bg-gray-50/50 px-4 py-3" },
                        React.createElement(LogsViewerToolbar, Object.assign({}, toolbarProps)))),
                    React.createElement(LogsTable, { logs: displayedLogs, serviceMap: serviceMap, isLoading: props.isLoading, focusedRowIndex: focusedRowIndex >= 0 ? focusedRowIndex : undefined, emptyMessage: props.noLogsMessage ||
                            getEmptyMessageWithTimeRange(props.timeRange), onRowClick: (_log, rowId) => {
                            setSelectedLogId((currentSelected) => {
                                if (currentSelected === rowId) {
                                    return null;
                                }
                                return rowId;
                            });
                        }, selectedLogId: selectedLogId, sortField: sortField, sortOrder: sortOrder, onSortChange: handleSortChange, selectedColumns: selectedColumns, renderExpandedContent: (log) => {
                            return (React.createElement(LogDetailsPanel, { log: log, serviceMap: serviceMap, onClose: () => {
                                    setSelectedLogId(null);
                                }, getTraceRoute: props.getTraceRoute, getSpanRoute: props.getSpanRoute, variant: "embedded", projectId: props.projectId, onFilterByAttribute: handleFieldValueSelectWithServiceResolve }));
                        } }),
                    React.createElement(LogsPagination, { currentPage: currentPage, totalItems: totalItems, pageSize: pageSize, pageSizeOptions: PAGE_SIZE_OPTIONS, onPageChange: handlePageChange, onPageSizeChange: handlePageSizeChange, isDisabled: props.isLoading || totalItems === 0 })))))));
};
export default LogsViewer;
//# sourceMappingURL=LogsViewer.js.map