import {
  App,
  computed,
  defineComponent,
  inject,
  PropType,
  reactive,
  ref,
  Ref,
  toRef,
  watch
} 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 { getParent, isTableColumnsOperateNotEmpty } from './utils';
import { drawerKey } from '@kt/unity-table-layout';
import { getGuid } from '@kt/unity-utils';
import { 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 { TableColumnsOperate } from './types';
import TCOLocalStorage from './components/tableColumnsOperate/tcoLocalStorage';

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 }) {
    const fakeStyle = new FakeStyle();

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

    // #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);
        }
      });
    }

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

      // 是通过表格操作栏点击触发的
      const isBtnLink = (target: any) => getParent(target, 'ant-btn-link');

      return {
        onClick: (event: any) => {
          // 先执行内部的方法
          if (drawer?.value && isBtnLink(event.target)) {
            clearAttribute();

            const $row = getParent(
              event.target,
              'ant-table-row'
            ) as unknown as HTMLElement;

            // @ts-ignore
            $row.setAttribute('ant-table-row-selected-custom', true);

            // 需要确保 a-table 都必须要 row-key 属性，否则不会高亮
            const dataRowKey = $row.getAttribute('data-row-key') || '';
            if (dataRowKey === '') {
              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) 属性，否则此行不会被高亮.`
                );
              }
            } else {
              fakeStyle.create(`.ant-table-tbody > .ant-table-row[data-row-key='${dataRowKey}'] > td 
{
    background: #F4F6F9;
    border-color: rgba(0, 0, 0, 0.03);
}`);
            }
          }

          // 执行外部的方法
          _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 _exclude = parseExclude(props.tableColumnsOperate.exclude || []);
      // 📝 用于表格列操作，只考虑首次，不考虑外部 columns 再次变化（长度）
      const _TCOList = props.columns.filter(
        (item: any) => !_exclude.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;
      },
      { deep: true, immediate: true }
    );

    if (isTCO) {
      // 监听 tableColumnsOperate 变化，外部可能存在参数异步的场景
      watch(
        tableColumnsOperate,
        () => {
          const newColumns = reshow(
            originColumns,
            tableColumnsOperate,
            tcoLocalStorage
          );
          _columns.value = 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;
      };
      headerCell = useHeaderCell({
        TCOShowIcon,
        TCOPopoverVisible,
        TCOList,
        tableColumnsOperate,
        tcoLocalStorage,
        onSave: _updateTableColumns,
        onReset: _updateTableColumns
      });
    }
    // #endregion

    return () => (
      <TableAlias
        class={`${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}
        v-slots={{
          ...slots,
          headerCell
        }}
      />
    );
  }
});

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