// ✨ [布局注意](https://ant.design/components/table-cn#table-demo-fixed-header)
// ✨ 表头固定模式时（:scroll="{ y: xxx }"）：需要指定 column 的 width 属性，否则列头和内容可能不对齐。如果指定 width 不生效或出现白色垂直空隙，请尝试建议留一列不设宽度以适应弹性布局，或者检查是否有超长连续字段破坏布局。

import {
  type App,
  computed,
  defineComponent,
  nextTick,
  provide,
  ref,
  toRef,
  watch,
  onMounted
} from 'vue';
// @ts-ignore
import style from './style/index.module.less';
import {
  drawerKey,
  drawerStyleKey,
  filterCustomSwitchKey,
  filterLeftMountedKey,
  filterSecondMountedKey,
  filterSecondOpenKey,
  mainMountedKey,
  updateDrawerKey
} from './utils/key';

import scrollTo from 'ant-design-vue/es/_util/scrollTo';
import { type GlobalOptions } from './types';
import { useDetectOverflow } from './hooks/useDetectOverflow';

const Tl = defineComponent({
  name: 'Tl',
  props: {
    // { fixTableScrollbar: true }
    fixed: { type: [Boolean, Object], default: true },
    drawer: { type: Boolean, default: false },
    // 是否卡片模式，目前永策都是卡片形式
    card: { type: Boolean, default: true }
  },
  emits: ['update:drawer'],
  setup(props, { attrs, slots, emit }) {
    // 动画为 @animation-duration-fast: 0.2s;这里需要预留时间
    const DELAY = 300;

    const mainMounted = ref(false);
    const filterSecondMounted = ref(false);
    const filterSecondOpen = ref(false);
    const filterLeftMounted = ref(false);
    const customSwitch = ref(false);
    const drawerStyle = ref<GlobalOptions['drawerStyle']>('custom');

    provide(mainMountedKey, mainMounted);
    provide(filterSecondMountedKey, filterSecondMounted);
    provide(filterSecondOpenKey, filterSecondOpen);
    provide(filterLeftMountedKey, filterLeftMounted);
    provide(filterCustomSwitchKey, customSwitch);

    provide(drawerKey, toRef(props, 'drawer'));
    provide(updateDrawerKey, (val: boolean) => {
      emit('update:drawer', val);
    });

    // 📝 这个值虽然从顶部提供，但是主要 props 接收在 Drawer 组件
    provide(drawerStyleKey, drawerStyle);

    const clsFixed = computed(() => (props.fixed ? 'table-layout--fixed' : ''));

    const clsFixTableScrollbar = computed(() =>
      getIsFixTableScrollbar() ? 'table-layout--fix-table-scrollbar' : ''
    );

    // 📝 card 模式下且没有 main 挂载，某些样式要做改变
    const clsMainMounted = computed(() => {
      return `${
        mainMounted.value
          ? 'flex' // main被挂载，默认采用 flex，承载 main 和 drawer
          : props.card // card 模式下
          ? 'flex flex-col'
          : 'flex flex-col px-[32px] py-[24px] !bg-[#fff]'
      }`;
    });

    // const clsHasDrawer = ref('');
    // // 做延迟
    // watch(
    //   () => props.drawer,
    //   (val: boolean) => {
    //     if (val) {
    //       clsHasDrawer.value = 'table-layout--has-drawer';
    //     } else {
    //       setTimeout(() => {
    //         clsHasDrawer.value = '';
    //       }, DELAY);
    //     }
    //   }
    // );

    const clsHasDrawer = computed(() => {
      return `${
        props.drawer && drawerStyle.value === 'custom'
          ? 'table-layout--has-drawer'
          : ''
      }`;
    });

    const inDrawer = ref(false);
    onMounted(() => {
      inDrawer.value = !!tl.value?.closest('.table-layout__drawer-main');
    });
    const clsCard = computed(() => {
      // ⚠ ⚠ ⚠ tl 在 tl-drawer 强制关闭 card 模式
      return `${inDrawer.value ? '' : props.card ? 'table-layout--card' : ''}`;
    });

    const cls = computed(() => {
      // return `${style['table-layout']} table-layout h-full bg-[#f5f6f9] ${clsHasDrawer.value} ${clsFixed.value} ${clsMainMounted.value} ${clsFixTableScrollbar.value} ${clsCard.value}`;
      return [
        style['table-layout'],
        'table-layout h-full bg-[#f5f6f9]',
        clsHasDrawer.value,
        clsFixed.value,
        clsMainMounted.value,
        clsFixTableScrollbar.value,
        clsCard.value
      ];
    });

    // #region 滚动条控制相关
    const tl = ref<HTMLElement | null>(null);
    const cacheScroll = { scrollLeft: 0, scrollTop: 0 };
    watch(
      () => props.drawer,
      async (val: boolean) => {
        const $tableBody = tl.value?.querySelector(
          '.ant-table-body'
        ) as HTMLElement;
        // 有 $tableBody 这个元素的 是因为 table :scroll 对象赋值了 x或者y
        if ($tableBody) {
          if (val) {
            const { scrollLeft, scrollTop } = $tableBody;
            Object.assign(cacheScroll, { scrollLeft, scrollTop });

            await nextTick();

            setTimeout(() => {
              // 滚动到合适位置
              const $row = $tableBody.querySelector(
                '.ant-table-row[ant-table-row-selected-custom="true"]'
              ) as HTMLElement;
              if ($row) {
                // $tableBody.scrollTop =
                //   $row.offsetTop -
                //   ($tableBody.offsetHeight - $row.offsetHeight) / 2;

                scrollTo(
                  $row.offsetTop -
                    ($tableBody.offsetHeight - $row.offsetHeight) / 2,
                  {
                    getContainer: () => $tableBody,
                    duration: 50
                  }
                );
              }
            }, DELAY);
          } else {
            await nextTick();
            setTimeout(() => {
              const { scrollLeft, scrollTop } = cacheScroll;
              Object.assign($tableBody, { scrollLeft, scrollTop });
            }, DELAY);
          }
        }
      }
    );
    // #endregion

    // ✨ 侦测是否有滚动条，用于处理表格样式
    getIsFixTableScrollbar() && useDetectOverflow(tl);

    function getIsFixTableScrollbar() {
      if (props.fixed !== null && typeof props.fixed === 'object') {
        if (props.fixed.fixTableScrollbar) return true;
      } else if (props.fixed === true) {
        return true;
      }
      return false;
    }

    return () => (
      <div ref={tl} class={cls.value}>
        {slots.default?.()}
      </div>
    );
  }
});
export default Tl as typeof Tl & {
  install: (app: App, ...options: any[]) => any;
};
