import {
  type Ref,
  nextTick,
  onMounted,
  onUnmounted,
  ref,
  provide,
  onActivated,
  onDeactivated
} from 'vue';
import ResizeObserver from 'resize-observer-polyfill';
import { hasScrollbarKey } from '../utils/key';
type MyHTMLElement = HTMLElement | null;
const TABLE_LAYOUT_FIXED_CLS_NAME = 'table-layout--fixed';
const ANT_TABLE_BODY_CLS_NAME = 'ant-table-body';

// antd 是如何实现 colgroup 页面 resize 后，动态更新 width？
// antd 3.20.x 源码搜索
// ant-design-vue-3.2.20/components/vc-table/Body/MeasureCell.tsx，<VCResizeObserver />
// useProvideResize
// useInjectResize
// updateColsWidths

// 📝 解决两种场景：
// 1. 没有 fixed: 'right' 的 column，只要控制 .ant-table-header > table > colgroup > col 最后一个 col 样式显示隐藏即可
// 2. 有 fixed: 'right' 的 column，且不止一个，控制表头多个 fixed: 'right' 的 th right 减去滚动条的宽度

// TODO: 考虑 ant-table-summary 和 复杂表头？
// TODO: 考虑空数据场景？✅
// TODO: 考虑缩小（抽屉）✅
// TODO: 考虑性能，暂无发现性能相关问题 ✅

//  a-table 设置了 scroll.x 固定了之后，带有 fixed right 的 columns 不会进行动态计算，没有设置 scroll.x 才会跟随屏幕大小动态计算
export const useDetectOverflow = (tableLayoutEl: Ref<HTMLElement | null>) => {
  const hasScrollbar = ref(false);
  provide(hasScrollbarKey, hasScrollbar);

  let roHasScrollbar: ResizeObserver | undefined;

  const init = async () => {
    await nextTick();
    if (
      tableLayoutEl.value &&
      // ✨ 被 table-layout--fixed 包含，肯定是弹性伸缩表格，需要计算滚动条显示隐藏后表格的一些处理
      tableLayoutEl.value.classList.contains(TABLE_LAYOUT_FIXED_CLS_NAME)
    ) {
      const tableEl =
        (tableLayoutEl.value.querySelector(
          '.table-layout__main > .table-layout__main-inner > .table-layout__table > .ant-table-wrapper'
        ) as MyHTMLElement) ||
        (tableLayoutEl.value.querySelector(
          '.table-layout__table > .ant-table-wrapper'
        ) as MyHTMLElement);

      if (tableEl) {
        let tableBodyEl: MyHTMLElement, colgroupLastColEl: MyHTMLElement;

        const getTableBodyEl = (tableEl: MyHTMLElement) => {
          if (tableBodyEl) return tableBodyEl;
          tableBodyEl = tableEl?.querySelector(
            `.${ANT_TABLE_BODY_CLS_NAME}`
          ) as MyHTMLElement;
          return tableBodyEl;
        };

        // 监听是否 table body 是否有滚动条
        roHasScrollbar = new ResizeObserver(
          debounce(entries => {
            const entry = entries[0];
            if (entry.target.scrollHeight > entry.target.clientHeight) {
              console.log('[unity-table-layout] antd body 出现滚动条 ✅');
              // ✨ 处理 antd 针对表头的 scrollbar 的计算，这个值会传递到 antd 底层 Table 的 FixedHolder 组件（需要 patch-package 修复）
              hasScrollbar.value = true;
              tableLayoutEl.value!.classList.remove(
                'table-layout--not-scrollbar'
              );
            } else {
              console.log('[unity-table-layout] antd body 没有出现滚动条 ❌');
              hasScrollbar.value = false;
              tableLayoutEl.value!.classList.add('table-layout--not-scrollbar');
            }
          }, 100)
        );
        tableBodyEl = getTableBodyEl(tableEl);
        roHasScrollbar.observe(tableBodyEl as Element);
      }
    }
  };
  onMounted(() => {
    init();
  });
  onUnmounted(() => {
    roHasScrollbar?.disconnect();
    roHasScrollbar = undefined;
  });
  // onActivated(() => {
  //   init();
  // });
  // onDeactivated(() => {
  //   roHasScrollbar?.disconnect();
  //   roHasScrollbar = undefined;
  // });
  return { hasScrollbar };
};

function throttle<T extends (...args: any[]) => void>(
  func: T,
  delay: number
): (...args: Parameters<T>) => void {
  let waiting = false;
  return function (this: ThisParameterType<T>, ...args: Parameters<T>): void {
    if (!waiting) {
      func.apply(this, args);
      waiting = true;
      setTimeout(() => {
        waiting = false;
      }, delay);
    }
  };
}

function debounce<T extends (...args: any[]) => void>(
  func: T,
  delay: number
): (...args: Parameters<T>) => void {
  let timer: number;
  return function (this: ThisParameterType<T>, ...args: Parameters<T>) {
    clearTimeout(timer);
    timer = window.setTimeout(() => {
      func.apply(this, args);
    }, delay);
  };
}
