import React, {
  useRef,
  useState,
  useMemo,
  useCallback,
  useEffect,
} from "react";
import classNames from "classnames";
import { TableProps } from "./TableProps";
import { TableHead } from "./TableHead";
import { TableBody } from "./TableBody";
import { useMiddleware } from "./util/use-middleware";
import { createRocket } from "../_util/create-rocket";
import { useConfig } from "../_util/config-context";
import { TableContextValue, TableContext } from "./TableContext";
import { forwardRefWithStatics } from "../_util/forward-ref-with-statics";
import * as addons from "./addons";
import { mergeEventProps } from "../_util/merge-event-props";

export const Table = forwardRefWithStatics(
  function Table<T>(props: TableProps<T>, ref: React.Ref<HTMLDivElement>) {
    const { classPrefix } = useConfig();
    const [scrollStatus, setScrollStatus] = useState<
      TableContextValue["scrollStatus"]
    >("left");
    const [columnsWidths, setColumnsWidths] = useState<number[]>([]);
    const { addons = [], bordered, compact, verticalTop } = props;

    const headRef = useRef<HTMLDivElement>(null);
    const bodyRef = useRef<HTMLDivElement>(null);

    // 执行 addon props middleware
    // eslint-disable-next-line no-param-reassign
    props = useMiddleware(addons, "onInjectProps")(props);

    const hasFixedColumn = useMemo(
      () => props.columns.find(column => !!column.fixed),
      [props.columns]
    );

    // 同步 body 和 header 滚动位置
    const handleScroll = useCallback(() => {
      // 设置水平滚动状态（固定列样式）
      if (bodyRef.current && hasFixedColumn) {
        const { scrollWidth, clientWidth, scrollLeft } = bodyRef.current;
        const atLeft = scrollLeft === 0;
        const atRight = scrollWidth <= Math.ceil(clientWidth + scrollLeft);
        if (atLeft && atRight) {
          setScrollStatus("no-scroll");
        } else if (atLeft) {
          setScrollStatus("left");
        } else if (atRight) {
          setScrollStatus("right");
        } else {
          setScrollStatus("scrolling");
        }
      }
      if (headRef.current && bodyRef.current) {
        headRef.current.scrollLeft = bodyRef.current.scrollLeft;
      }
    }, [hasFixedColumn]);

    useEffect(() => {
      handleScroll();
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [columnsWidths]);

    const renderTable = useMiddleware(
      addons,
      "onInjectTable"
    )(({ className, style, ...props }) => (
      <div
        ref={ref}
        className={classNames(`${classPrefix}-table`, className, {
          [`${classPrefix}-table--compact`]: compact,
          [`${classPrefix}-table--bordered`]: bordered,
          [`${classPrefix}-table--allbordered`]: bordered === "all",
          [`${classPrefix}-table--verticaltop`]: verticalTop,
        })}
        style={style}
        {...mergeEventProps(props)}
      >
        <TableContext.Provider value={{ scrollStatus, columnsWidths }}>
          <TableHead ref={headRef} {...props} onResize={setColumnsWidths} />
          <TableBody
            ref={bodyRef}
            onScrollCapture={handleScroll}
            onResize={setColumnsWidths}
            {...props}
          />
        </TableContext.Provider>
      </div>
    ));

    return renderTable(props);
  },
  {
    addons,
    ActionPanel: createRocket(
      "ActionPanel",
      "div.@{prefix}-table__action-panel"
    ),
  } as any
) as (<T>(
  props: TableProps<T> & { ref?: React.Ref<HTMLDivElement> }
) => React.ReactElement) & {
  addons: typeof addons;
  ActionPanel: ReturnType<typeof createRocket>;
  displayName: string;
};

Table.displayName = "Table";
