// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React from 'react';
import clsx from 'clsx';
import { findUpUntil } from '@cloudscape-design/component-toolkit/dom';
import { fireNonCancelableEvent } from '../internal/events';
import { getGroupColumnIds, getGroupSplit } from './column-groups/split-utils';
import { TableHeaderCell } from './header-cell';
import { TableGroupHeaderCell } from './header-cell/group-header-cell';
import { focusMarkers } from './selection';
import { TableHeaderSelectionCell } from './selection/selection-cell';
import { getTableHeaderRowRoleProps } from './table-role';
import { DEFAULT_COLUMN_WIDTH, useColumnWidths } from './use-column-widths';
import { getColumnKey } from './utils';
import styles from './styles.css.js';
const Thead = React.forwardRef(({ selectionType, getSelectAllProps, columnDefinitions, columnGroupsLayout, sortingColumn, sortingDisabled, sortingDescending, resizableColumns, variant, tableVariant, wrapLines, onFocusMove, onSortingChange, onResizeFinish, singleSelectionHeaderAriaLabel, stripedRows, sticky = false, hidden = false, stuck = false, stickyState, stickyColumnsFirst, stickyColumnsLast, selectionColumnId, focusedComponent, onFocusedComponentChange, tableRole, resizerRoleDescription, resizerTooltipText, isExpandable, setLastUserAction, }, outerRef) => {
    const { getColumnStyles, columnWidths, updateColumn, updateGroup, setCell } = useColumnWidths();
    const handleSplitGroupResize = (columnIds, newWidth) => {
        const lastColumn = columnIds[columnIds.length - 1];
        if (lastColumn) {
            const currentGroupWidth = columnIds.reduce((sum, id) => sum + (columnWidths.get(id) || DEFAULT_COLUMN_WIDTH), 0);
            const delta = newWidth - currentGroupWidth;
            const currentColumnWidth = columnWidths.get(lastColumn) || DEFAULT_COLUMN_WIDTH;
            updateColumn(lastColumn, currentColumnWidth + delta);
        }
    };
    const commonCellProps = {
        stuck,
        sticky,
        hidden,
        stripedRows,
        tableRole,
        variant,
        tableVariant,
        stickyState,
        wrapLines,
    };
    const sharedTrProps = {
        onFocus: (event) => {
            var _a;
            const focusControlElement = findUpUntil(event.target, element => !!element.getAttribute('data-focus-id'));
            const focusId = (_a = focusControlElement === null || focusControlElement === void 0 ? void 0 : focusControlElement.getAttribute('data-focus-id')) !== null && _a !== void 0 ? _a : null;
            onFocusedComponentChange === null || onFocusedComponentChange === void 0 ? void 0 : onFocusedComponentChange(focusId);
        },
        onBlur: () => onFocusedComponentChange === null || onFocusedComponentChange === void 0 ? void 0 : onFocusedComponentChange(null),
    };
    // No grouping - render single row
    if (!columnGroupsLayout || columnGroupsLayout.rows.length <= 1) {
        return (React.createElement("thead", { className: clsx(!hidden && styles['thead-active']) },
            React.createElement("tr", { ...focusMarkers.all, ref: outerRef, "aria-rowindex": 1, ...getTableHeaderRowRoleProps({ tableRole }), ...sharedTrProps },
                selectionType ? (React.createElement(TableHeaderSelectionCell, { ...commonCellProps, focusedComponent: focusedComponent, columnId: selectionColumnId, cellRef: node => setCell(sticky, selectionColumnId, node), getSelectAllProps: getSelectAllProps, onFocusMove: onFocusMove, singleSelectionHeaderAriaLabel: singleSelectionHeaderAriaLabel })) : null,
                columnDefinitions.map((column, colIndex) => {
                    const columnId = getColumnKey(column, colIndex);
                    return (React.createElement(TableHeaderCell, { ...commonCellProps, key: columnId, tabIndex: sticky ? -1 : 0, focusedComponent: focusedComponent, column: column, activeSortingColumn: sortingColumn, sortingDescending: sortingDescending, sortingDisabled: sortingDisabled, wrapLines: wrapLines, colIndex: selectionType ? colIndex + 1 : colIndex, columnId: columnId, updateColumn: updateColumn, onResizeFinish: () => onResizeFinish(columnWidths), resizableColumns: resizableColumns, resizableStyle: getColumnStyles(sticky, columnId), onClick: detail => {
                            setLastUserAction('sorting');
                            fireNonCancelableEvent(onSortingChange, detail);
                        }, isEditable: !!column.editConfig, cellRef: node => setCell(sticky, columnId, node), tableRole: tableRole, resizerRoleDescription: resizerRoleDescription, resizerTooltipText: resizerTooltipText, isExpandable: colIndex === 0 && isExpandable, hasDynamicContent: hidden && !resizableColumns && column.hasDynamicContent, isLast: colIndex === columnDefinitions.length - 1 }));
                }))));
    }
    // Grouped columns
    const totalColumns = columnDefinitions.length;
    return (React.createElement("thead", { className: clsx(!hidden && styles['thead-active']) }, columnGroupsLayout.rows.map((row, rowIndex) => (React.createElement("tr", { key: rowIndex, ...(rowIndex === 0 ? focusMarkers.all : {}), ref: rowIndex === 0 ? outerRef : undefined, "aria-rowindex": rowIndex + 1, "data-group-level": rowIndex, ...getTableHeaderRowRoleProps({ tableRole, rowIndex }), ...sharedTrProps },
        selectionType && rowIndex === 0 ? (React.createElement(TableHeaderSelectionCell, { ...commonCellProps, focusedComponent: focusedComponent, columnId: selectionColumnId, cellRef: node => setCell(sticky, selectionColumnId, node), getSelectAllProps: getSelectAllProps, onFocusMove: onFocusMove, singleSelectionHeaderAriaLabel: singleSelectionHeaderAriaLabel, rowSpan: columnGroupsLayout.rows.length })) : null,
        row.columns.map((col, colIndexInRow) => {
            var _a, _b;
            // A cell is the last child of its parent group when the next rendered cell
            // in the same row belongs to a different top-level parent, i.e. they don't
            // share the same immediate parent group.
            const nextCol = row.columns[colIndexInRow + 1];
            const thisParent = (_a = col.parentGroupIds[col.parentGroupIds.length - 1]) !== null && _a !== void 0 ? _a : null;
            const nextParent = nextCol ? ((_b = nextCol.parentGroupIds[nextCol.parentGroupIds.length - 1]) !== null && _b !== void 0 ? _b : null) : null;
            // A column is also considered last-child-of-group when the sticky boundary
            // bisects its parent group just after this column — visually it's the rightmost
            // column of the sticky half, so its resizer should span full-height like a
            // normal last-child-of-group.
            const isColumnAtStickyFirstBoundary = !col.isGroup &&
                thisParent !== null &&
                stickyColumnsFirst > 0 &&
                col.colIndex === stickyColumnsFirst - 1;
            const isColumnAtStickyLastBoundary = !col.isGroup &&
                thisParent !== null &&
                stickyColumnsLast > 0 &&
                col.colIndex === columnDefinitions.length - stickyColumnsLast - 1;
            const isLastChildOfGroup = (thisParent !== null && thisParent !== nextParent) ||
                isColumnAtStickyFirstBoundary ||
                isColumnAtStickyLastBoundary;
            if (col.isGroup) {
                // Group header cell
                const groupDefinition = col.groupDefinition;
                const childIds = getGroupColumnIds(columnGroupsLayout, col.id);
                const sharedGroupCellProps = {
                    ...commonCellProps,
                    tabIndex: sticky ? -1 : 0,
                    focusedComponent,
                    group: groupDefinition,
                    rowspan: col.rowSpan,
                    resizableColumns,
                    onResizeFinish: () => onResizeFinish(columnWidths),
                    columnGroupId: col.parentGroupIds.length > 0 ? col.parentGroupIds[col.parentGroupIds.length - 1] : undefined,
                };
                const splitFirst = getGroupSplit({
                    col,
                    stickyCount: stickyColumnsFirst,
                    side: 'first',
                    totalColumns,
                });
                const splitLast = getGroupSplit({
                    col,
                    stickyCount: stickyColumnsLast,
                    side: 'last',
                    totalColumns,
                });
                const split = splitFirst.stickyColspan > 0 ? splitFirst : splitLast;
                const isSplit = split.stickyColspan > 0;
                if (isSplit) {
                    // Group is bisected by the sticky boundary — render two <th> elements.
                    // Both halves get resizers. Each resizes its own rightmost column child.
                    const isSplitFirst = splitFirst.stickyColspan > 0;
                    // Left half is sticky for 'first', non-sticky for 'last'
                    const leftColspan = isSplitFirst ? split.stickyColspan : split.staticColspan;
                    const leftColIndex = col.colIndex;
                    const leftGroupId = isSplitFirst ? col.id : `${col.id}__split`;
                    const leftChildIds = childIds.slice(0, leftColspan);
                    // Right half is non-sticky for 'first', sticky for 'last'
                    const rightColspan = isSplitFirst ? split.staticColspan : split.stickyColspan;
                    const rightColIndex = col.colIndex + leftColspan;
                    const rightGroupId = isSplitFirst ? `${col.id}__split` : col.id;
                    const rightChildIds = childIds.slice(leftColspan);
                    return (React.createElement(React.Fragment, { key: col.id },
                        React.createElement(TableGroupHeaderCell, { ...sharedGroupCellProps, colspan: leftColspan, colIndex: selectionType ? leftColIndex + 1 : leftColIndex, groupId: leftGroupId, resizableStyle: undefined, updateGroupWidth: (_, newWidth) => {
                                handleSplitGroupResize(leftChildIds, newWidth);
                            }, childColumnIds: leftChildIds, firstChildColumnId: leftChildIds[0], lastChildColumnId: leftChildIds[leftChildIds.length - 1], cellRef: isSplitFirst ? node => setCell(sticky, col.id, node) : () => { }, isLast: false, stickyColumnId: isSplitFirst ? childIds[0] : undefined, stickyBoundaryColumnId: isSplitFirst ? leftChildIds[leftChildIds.length - 1] : undefined }),
                        React.createElement(TableGroupHeaderCell, { ...sharedGroupCellProps, colspan: rightColspan, colIndex: selectionType ? rightColIndex + 1 : rightColIndex, groupId: rightGroupId, resizableStyle: getColumnStyles(sticky, col.id), updateGroupWidth: (_, newWidth) => {
                                handleSplitGroupResize(rightChildIds, newWidth);
                            }, childColumnIds: rightChildIds, firstChildColumnId: rightChildIds[0], lastChildColumnId: rightChildIds[rightChildIds.length - 1], cellRef: !isSplitFirst ? node => setCell(sticky, col.id, node) : () => { }, resizerRoleDescription: resizerRoleDescription, resizerTooltipText: resizerTooltipText, isLast: rightColIndex + rightColspan === totalColumns, stickyColumnId: !isSplitFirst ? childIds[childIds.length - 1] : undefined })));
                }
                // Determine if the entire group is sticky (all children on one side)
                const isFullyStickyFirst = stickyColumnsFirst > 0 && col.colIndex + col.colSpan - 1 < stickyColumnsFirst;
                const isFullyStickyLast = stickyColumnsLast > 0 && col.colIndex >= columnDefinitions.length - stickyColumnsLast;
                const fullyStickyColumnId = isFullyStickyFirst
                    ? childIds[0]
                    : isFullyStickyLast
                        ? childIds[childIds.length - 1]
                        : undefined;
                // When the group's last child is the sticky-first boundary, the group
                // needs the shadow from that child (but offset from the first child).
                const isAtStickyFirstBoundary = isFullyStickyFirst && col.colIndex + col.colSpan - 1 === stickyColumnsFirst - 1;
                const isAtStickyLastBoundary = isFullyStickyLast && col.colIndex === columnDefinitions.length - stickyColumnsLast;
                const fullyStickyBoundaryColumnId = isAtStickyFirstBoundary
                    ? childIds[childIds.length - 1]
                    : isAtStickyLastBoundary
                        ? childIds[0]
                        : undefined;
                return (React.createElement(TableGroupHeaderCell, { ...sharedGroupCellProps, key: col.id, colspan: col.colSpan, colIndex: selectionType ? col.colIndex + 1 : col.colIndex, groupId: col.id, resizableStyle: getColumnStyles(sticky, col.id), updateGroupWidth: (groupId, newWidth) => {
                        updateGroup(groupId, newWidth);
                    }, childColumnIds: childIds, firstChildColumnId: childIds[0], lastChildColumnId: childIds[childIds.length - 1], cellRef: node => setCell(sticky, col.id, node), resizerRoleDescription: resizerRoleDescription, resizerTooltipText: resizerTooltipText, isLast: col.colIndex + col.colSpan === totalColumns, stickyColumnId: fullyStickyColumnId, stickyBoundaryColumnId: fullyStickyBoundaryColumnId }));
            }
            else {
                // Regular column cell
                const column = col.columnDefinition;
                const columnId = col.id;
                const colIndex = col.colIndex;
                return (React.createElement(TableHeaderCell, { ...commonCellProps, key: columnId, tabIndex: sticky ? -1 : 0, focusedComponent: focusedComponent, column: column, activeSortingColumn: sortingColumn, sortingDescending: sortingDescending, sortingDisabled: sortingDisabled, wrapLines: wrapLines, colIndex: selectionType ? colIndex + 1 : colIndex, columnId: columnId, updateColumn: updateColumn, onResizeFinish: () => onResizeFinish(columnWidths), resizableColumns: resizableColumns, resizableStyle: getColumnStyles(sticky, columnId), onClick: detail => {
                        setLastUserAction('sorting');
                        fireNonCancelableEvent(onSortingChange, detail);
                    }, isEditable: !!column.editConfig, cellRef: node => {
                        setCell(sticky, columnId, node);
                    }, tableRole: tableRole, resizerRoleDescription: resizerRoleDescription, resizerTooltipText: resizerTooltipText, isExpandable: colIndex === 0 && isExpandable, hasDynamicContent: hidden && !resizableColumns && column.hasDynamicContent, colSpan: col.colSpan, rowSpan: col.rowSpan, isLastChildOfGroup: isLastChildOfGroup, isLast: col.colIndex + col.colSpan === totalColumns, columnGroupId: col.parentGroupIds.length > 0 ? col.parentGroupIds[col.parentGroupIds.length - 1] : undefined }));
            }
        }))))));
});
export default Thead;
//# sourceMappingURL=thead.js.map