import {
  type App,
  type PropType,
  type Ref,
  computed,
  defineComponent,
  inject,
  reactive,
  ref,
  toRef,
  watch,
  Comment,
  onUnmounted,
  provide
} from 'vue';
import TableAlias from 'ant-design-vue/es/table';
import 'ant-design-vue/es/table/style';
import config from './config';
// @ts-ignore
import style from './style/index.module.less';
import { isTableColumnsOperateNotEmpty } from './utils';
import {
  drawerKey,
  hasScrollbarKey,
  highlightRowFnKey
} from '@kt/unity-table-layout';
import { getGuid } from '@kt/unity-utils';
import { type GetComponentProps } from 'ant-design-vue/es/vc-table/interface';
import FakeStyle from './utils/fakeStyle';
import {
  useHeaderCell,
  customHeaderCellExtra,
  reshow
} from './components/tableColumnsOperate';
import { parseExclude } from './components/tableColumnsOperate/utils';
import { cloneDeep } from 'lodash-es';
import { type TableColumnsOperate } from './types';
import TCOLocalStorage from './components/tableColumnsOperate/tcoLocalStorage';
import { useSyncLoadingStataus } from './hooks';
const Table = defineComponent({
  name: 'ATable',
  props: {
    // issue #3：https://ktcode.keytop.cn/front-framework/kt/unity/-/issues/3
    // 单独为 useTable 开放一个 prop，避免被 props.pagination 覆盖
    paginationForUseTable: {
      type: Object,
      default: () => {}
    },
    pagination: {
      type: [Object, Boolean],
      default: () => config.props.pagination
    },
    scroll: {
      type: Object,
      default: () => config.props.scroll
    },
    columns: {
      type: Array as PropType<any[]>,
      default: () => []
    },
    customRow: {
      // 沿用antd的ts声明
      type: Function as PropType<GetComponentProps<any>>
    },
    theadHeightNormal: {
      type: Boolean,
      default: false
    },
    tableColumnsOperate: {
      type: Object as PropType<TableColumnsOperate>,
      default: () => ({})
    }
  },
  inheritAttrs: false,
  setup(props, { attrs, slots, expose }) {
    const fakeStyle = new FakeStyle();

    const clsGuid = `table-extend-${getGuid()}`;
    const clsTheadHeightNormal = computed(() =>
      props.theadHeightNormal ? 'ant-table-wrapper--thead-height-normal' : ''
    );

    // 高亮行
    const highlightRowLocal = (
      $row: HTMLElement | null,
      // 需要确保 a-table 都必须要 row-key 属性，否则不会高亮
      dataRowKey: string | number = $row?.getAttribute('data-row-key') || ''
    ) => {
      // undefined 默认为 ''
      if ($row && dataRowKey !== null && `${dataRowKey}`.trim() !== '') {
        clearAttribute();

        // 📝 手动添加属性用于滚动
        $row?.setAttribute('ant-table-row-selected-custom', 'true');
        fakeStyleCreate(dataRowKey);
      } else {
        if (process.env.NODE_ENV !== 'production') {
          console.warn(
            `[unity-ant-table warn]: 请确保传入 [row-key](https://www.antdv.com/components/table-cn#%E6%B3%A8%E6%84%8F) 属性，否则此行不会被高亮.`
          );
        }
      }
    };

    const fakeStyleCreate = (dataRowKey: string | number) => {
      // background: #F4F6F9;
      // fix: 加入 clsGuid scope，否则在其他页面如果有 key 值一样的表格行，将会出现错误的高亮行为
      fakeStyle.create(`.${clsGuid} .ant-table-tbody > .ant-table-row[data-row-key='${dataRowKey}'] > td {
  background: #edf0f5;
  border-color: rgba(0, 0, 0, 0.03);
}`);
    };

    // #region 和 TableLayout 结合工作，不用 TableLayout 包裹也不会存在问题
    // 清除样式
    const clearAttribute = () => {
      const $rows =
        document
          .querySelector(`.${clsGuid}`)
          ?.querySelectorAll(
            '.ant-table-row[ant-table-row-selected-custom="true"]'
          ) || [];
      for (const item of $rows)
        item.removeAttribute('ant-table-row-selected-custom');
    };

    const drawer = inject<Ref<boolean>>(drawerKey);
    if (drawer) {
      watch(drawer, (val: boolean) => {
        if (!val) {
          const DELAY = 300;
          setTimeout(() => {
            clearAttribute();
            // 清空
            fakeStyle.clear();
          }, DELAY);
        }
      });
    }

    const hasScrollbar = inject<Ref<boolean>>(hasScrollbarKey);

    // sync loading status
    useSyncLoadingStataus(attrs);

    // 提供方法给 DropdownButton 内部使用
    provide(highlightRowFnKey, highlightRowLocal);

    /**
     * customRow 拦截
     */
    const _customRow = (record: any, index?: number) => {
      const { onClick: _onClick, ...rest } =
        props.customRow?.(record, index) || {};

      // 是通过表格操作栏点击触发的
      // ✅ 使用 closest 代替
      const isBtnLink = (target: any) =>
        (target as HTMLElement).closest('.ant-btn-link');

      return {
        onClick: (event: any) => {
          // 先执行内部的方法
          if (drawer?.value && isBtnLink(event.target)) {
            // ✅ 使用 closest 代替
            const $row = (event.target as HTMLElement).closest(
              '.ant-table-row'
            ) as HTMLElement | null;
            highlightRowLocal($row);
          }

          // 执行外部的方法
          _onClick?.(event);
        },
        ...rest
      };
    };
    // #endregion

    // #region 表格列操作

    /**
     * 验证是否需要初始化操作列相关，tableColumnsOperate 不能为空
     */
    let isTCO = isTableColumnsOperateNotEmpty(props.tableColumnsOperate);
    // 保持响应性
    const tableColumnsOperate = toRef(props, 'tableColumnsOperate');
    const TCOShowIcon = reactive<Record<string, boolean>>({});
    const TCOPopoverVisible = reactive<Record<string, boolean>>({});
    const TCOList = ref<any[]>([]);
    let tcoLocalStorage!: TCOLocalStorage;
    if (isTCO) {
      // 初始化 tco 缓存数据
      tcoLocalStorage = new TCOLocalStorage(TCOLocalStorage.getState());

      const excludeHead = parseExclude(props.tableColumnsOperate.excludeHead);
      // 刚开始只考虑 exclude 为了与 excludeHead 做区分，新增了 excludeTail ，但是还是对之前的 exclude 做兼容
      const excludeTail = parseExclude(
        props.tableColumnsOperate.excludeTail ||
          props.tableColumnsOperate.exclude
      );
      // 📝 用于表格列操作，只考虑首次，不考虑外部 columns 再次变化（长度）
      let _TCOList = props.columns.filter(
        (item: any) => !excludeHead.includes(item.dataIndex + '')
      );
      _TCOList = _TCOList.filter(
        (item: any) => !excludeTail.includes(item.dataIndex + '')
      );
      TCOList.value = _TCOList;

      if (_TCOList.length === 0) {
        // 关闭表格操作列功能
        isTCO = false;
        if (process.env.NODE_ENV !== 'production') {
          console.warn(
            `[unity-ant-table warn]: 请确保 columns 有值，否则无法操作表格列.`
          );
        }
      }
    }

    const _columns = ref<any[]>([]);

    // originColumns
    let originColumns: any[] = [];
    watch(
      () => props.columns,
      val => {
        // 深拷贝，先做一层拦截
        let columns = (originColumns = cloneDeep(val));
        for (const item of columns) {
          item.align = item.align ?? config.props.column.align;

          // 注册事件
          isTCO &&
            customHeaderCellExtra(item, { TCOShowIcon, TCOPopoverVisible });
        }

        // 回显
        isTCO &&
          (columns = reshow(columns, tableColumnsOperate, tcoLocalStorage));

        // 表格渲染
        _columns.value = columns;

        tableColumnsOperate.value.postColumns?.(columns);
      },
      { deep: true, immediate: true }
    );

    if (isTCO) {
      // 监听 tableColumnsOperate 变化，外部可能存在参数异步获取传入的场景
      watch(
        tableColumnsOperate,
        () => {
          const newColumns = reshow(
            originColumns,
            tableColumnsOperate,
            tcoLocalStorage
          );
          _columns.value = newColumns;
          tableColumnsOperate.value.postColumns?.(newColumns);
        },
        { deep: true }
      );
    }

    // const _columns = computed(() => {
    //   props.columns.forEach((item: any) => {
    //     // 默认 left
    //     item.align = item.align ?? config.props.column.align;
    //   });
    //   return props.columns as any;
    // });

    let headerCell: any = undefined;
    if (isTCO) {
      const _updateTableColumns = () => {
        const newColumns = reshow(
          originColumns,
          tableColumnsOperate,
          tcoLocalStorage
        );
        _columns.value = newColumns;

        tableColumnsOperate.value.postColumns?.(newColumns);
      };
      headerCell = useHeaderCell({
        TCOShowIcon,
        TCOPopoverVisible,
        TCOList,
        tableColumnsOperate,
        tcoLocalStorage,
        onSave: _updateTableColumns,
        onReset: _updateTableColumns
      });
    }
    // #endregion

    // FIX:修复外部 headerCell 插槽被内部 headerCell 表格列操作覆盖问题，在这里进行合并
    const headerCellMerge = (props: any) => {
      // 开启了 tco，就要合并外部的 headerCell 插槽
      let renderRes = slots.headerCell?.(props);
      // 不存在元素
      if (renderRes?.filter(c => c.type !== Comment).length === 0)
        renderRes = undefined;
      // 合并
      return headerCell
        ? [renderRes || props.column.title, headerCell(props)]
        : renderRes;
    };

    expose({
      // 让业务端控制行高亮
      highlightRow(dataRowKey: string | number) {
        const $row = document
          .querySelector(`.${clsGuid}`)
          ?.querySelector(
            `.ant-table-tbody > .ant-table-row[data-row-key='${dataRowKey}']`
          ) as HTMLElement | null;

        highlightRowLocal($row, dataRowKey);
      }
    });

    onUnmounted(() => {
      fakeStyle.remove();
    });

    return () => (
      <TableAlias
        class={[
          'unity-ant-table',
          `${style['table-extend']} ${clsGuid}`,
          clsTheadHeightNormal.value
        ]}
        {...config.props}
        {...attrs}
        customRow={_customRow}
        /**
         * 由于需要对深层对象进行一次合并覆盖，所以用 props 接收的方式，将它从 attrs 列表排除
         * pagination 可被置为 false 这里做判断
         */
        // @ts-ignore
        pagination={
          props.pagination
            ? {
                ...config.props.pagination,
                ...(props.pagination as Record<string, any>),
                ...props.paginationForUseTable
              }
            : false
        }
        scroll={
          props.scroll
            ? {
                ...config.props.scroll,
                ...props.scroll
              }
            : undefined
        }
        columns={_columns.value}
        hasScrollbar={hasScrollbar?.value}
        v-slots={{
          ...slots,
          headerCell: headerCellMerge
          // headerCell
        }}
      />
    );
  }
});

export default Table as typeof Table & {
  install: (app: App, ...options: any[]) => any;
};
// export default Table;
