import React, { useEffect, useMemo, useRef, useState } from "react";
import "antd/dist/antd.css";
import "./index.less";
import { Spin, Table, Tag } from "antd";
import type { TableProps } from "antd";
import classNames from "classnames";
import ResizeObserver from "rc-resize-observer";
import type { ColumnsType } from "antd/es/table";
import { VariableSizeGrid as Grid } from "react-window";
import { Resizable } from "react-resizable";

const ResizableHeader = (props: { [x: string]: any; onResize: any; width: any }) => {
    const { onResize, width, ...restProps } = props;
    if (!width) {
        return <th {...restProps} />
    }
    return <Resizable width={width} height={0} onResize={onResize} draggableOpts={{ enableUserSelectHack: false }}>
        <th {...restProps} />
    </Resizable>
}

const getColumns = <RecordType extends object>(columns: ColumnsType<RecordType> | undefined) => {
    return columns!.map((column) => {
        if (column.width)  return column;
        return { ...column, width: 100 };
    })
}

interface Props<RecordType extends object> extends TableProps<RecordType> {
    rowHeight: number
    loading?: boolean,
    total?: number,
    current?: number,
    pageSize?: number,
    defaultPageSize?: number
    pageChange?: (page: number, pageSize?: number) => void,
    sizeChange?: (current: number, size?: number) => void,
    isShowTotal?: boolean
    handelResize?: (columns: any) => void//当表头被拖动改变宽度时回调设置对应的本地保存
}

const VTable = <RecordType extends object>(props: Props<RecordType>) => {

    const {
        columns,
        scroll,
        className,
        rowHeight,
        loading = false,
        total = 0,
        current,
        pageSize,
        defaultPageSize,
        pageChange,
        sizeChange,
        isShowTotal = true,
        handelResize
    } = props;
    const [tableWidth, setTableWidth] = useState(0);
    let bodyWidth = document.body.clientWidth < 415
    const [mergedColumns, setMergedColumns] = useState<ColumnsType<RecordType>>(getColumns(columns))

    useEffect(() => setMergedColumns(() => getColumns(columns)), [columns])

    const handleResize = (index: any) => (e: any, { size }: any) => {
        const nextColumns = [...mergedColumns]
        nextColumns[index] = {
            ...nextColumns[index],
            width: size.width
        }
        setMergedColumns(nextColumns)
        handelResize?.(nextColumns)
    }
    const columnsRef = useRef<any[]>([])
    columnsRef.current = (mergedColumns || []).map((col: any, index: any) => ({
        ...col,
        onHeaderCell: (column: any) => ({
            width: column.width,
            onResize: handleResize(index)
        })
    }))
    console.log('---->', columnsRef.current)

    const gridRef = useRef<any>();
    const [connectObject] = useState<any>(() => {
        const obj = {};
        Object.defineProperty(obj, "scrollLeft", {
            get: () => {
                if (gridRef.current) {
                    return gridRef.current?.state?.scrollLeft;
                }
                return null;
            },
            set: (scrollLeft: number) => {
                if (gridRef.current) {
                    gridRef.current.scrollTo({ scrollLeft });
                }
            }
        });

        return obj;
    });

    const resetVirtualGrid = () => {
        gridRef.current?.resetAfterIndices({
            columnIndex: 0,
            shouldForceUpdate: true
        });
    };

    useEffect(() => resetVirtualGrid, [tableWidth]);

    const renderVirtualList = (rawData: object[], { scrollbarSize, ref, onScroll }: any) => {
        ref.current = connectObject;
        const totalHeight = rawData.length * rowHeight + 6;
        return (
            <Grid
                ref={gridRef}
                className="virtual-grid"
                columnCount={columnsRef.current.length}
                columnWidth={(index: number) => {
                    const { width } = columnsRef.current[index];
                    return totalHeight > (scroll!.y! as any) && index === columnsRef.current.length - 1
                        ? (width as number) - scrollbarSize - 1
                        : (width as number);
                }}
                height={scroll!.y as number > totalHeight ? totalHeight : scroll!.y as number}
                rowCount={rawData.length}
                rowHeight={() => rowHeight}
                width={tableWidth}
                onScroll={({ scrollLeft }: { scrollLeft: number }) => {
                    onScroll({ scrollLeft });
                }}
            >
                {({ columnIndex, rowIndex, style }: { columnIndex: number; rowIndex: number; style: React.CSSProperties; }) => {
                    const { render, dataIndex, align } = (columnsRef.current as any)[columnIndex];
                    // if ((columnsRef.current as any)[columnIndex].title === 'C') {
                    //     console.log('style--->', style)
                    // }
                    const myStyle = {
                        justifyContent:
                            align === "left"
                                ? "flex-start"
                                : align === "right"
                                    ? "flex-end"
                                    : align,
                        ...style
                    }
                    return (
                        <div
                            className={classNames("virtual-table-cell", {
                                "virtual-table-cell-last": columnIndex === columnsRef.current.length - 1
                            })}
                            style={myStyle}
                        >
                            {render
                                ? render(
                                    (rawData[rowIndex] as any)[dataIndex],
                                    rawData[rowIndex] as any
                                )
                                : (rawData[rowIndex] as any)[dataIndex]}
                        </div>
                    );
                }}
            </Grid>
        );
    };

    const a = useMemo(() => {
        return <div>22</div>
    }, [columnsRef.current])

    return <Spin style={{ width: '100%' }} spinning={loading}>
        <ResizeObserver
            onResize={({ width }) => {
                setTableWidth(width);
            }}
        >
            <Table
                {...props}
                bordered
                className={`virtual-table all_table ${className ? className : ''}`}
                columns={columnsRef.current}
                pagination={{
                    defaultCurrent: 1,
                    total: total || 0,
                    current: current || 1,
                    pageSize: pageSize || 20,
                    defaultPageSize: defaultPageSize || 20,
                    pageSizeOptions: ['10', '20', '30', '40', '50', '60', '70', '80', '90', '100'],
                    size: "small",
                    showTotal: (total) => isShowTotal ? <Tag color="cyan">总共{total}数据</Tag> : null,
                    showSizeChanger: true,
                    onChange: pageChange,
                    onShowSizeChange: sizeChange,
                    showLessItems: true,
                    simple: bodyWidth ? true : false,//开启简单分页
                }}
                components={{
                    header: {
                        cell: ResizableHeader
                    },
                    body: renderVirtualList as any
                }}
            />
        </ResizeObserver>
    </Spin>
};

// Usage
const columns: ColumnsType<any> = [
    { title: <span>YYY</span>, dataIndex: "key", width: 150, align: "center", sorter: true },
    { title: "B", dataIndex: "key" },
    { title: "C", dataIndex: "key" },
    { title: "D", dataIndex: "key" },
    { title: "E", dataIndex: "key", width: 50 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100, align: "center" },
    {
        title: "dd11",
        dataIndex: "key",
        width: 100,
        align: "center",
        render: (a) => {
            return <span>{a * 20}</span>;
        }
    },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 200 },
    { title: "F", dataIndex: "key", width: 200 },
    { title: "F", dataIndex: "key", width: 200 },
    { title: "F", dataIndex: "key", width: 200 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "key", width: 100 },
    { title: "F", dataIndex: "dd", width: 100 }
];

const data = Array.from({ length: 100 }, (_, key) => ({
    key,
    dd: "啊大大撒1111啊大大阿三打撒"
}));


interface VirtualTableProps {
    loading?: boolean,
}
const VirtualTable: React.FC<VirtualTableProps> = ({ loading }) => {

    return <VTable
        rowHeight={26}
        columns={columns}
        dataSource={data}
        scroll={{ y: 600, x: "100vw" }}
    />
};

export default VirtualTable;