/**
 * 行选择插件
 *
 * 作为行选择的**单一来源**，提供全部选择能力：
 * - 单选 / 多选
 * - 全选 / 半选态
 * - 跨页保留选中
 * - 事件总线通知（ROW_SELECT / CELL_CLEAR）
 *
 * 数据源口径统一为当前**可见数据**（筛选后），由调用方通过
 * pipeline.setContext('visibleData', ...) 预注入。
 */
import { event as eventBus } from '@ice/stark-data';
import { isSameRowKey, safeGetRowKey } from '../../../../../../../cn-ai-table/view/utils/primary-key';
export function rowSelectionPlugin(options) {
    return (pipeline) => {
        const { enabled, selectionType, selectedKeys, primaryKey, dataSource, setSelectKeys, disabledRowKeys, eventNames, } = options;
        if (!enabled) {
            return pipeline;
        }
        // ---------- 派生状态 ----------
        const selectableRowKeys = dataSource
            .filter((record, index) => {
            const recordKey = safeGetRowKey(record, primaryKey, index);
            for (const key of disabledRowKeys) {
                if (isSameRowKey(key, recordKey))
                    return false;
            }
            return true;
        })
            .map((record, index) => safeGetRowKey(record, primaryKey, index));
        let selectAllState = { checked: false, indeterminate: false };
        if (selectableRowKeys.length > 0) {
            const selectedCount = selectableRowKeys.filter((key) => selectedKeys.some((sk) => isSameRowKey(sk, key))).length;
            const allSelected = selectedCount === selectableRowKeys.length;
            selectAllState = {
                checked: allSelected,
                indeterminate: selectedCount > 0 && !allSelected,
            };
        }
        // ---------- Handlers ----------
        const handlers = {
            handleRowSelectChange: (rowId, selected) => {
                if (!setSelectKeys)
                    return;
                let newSelectedKeys;
                if (selectionType === 'single') {
                    newSelectedKeys = selected ? [rowId] : [];
                }
                else {
                    newSelectedKeys = selected
                        ? [...selectedKeys, rowId]
                        : selectedKeys.filter((key) => !isSameRowKey(key, rowId));
                }
                const selectedRows = dataSource.filter((row, idx) => newSelectedKeys.some((key) => isSameRowKey(key, safeGetRowKey(row, primaryKey, idx))));
                setSelectKeys(newSelectedKeys, selectedRows);
                if (newSelectedKeys.length > 0) {
                    eventBus.emit(eventNames.ROW_SELECT, {
                        type: 'row',
                        selectedRowKeys: newSelectedKeys,
                        selectedRows,
                    });
                }
                else {
                    eventBus.emit(eventNames.CELL_CLEAR);
                }
            },
            isRowSelected: (rowId) => {
                return selectedKeys.some((key) => isSameRowKey(key, rowId));
            },
            isRowDisabled: (record, index) => {
                const recordKey = safeGetRowKey(record, primaryKey, index);
                for (const key of disabledRowKeys) {
                    if (isSameRowKey(key, recordKey))
                        return true;
                }
                return false;
            },
            selectableRowKeys,
            selectAllState,
            handleSelectAll: (checked) => {
                if (!setSelectKeys)
                    return;
                const currentPageKeys = dataSource.map((r, idx) => safeGetRowKey(r, primaryKey, idx));
                const isInCurrentPage = (key) => currentPageKeys.some((pk) => isSameRowKey(pk, key));
                if (checked) {
                    const crossPage = selectedKeys.filter((key) => !isInCurrentPage(key));
                    const merged = [...crossPage, ...selectableRowKeys];
                    const unique = [];
                    for (const key of merged) {
                        if (!unique.some((k) => isSameRowKey(k, key))) {
                            unique.push(key);
                        }
                    }
                    const selectedRows = dataSource.filter((r, idx) => unique.some((key) => isSameRowKey(key, safeGetRowKey(r, primaryKey, idx))));
                    setSelectKeys(unique, selectedRows);
                    eventBus.emit(eventNames.ROW_SELECT, {
                        type: 'row',
                        selectedRowKeys: unique,
                        selectedRows,
                    });
                }
                else {
                    const crossPage = selectedKeys.filter((key) => !isInCurrentPage(key));
                    setSelectKeys(crossPage, []);
                    if (crossPage.length > 0) {
                        eventBus.emit(eventNames.ROW_SELECT, {
                            type: 'row',
                            selectedRowKeys: crossPage,
                            selectedRows: [],
                        });
                    }
                    else {
                        eventBus.emit(eventNames.CELL_CLEAR);
                    }
                }
            },
            handleClearSelection: () => {
                if (!setSelectKeys)
                    return;
                setSelectKeys([], []);
                eventBus.emit(eventNames.CELL_CLEAR);
            },
        };
        pipeline.setContext('rowSelectionHandlers', handlers);
        pipeline.setConfig({
            rowSelection: {
                enabled,
                selectionType,
                selectedKeys,
                primaryKey,
                dataSource,
            },
        });
        return pipeline;
    };
}
