import { jsx, jsxs } from 'react/jsx-runtime';
import { useRef, useState, useMemo, useEffect, useCallback, isValidElement, cloneElement } from 'react';
import { DndContext, closestCorners } from '../../../node_modules/.pnpm/@dnd-kit_core@6.3.1_react-d_dd28f9613915b34fadb5fb09ef9e129f/node_modules/@dnd-kit/core/dist/core.esm.js';
import { restrictToVerticalAxis } from '../../../node_modules/.pnpm/@dnd-kit_modifiers@9.0.0_@d_29804ea7af5102b7c3fb5f8ff91223c9/node_modules/@dnd-kit/modifiers/dist/modifiers.esm.js';
import { SortableContext, verticalListSortingStrategy } from '../../../node_modules/.pnpm/@dnd-kit_sortable@8.0.0_@dn_d0203b85309944898f6a8d832beb8e74/node_modules/@dnd-kit/sortable/dist/sortable.esm.js';
import classNames from '../../../_virtual/index.js';
import StepTableMainRow from './StepTableMainRow.js';
import Typography from '../../Typography/Typography.js';
import { prepareData } from '../../TableTreeFn/Utils/TableCell.js';
import { appendNewRow } from '../../../utils/AppendNewRow/AppendNewRow.js';
import { checkEmpty } from '../../../utils/checkEmpty/checkEmpty.js';
import { isFunction } from '../../../assets/utils/functionUtils.js';
import { ffid } from '../../../utils/ffID/ffid.js';
import Icon from '../../Icon/Icon.js';

const accordionRowTypes = new Set(['group', 'pre', 'post', 'script']);
const getVirtualRowKey = (row, kind, index) => `${kind}-${row?._id || row?.stepId || row?.id || index}`;
const isAccordionRow = (row) => accordionRowTypes.has(row?.entityType?.toLowerCase()) ||
    accordionRowTypes.has(row?.type?.toLowerCase());
const getNestedPadding = (row) => isAccordionRow(row) ? '6px 8px' : '7px 8px';
const VirtualNestedRow = ({ row, indent = 0, columns, tableType, viewModeId, ViewComponent, handleClick, handleStepGroupExpand, isStepGroupExpanded, isViewPrivilegeMode, measureIndex, updateRowHeight, }) => {
    const rowRef = useRef(null);
    const showAccordion = isAccordionRow(row);
    useEffect(() => {
        const currentRow = rowRef.current;
        if (!currentRow || !updateRowHeight)
            return;
        const measureRow = () => {
            updateRowHeight(measureIndex, currentRow.getBoundingClientRect().height);
        };
        measureRow();
        if (typeof ResizeObserver === 'undefined')
            return undefined;
        const resizeObserver = new ResizeObserver(measureRow);
        resizeObserver.observe(currentRow);
        return () => {
            resizeObserver.disconnect();
        };
    }, [measureIndex, row, updateRowHeight, viewModeId]);
    if (viewModeId === row?.stepId) {
        return (jsx("tr", { ref: rowRef, className: "steps-edit-row", id: "getInFocus", "data-rowid": row?.stepId, children: jsx("td", { colSpan: columns.length, children: jsx("div", { style: { marginLeft: `${indent}px` }, children: ViewComponent && jsx(ViewComponent, {}) }) }) }));
    }
    return (jsx("tr", { ref: rowRef, "data-rowid": row?.stepId, children: columns.map((col, idx) => (jsx("td", { style: {
                maxWidth: col.width,
                padding: getNestedPadding(row),
            }, children: jsxs(Typography, { as: "div", className: "ff-data-checkbox-container", children: [jsxs("div", { className: "ff-data-checkbox-container-content", style: {
                            marginLeft: idx === 0 ? `${indent}px` : 0,
                        }, onClick: () => {
                            const isClickable = idx === 0 &&
                                !row?.displayName?.includes('End') &&
                                !row?.isDisabled;
                            if (isClickable)
                                handleClick?.({ ...row, tableType });
                        }, children: [!isViewPrivilegeMode && idx === 0 && (jsx("div", { className: "ff-nested-row-spacer" })), prepareData({ ...row, marginLeft: indent }, col)] }), idx === 0 && showAccordion && (jsx("div", { className: `ff-accordion-arrow ${isStepGroupExpanded?.(row.stepId) ? 'expanded' : ''}`, children: jsx(Icon, { name: "arrow_right", color: isStepGroupExpanded?.(row.stepId)
                                ? 'var(--brand-color)'
                                : 'var(--default-color)', className: "steps-arrow-svg", width: 12, height: 12, onClick: () => handleStepGroupExpand?.({
                                ...row,
                                tableType,
                            }) }) }))] }) }, `${row?.stepId || row?._id}-${idx}`))) }));
};
const StepInnerTable = ({ data = [], columns = [], headerType, withCheckbox = false, onSelect, withFixedHeader = true, borderWithRadius = false, noDataContent, height = '100%', className = '', tableBodyRowClass = '', headerTextColor, tableDataTextColor, draggable = false, onDragEnd, loadMore = () => { }, editMode = '', editComponent, NlpComponent, AddNlp, handleDragStart, tableType, viewModeId, ViewComponent, handleClick, selectedRows, handleStepGroupExpand, isStepGroupExpanded, stepPartialSelect, isViewPrivilegeMode, isClientSide, highlightKey, onHighlightComplete, }) => {
    const observerRef = useRef(null);
    const containerRef = useRef(null);
    const [scrollTop, setScrollTop] = useState(0);
    const [containerHeight, setContainerHeight] = useState(0);
    const [rowHeights, setRowHeights] = useState([]);
    const [focusRowId, setFocusRowId] = useState(null);
    const buffer = 5;
    const estimatedRowHeight = 34;
    const firstVisibleIndexRef = useRef(0);
    const measuredRowHeightsRef = useRef(new Map());
    const rowHeightsRef = useRef([]);
    const hasFixedHeight = height !== 'auto';
    const fullData = useMemo(() => appendNewRow(data, AddNlp ?? {}), [data, AddNlp]);
    const virtualRows = useMemo(() => {
        if (!hasFixedHeight) {
            return fullData.map((row, index) => ({
                key: getVirtualRowKey(row, 'main', index),
                kind: 'main',
                row,
                dataIndex: index,
            }));
        }
        const flattenedRows = [];
        const appendNestedRows = (rows = [], level = 0) => {
            const indent = level + 8;
            rows.forEach((row) => {
                const nestedIndex = flattenedRows.length;
                flattenedRows.push({
                    key: getVirtualRowKey(row, 'nested', nestedIndex),
                    kind: 'nested',
                    row,
                    dataIndex: nestedIndex,
                    indent,
                });
                if (isStepGroupExpanded?.(row?.stepId)) {
                    appendNestedRows(row?.data || row?.stepResults || [], indent);
                }
            });
        };
        fullData.forEach((row, index) => {
            flattenedRows.push({
                key: getVirtualRowKey(row, 'main', index),
                kind: 'main',
                row,
                dataIndex: index,
            });
            const isEditOrNew = editMode === row?.stepId || row?.isNew;
            if (!isEditOrNew && isStepGroupExpanded?.(row?.stepId)) {
                appendNestedRows(row?.data || row?.stepResults || [], row?.marginLeft);
            }
        });
        return flattenedRows;
    }, [editMode, fullData, hasFixedHeight, isStepGroupExpanded]);
    useEffect(() => {
        setRowHeights((prev) => {
            const next = virtualRows.map((row) => measuredRowHeightsRef.current.get(row.key) ?? estimatedRowHeight);
            const hasChanged = prev.length !== next.length ||
                prev.some((height, index) => height !== next[index]);
            return hasChanged ? next : prev;
        });
    }, [virtualRows]);
    useEffect(() => {
        rowHeightsRef.current = rowHeights;
    }, [rowHeights]);
    const totalRows = virtualRows.length;
    const totalContentHeight = useMemo(() => {
        if (!hasFixedHeight)
            return undefined;
        if (rowHeights.length !== totalRows) {
            return totalRows * estimatedRowHeight;
        }
        return rowHeights.reduce((sum, rowHeight) => sum + rowHeight, 0);
    }, [hasFixedHeight, rowHeights, totalRows]);
    useEffect(() => {
        if (!hasFixedHeight ||
            !containerRef.current ||
            totalContentHeight === undefined) {
            return;
        }
        const maxScrollTop = Math.max(0, totalContentHeight - containerHeight);
        if (scrollTop > maxScrollTop) {
            containerRef.current.scrollTop = maxScrollTop;
            setScrollTop(maxScrollTop);
        }
    }, [containerHeight, hasFixedHeight, scrollTop, totalContentHeight]);
    useEffect(() => {
        if (containerRef.current) {
            setContainerHeight(containerRef.current.clientHeight);
        }
    }, [data, AddNlp]);
    useEffect(() => {
        const container = containerRef.current;
        if (!container)
            return;
        const updateContainerHeight = () => {
            setContainerHeight(container.clientHeight);
        };
        updateContainerHeight();
        if (typeof ResizeObserver === 'undefined') {
            window.addEventListener('resize', updateContainerHeight);
            return () => {
                window.removeEventListener('resize', updateContainerHeight);
            };
        }
        const resizeObserver = new ResizeObserver(updateContainerHeight);
        resizeObserver.observe(container);
        return () => {
            resizeObserver.disconnect();
        };
    }, []);
    // Track focus row for edit/new rows
    useEffect(() => {
        // Prioritize highlightKey over other states
        if (!checkEmpty(highlightKey)) {
            setFocusRowId(highlightKey);
        }
        else if (editMode) {
            setFocusRowId(editMode);
        }
        else if (AddNlp && Object.keys(AddNlp).length > 0) {
            const newRow = appendNewRow(data, AddNlp).find((row) => row.isNew);
            if (newRow) {
                setFocusRowId(newRow.stepId || 'new-row');
            }
        }
        else {
            setFocusRowId(null);
        }
    }, [editMode, AddNlp, data, highlightKey]);
    // Update scroll effect
    useEffect(() => {
        if (focusRowId && containerRef.current) {
            const timer = setTimeout(() => {
                const focusElement = containerRef.current?.querySelector(`[data-rowid="${focusRowId}"]`);
                if (focusElement) {
                    focusElement.scrollIntoView({
                        behavior: 'smooth',
                        block: 'nearest',
                    });
                    // ADD THIS: Reset highlight after scroll completes
                    setTimeout(() => {
                        if (!checkEmpty(highlightKey)) {
                            onHighlightComplete?.();
                        }
                    }, 300); // Match scroll duration
                }
            }, 100);
            return () => clearTimeout(timer);
        }
        return undefined;
    }, [focusRowId, rowHeights, highlightKey, onHighlightComplete]);
    const updateRowHeight = useCallback((index, height) => {
        const nextHeight = Math.ceil(height);
        const previousHeight = rowHeightsRef.current[index] ?? estimatedRowHeight;
        if (previousHeight === nextHeight)
            return;
        const rowKey = virtualRows[index]?.key;
        if (rowKey) {
            measuredRowHeightsRef.current.set(rowKey, nextHeight);
        }
        const heightDelta = nextHeight - previousHeight;
        if (hasFixedHeight &&
            index < firstVisibleIndexRef.current &&
            containerRef.current) {
            const nextScrollTop = Math.max(0, containerRef.current.scrollTop + heightDelta);
            containerRef.current.scrollTop = nextScrollTop;
            setScrollTop(nextScrollTop);
        }
        setRowHeights((prev) => {
            const newHeights = [...prev];
            if (index < newHeights.length && newHeights[index] !== nextHeight) {
                newHeights[index] = nextHeight;
                return newHeights;
            }
            return prev;
        });
    }, [hasFixedHeight, virtualRows]);
    const handleScroll = useCallback((e) => {
        const scrollTopValue = e.currentTarget.scrollTop;
        setScrollTop(scrollTopValue);
        checkAndFetchMoreData(scrollTopValue);
    }, [totalRows]);
    const checkAndFetchMoreData = useCallback((currentScrollTop) => {
        if (!containerRef.current)
            return;
        const containerHeight = containerRef.current.clientHeight;
        const scrollableHeight = containerRef.current.scrollHeight;
        const scrollPercentage = (currentScrollTop + containerHeight) / scrollableHeight;
        if (scrollPercentage > 0.8) {
            loadMore('below');
        }
        if (currentScrollTop < 200) {
            loadMore('above');
        }
    }, [loadMore]);
    const { startIndex, firstVisibleIndex, paddingTop, paddingBottom, visibleRows, } = useMemo(() => {
        if (!hasFixedHeight) {
            return {
                startIndex: 0,
                firstVisibleIndex: 0,
                endIndex: totalRows - 1,
                paddingTop: 0,
                paddingBottom: 0,
                visibleRows: virtualRows,
            };
        }
        let startIndex = 0;
        let firstVisibleIndex = 0;
        let endIndex = totalRows - 1;
        let paddingTop = 0;
        let paddingBottom = 0;
        if (rowHeights.length === totalRows && containerHeight > 0) {
            let cumulativeHeight = 0;
            for (let i = 0; i < totalRows; i++) {
                const rowHeight = rowHeights[i] ?? estimatedRowHeight;
                if (cumulativeHeight + rowHeight > scrollTop) {
                    firstVisibleIndex = i;
                    break;
                }
                cumulativeHeight += rowHeight;
                if (i === totalRows - 1) {
                    firstVisibleIndex = totalRows - 1;
                }
            }
            cumulativeHeight = 0;
            for (let i = 0; i < totalRows; i++) {
                cumulativeHeight += rowHeights[i] ?? 0;
                if (cumulativeHeight >= scrollTop + containerHeight &&
                    endIndex === totalRows - 1) {
                    endIndex = i;
                    break;
                }
            }
            startIndex = Math.max(0, firstVisibleIndex - buffer);
            endIndex = Math.min(totalRows - 1, endIndex + buffer);
            if (focusRowId) {
                const focusIndex = virtualRows.findIndex(({ row }) => row?.stepId === focusRowId ||
                    (row?.isNew && focusRowId === 'new-row'));
                if (focusIndex >= 0) {
                    if (focusIndex < startIndex) {
                        startIndex = focusIndex;
                    }
                    else if (focusIndex > endIndex) {
                        endIndex = focusIndex;
                    }
                }
            }
            paddingTop = rowHeights
                .slice(0, startIndex)
                .reduce((sum, height) => sum + height, 0);
            paddingBottom = rowHeights
                .slice(endIndex + 1)
                .reduce((sum, height) => sum + height, 0);
        }
        else {
            firstVisibleIndex = Math.max(0, Math.floor(scrollTop / estimatedRowHeight));
            startIndex = Math.max(0, firstVisibleIndex - buffer);
            endIndex = Math.min(totalRows - 1, firstVisibleIndex +
                Math.ceil(containerHeight / estimatedRowHeight) +
                buffer);
            if (focusRowId) {
                const focusIndex = virtualRows.findIndex(({ row }) => row?.stepId === focusRowId ||
                    (row?.isNew && focusRowId === 'new-row'));
                if (focusIndex >= 0) {
                    if (focusIndex < startIndex) {
                        startIndex = focusIndex;
                    }
                    else if (focusIndex > endIndex) {
                        endIndex = focusIndex;
                    }
                }
            }
            paddingTop = startIndex * estimatedRowHeight;
            paddingBottom = (totalRows - endIndex - 1) * estimatedRowHeight;
        }
        const visibleRows = virtualRows.slice(startIndex, endIndex + 1);
        return {
            startIndex,
            firstVisibleIndex,
            endIndex,
            paddingTop,
            paddingBottom,
            visibleRows,
        };
    }, [
        hasFixedHeight,
        totalRows,
        virtualRows,
        rowHeights,
        containerHeight,
        scrollTop,
        buffer,
        focusRowId,
        estimatedRowHeight,
    ]);
    useEffect(() => {
        firstVisibleIndexRef.current = firstVisibleIndex;
    }, [firstVisibleIndex]);
    useEffect(() => {
        const scrollContainer = containerRef.current;
        const firstNode = document.getElementById('ff-table-first-node');
        const lastNode = document.getElementById('ff-table-last-node');
        if (!scrollContainer || !firstNode || !lastNode || !data?.length) {
            return;
        }
        observerRef.current = new IntersectionObserver((entries) => {
            entries.forEach((entry) => {
                if (entry.isIntersecting) {
                    const direction = entry.target.id === 'ff-table-last-node' ? 'below' : 'above';
                    loadMore(direction);
                }
            });
        }, {
            root: scrollContainer,
            rootMargin: '8px',
            threshold: 0.1,
        });
        observerRef.current.observe(firstNode);
        observerRef.current.observe(lastNode);
        return () => {
            observerRef.current?.disconnect();
        };
    }, [data?.length, loadMore]);
    const handleOnclick = (column, row, index) => {
        const { onClick, accessor } = column;
        if (onClick && isFunction(onClick)) {
            onClick(accessor, row, index);
        }
    };
    const onSelectClick = (tableType, rowData, isChecked) => {
        if (onSelect) {
            onSelect(tableType, rowData, isChecked);
        }
    };
    const handleDragEnd = (event) => {
        const { active, over } = event;
        if (!over || active.id === over.id)
            return;
        const oldIndex = data.findIndex((item) => item._id === active.id || item.stepId === active.id);
        const newIndex = data.findIndex((item) => item._id === over.id || item.stepId === over.id);
        if (oldIndex === -1 || newIndex === -1)
            return;
        if (onDragEnd)
            onDragEnd(oldIndex, newIndex);
    };
    return (jsx(DndContext, { collisionDetection: closestCorners, onDragStart: handleDragStart, onDragEnd: handleDragEnd, modifiers: [restrictToVerticalAxis], children: jsx(SortableContext, { disabled: !draggable, items: data?.map((row) => row._id || row.stepId), strategy: verticalListSortingStrategy, children: jsx("div", { ref: containerRef, style: {
                    height: height,
                    position: 'relative',
                    overflowY: hasFixedHeight ? 'auto' : undefined,
                }, id: "ff-table-scroll-container", className: classNames(className, {
                    'ff-fixed-header-steps-table': withFixedHeader,
                    'steps-border-borderRadius': borderWithRadius,
                }), onScroll: handleScroll, children: jsxs("div", { className: "ff-scroll-container-inner", style: { height: totalContentHeight }, children: [jsxs("table", { className: classNames(`ff-table-steps`), cellSpacing: 0, children: [jsx("thead", { className: 'steps-inner-thead', children: jsx("tr", { children: columns?.map((column) => (jsx("th", { className: classNames(`${headerType && `${headerType}-bg`}`, `${headerTextColor && `${headerTextColor}-color`}`), style: { width: column?.width } }, `${column.header}-${ffid()}`))) }) }), jsxs("tbody", { className: "ff-steps-tbody", children: [jsx("tr", { id: "ff-table-first-node", className: "ff-hidden-sentinel" }), paddingTop > 0 && (jsx("tr", { "aria-hidden": "true", children: jsx("td", { className: "ff-padding-row", style: { height: paddingTop }, colSpan: columns.length }) })), visibleRows.map((virtualRow, index) => {
                                            const absoluteIndex = startIndex + index;
                                            const { row } = virtualRow;
                                            if (virtualRow.kind === 'nested') {
                                                return (jsx(VirtualNestedRow, { row: row, indent: virtualRow.indent, columns: columns, tableType: tableType, viewModeId: viewModeId, ViewComponent: ViewComponent, handleClick: handleClick, handleStepGroupExpand: handleStepGroupExpand, isStepGroupExpanded: isStepGroupExpanded, isViewPrivilegeMode: isViewPrivilegeMode, measureIndex: absoluteIndex, updateRowHeight: updateRowHeight }, virtualRow.key));
                                            }
                                            const displayIndex = virtualRow.dataIndex;
                                            const isEdit = editMode === row.stepId;
                                            const isEditOrNew = isEdit || row.isNew;
                                            const isFocusRow = (isEdit && row.stepId === focusRowId) ||
                                                (row.isNew && focusRowId === 'new-row');
                                            const renderEditableRow = () => (jsxs("tr", { className: "steps-edit-row", id: isFocusRow ? 'getInFocus' : undefined, "data-rowid": row.stepId || 'new-row', children: [isEdit && isValidElement(editComponent) && (jsx("td", { colSpan: columns.length, children: cloneElement(editComponent, {
                                                            rowData: row,
                                                            rowIndex: displayIndex + 1,
                                                        }) })), row.isNew &&
                                                        !isEdit &&
                                                        isValidElement(NlpComponent) && (jsx("td", { colSpan: columns.length, children: cloneElement(NlpComponent, {
                                                            rowIndex: displayIndex,
                                                            rowData: row,
                                                        }) }))] }, virtualRow.key));
                                            const renderSortableRow = () => (jsx(StepTableMainRow, { rowId: row.stepId, row: row, indexNumber: displayIndex, columns: columns, tableBodyRowClass: tableBodyRowClass, handleOnclick: handleOnclick, tableDataTextColor: tableDataTextColor, withCheckbox: withCheckbox, onSelectClick: onSelectClick, draggable: draggable, tableType: tableType, viewModeId: viewModeId, ViewComponent: ViewComponent, handleClick: handleClick, selectedRows: selectedRows, handleStepGroupExpand: handleStepGroupExpand, isStepGroupExpanded: isStepGroupExpanded, dataLength: data?.length, stepPartialSelect: stepPartialSelect, isViewPrivilegeMode: isViewPrivilegeMode, isClientSide: isClientSide, measureIndex: absoluteIndex, renderExpandedChildren: !hasFixedHeight, updateRowHeight: updateRowHeight }, virtualRow.key));
                                            return isEditOrNew
                                                ? renderEditableRow()
                                                : renderSortableRow();
                                        }), paddingBottom > 0 && (jsx("tr", { "aria-hidden": "true", children: jsx("td", { className: "ff-padding-row", style: { height: paddingBottom }, colSpan: columns.length }) })), jsx("tr", { id: "ff-table-last-node", className: "ff-hidden-sentinel" })] })] }), checkEmpty(data) && (jsx("div", { className: "steps-no-data-content", style: {
                                height: hasFixedHeight ? `calc(${height} - 50px)` : 'auto',
                            }, children: noDataContent }))] }) }) }) }));
};

export { StepInnerTable as default };
//# sourceMappingURL=StepInnerTable.js.map
