import { ProTable } from "@ant-design/pro-components";
import dayjs from "dayjs";
import { useEffect, useMemo, useState } from "react";
import { throttle } from "throttle-debounce";
import { useAntdResizableHeader } from "use-antd-resizable-header";
import { getDataType, getIndexColumn } from "../../utils";
import "use-antd-resizable-header/dist/style.css";
import "./index.less";

const CLEANUP_INTERVAL_DAYS = 10; // 清理间隔天数
const LAST_CLEANUP_KEY = "tableLocalStorageLastCleanup"; // 最后清理时间存储key

// 清理本地存储中特定后缀的key
function cleanupTableLocalStorage() {
  const now = dayjs();
  const lastCleanupStr = localStorage.getItem(LAST_CLEANUP_KEY);
  const lastCleanup = lastCleanupStr ? dayjs(lastCleanupStr) : null;

  // 如果没有上次清理时间或距离上次清理已超过10天
  if (!lastCleanup || now.diff(lastCleanup, "day") >= CLEANUP_INTERVAL_DAYS) {
    // 查找并清理符合条件的key
    const keysToRemove = [];
    for (let i = 0; i < localStorage.length; i++) {
      const key = localStorage.key(i);
      if (key && (key.endsWith("#columnState")
        || key.endsWith("#size")
        || key.endsWith("#resizable"))) {
        keysToRemove.push(key);
      }
    }

    // 删除匹配的key
    keysToRemove.forEach((key) => {
      localStorage.removeItem(key);
    });

    // 更新最后清理时间
    localStorage.setItem(LAST_CLEANUP_KEY, now.toISOString());
  }
}

function getPersistenceKey(index) {
  const basename = process.env?.app?.basename;
  const pathname = decodeURIComponent(window.location.pathname);
  const insertIndex = getDataType(index) === "Undefined" ? "" : `#{${index}}`;

  return {
    size: `${basename}#${pathname}${insertIndex}#size`,
    resizable: `${basename}#${pathname}${insertIndex}#resizable`,
    columnState: `${basename}#${pathname}${insertIndex}#columnState`,
  };
}

function getTableSize(index) {
  return window.localStorage.getItem(getPersistenceKey(index).size);
}

function setTableSize(value, index) {
  return window.localStorage.setItem(getPersistenceKey(index).size, value);
}

function Table(props) {
  const {
    columns = [],
    showIndexColumn = true,
    ellipsis = true,
    align = "center",
    indexColumnFixed = "left",
    rowKey = "id",
    storeIndex,
    disabledResizer = false,
    height,
    ...restProps
  } = props;

  const antPrefix = process.env.app.antd["ant-prefix"];
  const prefix = antPrefix || "ant";
  const baseCls = `.${prefix}-table`;
  const tableCls = `${baseCls}-wrapper`;
  const tableBodyCls = `${baseCls}-body`;

  const [size, setSize] = useState(getTableSize(storeIndex) || "default");
  const [tableHeight, setTableHeight] = useState(0);

  const persistenceKey = getPersistenceKey(storeIndex);
  const enabledResizer = !disabledResizer;

  const {
    components,
    resizableColumns,
    tableWidth,
    resetColumns,
  } = useAntdResizableHeader({
    columns,
    columnsState: {
      persistenceKey: persistenceKey.resizable,
      persistenceType: "localStorage",
    },
  });

  // 计算高度
  const calcTableHeight = throttle(50, () => {
    try {
      // table元素
      const tableEl = document.querySelector(tableCls);
      // table-body元素
      const tableBodyEl = document.querySelector(tableBodyCls);

      // 获取页脚元素高度
      const footerEl = document.querySelector(".page-layout-footer");
      const footerHeight = footerEl ? footerEl.offsetHeight : 0;

      if (tableBodyEl && tableEl) {
        // 获取table元素的矩形数据
        const tableRect = tableEl.getBoundingClientRect();
        // 获取table-body元素的矩形数据
        const tableBodyRect = tableBodyEl.getBoundingClientRect();
        // 获取底部的高度差
        const bottomHeight = tableRect.bottom - tableBodyRect.bottom;
        // 计算最终值，减去页脚高度
        setTableHeight(innerHeight - tableBodyRect.top - bottomHeight - (window.__IN_BASE__ ? 38 : 22) - footerHeight);
      }
    }
    catch (e) {
      window.console.error(e);
    }
  });

  useEffect(() => {
    let mutationObserver, resizeObserver;
    if (enabledResizer) {
      // 监听-DOM树
      mutationObserver = new MutationObserver(mutations => mutations.forEach(() => calcTableHeight()));
      // 监听-缩放
      resizeObserver = new ResizeObserver(entries => entries.forEach(() => calcTableHeight()));

      // 初始化首次计算
      setTimeout(() => calcTableHeight(), 500);

      // 执行-监听-缩放
      resizeObserver.observe(document.body);
      // 执行-监听-DOM树是否发生变化
      mutationObserver.observe(document.body, {
        subtree: true,
        childList: true,
      });
    }

    cleanupTableLocalStorage();

    return () => {
      if (mutationObserver && resizeObserver && enabledResizer) {
        resizeObserver.unobserve(document.body);
        mutationObserver.disconnect(document.body);
      }
    };
  }, []);

  useEffect(() => {
    setTableSize(size, storeIndex);
  }, [size]);

  const settingColumns = () => {
    const columnsCopy = [...resizableColumns];
    showIndexColumn && columnsCopy.unshift({ ...getIndexColumn(props.pagination), fixed: indexColumnFixed });

    const setAlign = column => ({
      align,
      ellipsis,
      ...column,
      ...(column.children ? { children: column.children.map(setAlign) } : {}),
    });

    return columnsCopy.map(setAlign);
  };

  const processedColumns = useMemo(() => settingColumns(), [resizableColumns, showIndexColumn, align, ellipsis, indexColumnFixed, props.pagination]);

  return (
    <div className="table-layout card-layout">
      <ProTable
        ghost={true}
        search={false}
        scroll={{
          x: tableWidth,
          y: height || (enabledResizer ? tableHeight : undefined),
        }}
        options={{
          reload: false,
          fullScreen: true,
          setting: {
            checkedReset: true,
            extra: (
              <a
                className={`${antPrefix}-pro-table-column-setting-action-rest-button`}
                onClick={resetColumns}
              >
                重置列宽
              </a>
            ),
          },
        }}
        components={components}
        columnsState={{
          persistenceKey: persistenceKey.columnState,
          persistenceType: "localStorage",
        }}
        onSizeChange={setSize}
        columns={processedColumns}
        bordered
        size="small"
        rowKey={rowKey}
        {...restProps}
      />
    </div>
  );
}

Table.displayName = "Table";

export default Table;
