import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import react, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { RecursionField, action, observer, spliceArrayState, uid, useField, useFieldSchema } from "@tachybase/schema";
import { isPortalInBody } from "@tego/client";
import { CopyOutlined, DeleteOutlined, MenuOutlined } from "@ant-design/icons";
import { SortableContext, useSortable } from "@dnd-kit/sortable";
import { useMemoizedFn } from "ahooks";
import { Table } from "antd";
import classnames from "classnames";
import lodash, { each } from "lodash";
import { useTranslation } from "react-i18next";
import { useToken } from "../__builtins__/index.mjs";
import { DndContext, useDesignable, useTableSize } from "../../index.mjs";
import { RecordIndexProvider, RecordProvider, useACLFieldWhitelist, useCollection, useCollectionParentRecordData, useCollection_deprecated, useSchemaInitializerRender, useTableBlockContext, useTableSelectorContext } from "../../../index.mjs";
import { withDynamicSchemaProps } from "../../../application/hoc/withDynamicSchemaProps.mjs";
import { isNewRecord, markRecordAsNew } from "../../../data-source/collection-record/isNewRecord.mjs";
import { DeclareVariable } from "../../../modules/variable/DeclareVariable.mjs";
import { SubFormProvider } from "../association-field/hooks.mjs";
import { withAutoQuickJumper } from "../pagination/utils.mjs";
import { ColumnFieldProvider } from "./components/ColumnFieldProvider.mjs";
import { useStyles } from "./Table.styles.mjs";
import { extractIndex, isCollectionFieldComponent, isColumnComponent } from "./utils.mjs";
const useArrayField = (props)=>{
    const field = useField();
    return props.field || field;
};
const useTableColumns = (props)=>{
    var _field_value_slice_filter, _field_value_slice, _field_value_slice1, _field_value, _schema_reduceProperties;
    const { t } = useTranslation();
    const { styles } = useStyles();
    const field = useArrayField(props);
    const schema = useFieldSchema();
    const { schemaInWhitelist } = useACLFieldWhitelist();
    const { designable } = useDesignable();
    const { exists, render } = useSchemaInitializerRender(schema['x-initializer'], schema['x-initializer-props']);
    const parentRecordData = useCollectionParentRecordData();
    const collection = useCollection();
    const dataSource = (null == field ? void 0 : null == (_field_value = field.value) ? void 0 : null == (_field_value_slice1 = _field_value.slice) ? void 0 : null == (_field_value_slice = _field_value_slice1.call(_field_value)) ? void 0 : null == (_field_value_slice_filter = _field_value_slice.filter) ? void 0 : _field_value_slice_filter.call(_field_value_slice, Boolean)) || [];
    const columns = null == (_schema_reduceProperties = schema.reduceProperties((buf, s)=>{
        if (isColumnComponent(s) && schemaInWhitelist(Object.values(s.properties || {}).pop())) return buf.concat([
            s
        ]);
        return buf;
    }, [])) ? void 0 : _schema_reduceProperties.map((s)=>{
        var _s_xcomponentprops;
        const collectionFields = s.reduceProperties((buf, s)=>{
            if (isCollectionFieldComponent(s)) return buf.concat([
                s
            ]);
        }, []);
        const dataIndex = (null == collectionFields ? void 0 : collectionFields.length) > 0 ? collectionFields[0].name : s.name;
        return {
            title: /*#__PURE__*/ jsx(RecursionField, {
                name: s.name,
                schema: s,
                onlyRenderSelf: true
            }),
            dataIndex,
            key: s.name,
            sorter: null == (_s_xcomponentprops = s['x-component-props']) ? void 0 : _s_xcomponentprops['sorter'],
            width: 200,
            ...s['x-component-props'],
            render: (v, record)=>{
                var _field_value;
                const index = null == (_field_value = field.value) ? void 0 : _field_value.indexOf(record);
                return /*#__PURE__*/ jsx(DeclareVariable, {
                    name: "$nPopupRecord",
                    title: t('Current popup record'),
                    value: record,
                    collection: collection,
                    children: /*#__PURE__*/ jsx(SubFormProvider, {
                        value: {
                            value: record,
                            collection
                        },
                        children: /*#__PURE__*/ jsx(RecordIndexProvider, {
                            index: record.__index || index,
                            children: /*#__PURE__*/ jsx(RecordProvider, {
                                isNew: isNewRecord(record),
                                record: record,
                                parent: parentRecordData,
                                children: /*#__PURE__*/ jsx(ColumnFieldProvider, {
                                    schema: s,
                                    basePath: field.address.concat(record.__index || index),
                                    children: /*#__PURE__*/ jsx("span", {
                                        role: "button",
                                        className: styles.toolbar,
                                        children: /*#__PURE__*/ jsx(RecursionField, {
                                            basePath: field.address.concat(record.__index || index),
                                            schema: s,
                                            onlyRenderProperties: true
                                        })
                                    })
                                })
                            })
                        })
                    })
                });
            }
        };
    });
    if (!exists) return columns;
    const tableColumns = columns.concat({
        title: render(),
        fixed: 'right',
        dataIndex: 'TABLE_COLUMN_INITIALIZER',
        key: 'TABLE_COLUMN_INITIALIZER',
        render: designable ? ()=>/*#__PURE__*/ jsx("span", {}) : null
    });
    if (props.showDel) tableColumns.push({
        title: '',
        key: 'delete',
        width: 60,
        align: 'center',
        fixed: 'right',
        render: (v, record, index)=>/*#__PURE__*/ jsxs(Fragment, {
                children: [
                    /*#__PURE__*/ jsx(CopyOutlined, {
                        style: {
                            cursor: 'pointer',
                            marginRight: '10px'
                        },
                        onClick: ()=>{
                            action(()=>{
                                if (!Array.isArray(field.value)) field.value = [];
                                spliceArrayState(field, {
                                    startIndex: index + 1,
                                    insertCount: 1
                                });
                                field.value.splice(index + 1, 0, markRecordAsNew(lodash.cloneDeep(record)));
                                each(field.form.fields, (targetField, key)=>{
                                    if (!targetField) delete field.form.fields[key];
                                });
                                return field.onInput(field.value);
                            });
                        }
                    }),
                    /*#__PURE__*/ jsx(DeleteOutlined, {
                        style: {
                            cursor: 'pointer'
                        },
                        onClick: ()=>{
                            action(()=>{
                                var _field_initialValue;
                                const index = dataSource.indexOf(record);
                                spliceArrayState(field, {
                                    startIndex: index,
                                    deleteCount: 1
                                });
                                field.value.splice(index, 1);
                                null == (_field_initialValue = field.initialValue) || _field_initialValue.splice(index, 1);
                                props.setFieldValue([
                                    ...field.value
                                ]);
                                return field.onInput(field.value);
                            });
                        }
                    })
                ]
            })
    });
    return [
        ...tableColumns.filter((column)=>'left' === column.fixed),
        ...tableColumns.filter((column)=>!column.fixed || 'left' !== column.fixed && 'right' !== column.fixed),
        ...tableColumns.filter((column)=>'right' === column.fixed)
    ];
};
const SortableRow = (props)=>{
    var _props_datarowkey, _active_data_current, _over_data_current_sortable, _over_data_current;
    const { styles } = useStyles();
    const id = null == (_props_datarowkey = props['data-row-key']) ? void 0 : _props_datarowkey.toString();
    const { setNodeRef, isOver, active, over } = useSortable({
        id
    });
    var _active_data_current_sortable_index, _over_data_current_sortable_index;
    const className = (null != (_active_data_current_sortable_index = null == active ? void 0 : null == (_active_data_current = active.data.current) ? void 0 : _active_data_current.sortable.index) ? _active_data_current_sortable_index : -1) > (null != (_over_data_current_sortable_index = null == over ? void 0 : null == (_over_data_current = over.data.current) ? void 0 : null == (_over_data_current_sortable = _over_data_current.sortable) ? void 0 : _over_data_current_sortable.index) ? _over_data_current_sortable_index : -1) ? styles.topActive : styles.bottomActive;
    return /*#__PURE__*/ jsx("tr", {
        ref: (null == active ? void 0 : active.id) !== id ? setNodeRef : null,
        ...props,
        className: classnames(props.className, {
            [className]: active && isOver
        })
    });
};
const SortHandle = (props)=>{
    const { id, ...otherProps } = props;
    const { listeners } = useSortable({
        id
    });
    return /*#__PURE__*/ jsx(MenuOutlined, {
        ...otherProps,
        ...listeners,
        style: {
            cursor: 'grab'
        }
    });
};
const TableIndex = (props)=>{
    const { index, ...otherProps } = props;
    return /*#__PURE__*/ jsx("div", {
        className: classnames('tb-table-index'),
        style: {
            padding: '0 8px 0 16px'
        },
        ...otherProps,
        children: index
    });
};
const pageSizeOptions = [
    5,
    10,
    20,
    50,
    100,
    200
];
const usePaginationProps = (pagination1, pagination2)=>{
    const { t } = useTranslation();
    const showTotal = useCallback((total)=>t('Total {{count}} items', {
            count: total
        }), [
        t
    ]);
    if (false === pagination2) return false;
    if (!pagination2 && false === pagination1) return false;
    const result = {
        showTotal,
        showSizeChanger: true,
        pageSizeOptions,
        ...pagination1,
        ...pagination2
    };
    return result.total ? withAutoQuickJumper(result) : false;
};
const Table_Table = withDynamicSchemaProps(observer((props)=>{
    var _schema_parent, _field_data, _field_value_slice_filter, _field_value_slice, _field_value_slice1, _field_value, _fieldSchema_parent_xdecoratorprops, _fieldSchema_parent;
    const { token } = useToken();
    const { styles } = useStyles();
    const { pagination: pagination1, useProps, ...others1 } = props;
    const { pagination: pagination2, ...others2 } = (null == useProps ? void 0 : useProps()) || {};
    const { dragSort: tableDragSort, showIndex = true, onRowSelectionChange, onChange: onTableChange, rowSelection, rowKey, required, onExpand, onClickRow, ...others } = {
        ...others1,
        ...others2
    };
    const field = useArrayField(others);
    const columns = useTableColumns(others);
    const schema = useFieldSchema();
    const collection = useCollection_deprecated();
    const isTableSelector = (null == schema ? void 0 : null == (_schema_parent = schema.parent) ? void 0 : _schema_parent['x-decorator']) === 'TableSelectorProvider';
    const ctx = isTableSelector ? useTableSelectorContext() : useTableBlockContext();
    const { expandFlag, allIncludesChildren } = ctx;
    const onRowDragEnd = useMemoizedFn(others.onRowDragEnd || (()=>{}));
    const paginationProps = usePaginationProps(pagination1, pagination2);
    const [expandedKeys, setExpandesKeys] = useState([]);
    const [selectedRowKeys, setSelectedRowKeys] = useState((null == field ? void 0 : null == (_field_data = field.data) ? void 0 : _field_data.selectedRowKeys) || []);
    const [selectedRow, setSelectedRow] = useState([]);
    const dataSource = (null == field ? void 0 : null == (_field_value = field.value) ? void 0 : null == (_field_value_slice1 = _field_value.slice) ? void 0 : null == (_field_value_slice = _field_value_slice1.call(_field_value)) ? void 0 : null == (_field_value_slice_filter = _field_value_slice.filter) ? void 0 : _field_value_slice_filter.call(_field_value_slice, Boolean)) || [];
    const isRowSelect = (null == rowSelection ? void 0 : rowSelection.type) !== 'none';
    const dragSort = tableDragSort || field.componentProps.dragSort || false;
    const defaultRowKeyMap = useRef(new Map());
    let onRow = null, highlightRow = '';
    if (onClickRow) {
        onRow = (record)=>({
                onClick: (e)=>{
                    if (isPortalInBody(e.target)) return;
                    onClickRow(record, setSelectedRow, selectedRow);
                }
            });
        highlightRow = styles.highlightRow;
    }
    useEffect(()=>{
        expandFlag ? setExpandesKeys(allIncludesChildren) : setExpandesKeys([]);
    }, [
        expandFlag,
        allIncludesChildren
    ]);
    const components = useMemo(()=>({
            header: {
                wrapper: (props)=>/*#__PURE__*/ jsx(DndContext, {
                        children: /*#__PURE__*/ jsx("thead", {
                            ...props
                        })
                    }),
                cell: (props)=>/*#__PURE__*/ jsx("th", {
                        ...props,
                        className: classnames(props.className, styles.headerCellDesigner)
                    })
            },
            body: {
                wrapper: (props)=>/*#__PURE__*/ jsx(DndContext, {
                        onDragEnd: (e)=>{
                            var _e_active_data_current_sortable, _e_active_data_current, _e_active, _e_over_data_current_sortable, _e_over_data_current, _e_over;
                            if (!e.active || !e.over) return void console.warn('move cancel');
                            const fromIndex = null == (_e_active = e.active) ? void 0 : null == (_e_active_data_current = _e_active.data.current) ? void 0 : null == (_e_active_data_current_sortable = _e_active_data_current.sortable) ? void 0 : _e_active_data_current_sortable.index;
                            const toIndex = null == (_e_over = e.over) ? void 0 : null == (_e_over_data_current = _e_over.data.current) ? void 0 : null == (_e_over_data_current_sortable = _e_over_data_current.sortable) ? void 0 : _e_over_data_current_sortable.index;
                            const from = field.value[fromIndex] || e.active;
                            const to = field.value[toIndex] || e.over;
                            field.move(fromIndex, toIndex);
                            onRowDragEnd({
                                from,
                                to
                            });
                        },
                        children: /*#__PURE__*/ jsx("tbody", {
                            ...props
                        })
                    }),
                row: (props)=>/*#__PURE__*/ jsx(SortableRow, {
                        ...props
                    }),
                cell: (props)=>/*#__PURE__*/ jsx("td", {
                        ...props,
                        className: classnames(props.className, styles.bodyCell)
                    })
            }
        }), [
        field,
        onRowDragEnd,
        dragSort
    ]);
    const defaultRowKey = (record)=>{
        if (record.key) return record.key;
        if (defaultRowKeyMap.current.has(record)) return defaultRowKeyMap.current.get(record);
        const key = uid();
        defaultRowKeyMap.current.set(record, key);
        return key;
    };
    const getRowKey = (record)=>{
        if ('string' == typeof rowKey) {
            var _record_rowKey;
            return null == (_record_rowKey = record[rowKey]) ? void 0 : _record_rowKey.toString();
        }
        var _this;
        return null == (_this = (null != rowKey ? rowKey : defaultRowKey)(record)) ? void 0 : _this.toString();
    };
    const restProps = {
        rowSelection: rowSelection ? {
            type: 'checkbox',
            selectedRowKeys: selectedRowKeys,
            onChange (selectedRowKeys, selectedRows) {
                field.data = field.data || {};
                field.data.selectedRowKeys = selectedRowKeys;
                setSelectedRowKeys(selectedRowKeys);
                null == onRowSelectionChange || onRowSelectionChange(selectedRowKeys, selectedRows);
            },
            getCheckboxProps (record) {
                return {
                    'aria-label': "checkbox"
                };
            },
            renderCell: (checked, record, index, originNode)=>{
                var _props_pagination, _props_pagination1;
                if (!dragSort && !showIndex) return originNode;
                const current = null == props ? void 0 : null == (_props_pagination = props.pagination) ? void 0 : _props_pagination.current;
                const pageSize = (null == props ? void 0 : null == (_props_pagination1 = props.pagination) ? void 0 : _props_pagination1.pageSize) || 20;
                if (current) index = index + (current - 1) * pageSize + 1;
                else index += 1;
                if (record.__index) index = extractIndex(record.__index);
                return /*#__PURE__*/ jsxs("div", {
                    role: "button",
                    "aria-label": "table-index-".concat(index),
                    className: classnames(checked ? 'checked' : null, styles.rowSelect, {
                        [styles.rowSelectHover]: isRowSelect
                    }),
                    children: [
                        /*#__PURE__*/ jsxs("div", {
                            className: classnames(checked ? 'checked' : null, styles.cellChecked),
                            children: [
                                dragSort && /*#__PURE__*/ jsx(SortHandle, {
                                    id: getRowKey(record)
                                }),
                                showIndex && /*#__PURE__*/ jsx(TableIndex, {
                                    index: index
                                })
                            ]
                        }),
                        isRowSelect && /*#__PURE__*/ jsx("div", {
                            className: classnames('tb-origin-node', checked ? 'checked' : null, styles.cellCheckedNode),
                            children: originNode
                        })
                    ]
                });
            },
            ...rowSelection
        } : void 0
    };
    const SortableWrapper = useCallback((param)=>{
        let { children } = param;
        var _field_value_map, _field_value;
        return dragSort ? /*#__PURE__*/ react.createElement(SortableContext, {
            items: (null == (_field_value = field.value) ? void 0 : null == (_field_value_map = _field_value.map) ? void 0 : _field_value_map.call(_field_value, getRowKey)) || []
        }, children) : /*#__PURE__*/ react.createElement(react.Fragment, {}, children);
    }, [
        field,
        dragSort
    ]);
    const fieldSchema = useFieldSchema();
    const fixedBlock = null == fieldSchema ? void 0 : null == (_fieldSchema_parent = fieldSchema.parent) ? void 0 : null == (_fieldSchema_parent_xdecoratorprops = _fieldSchema_parent['x-decorator-props']) ? void 0 : _fieldSchema_parent_xdecoratorprops.fixedBlock;
    const { height: tableHeight, tableSizeRefCallback } = useTableSize();
    const scroll = useMemo(()=>fixedBlock ? {
            x: 'max-content',
            y: tableHeight
        } : {
            x: 'max-content'
        }, [
        fixedBlock,
        tableHeight
    ]);
    return /*#__PURE__*/ jsxs("div", {
        className: styles.container,
        children: [
            /*#__PURE__*/ jsx(SortableWrapper, {
                children: /*#__PURE__*/ jsx(Table, {
                    ref: tableSizeRefCallback,
                    rowKey: null != rowKey ? rowKey : defaultRowKey,
                    dataSource: dataSource,
                    tableLayout: "auto",
                    ...others,
                    ...restProps,
                    pagination: paginationProps,
                    components: components,
                    onChange: (pagination, filters, sorter, extra)=>{
                        null == onTableChange || onTableChange(pagination, filters, sorter, extra);
                    },
                    onRow: onRow,
                    rowClassName: (record)=>selectedRow.includes(record[rowKey]) ? highlightRow : '',
                    scroll: scroll,
                    columns: columns,
                    expandable: {
                        onExpand: (flag, record)=>{
                            const newKeys = flag ? [
                                ...expandedKeys,
                                record[collection.getPrimaryKey()]
                            ] : expandedKeys.filter((i)=>record[collection.getPrimaryKey()] !== i);
                            setExpandesKeys(newKeys);
                            null == onExpand || onExpand(flag, record);
                        },
                        expandedRowKeys: expandedKeys
                    }
                })
            }),
            field.errors.length > 0 && /*#__PURE__*/ jsx("div", {
                className: "ant-formily-item-error-help ant-formily-item-help ant-formily-item-help-enter ant-formily-item-help-enter-active",
                children: field.errors.map((error)=>error.messages.map((message)=>/*#__PURE__*/ jsx("div", {
                            children: message
                        }, message)))
            })
        ]
    });
}), {
    displayName: 'Table'
});
export { Table_Table as Table };
