<script lang="tsx">
import { ElTable, ElTableColumn, ElPagination, ElEmpty } from 'element-plus'
import { defineComponent, ref, computed, unref, watch, onMounted } from 'vue'
import { tableProps } from './props'
import { BasicTableProps, ColumnProps, TableSlotDefault, Pagination } from '@/types/table'
import { ZtTableHeader, ztTableHeaderHelp,ztTableFooter } from '../components/index'
import { createTableContext } from '../hooks/useTableContext'
import { getSlot } from '@/utils/tsxHelper'
import { useDesign } from '@/hooks/web/useDesign'
import { useLoading } from '../hooks/useLoading'
import { usePagination } from '../hooks/usePagination'
import { useRowSelection } from '../hooks/useRowSelect'
import { useTableData } from '../hooks/useTableData'
import { formatToDate } from '@/utils/dateUtil'
import { PAGE_SIZE } from './const'
import { useColumns } from '../hooks/useColumns'
import { omit } from 'lodash-es'

import { isFunction } from '@/utils/is'

export default defineComponent({
  // eslint-disable-next-line vue/no-reserved-component-names
  name: 'ZtTable',
  inheritAttrs: false,
  props: tableProps,
  emits: [
    //请求成功
    'fetch-success',
    //请求失败
    'fetch-error',
    //注册ref
    'register',
    //单选回调
    'current-change',
    //多选回调
    'selecet-key-change',
    'row-mouseenter',
    'row-mouseleave',
    'change'
  ],
  setup(props, { emit, expose }) {
    const slots = useSlots()
    const attrs = useAttrs()

    //获取css前缀
    const { getPrefixCls } = useDesign()
    const prefixCls = getPrefixCls('table')

    //table 的ref实例
    const tableElRef = ref<InstanceType<typeof ElTable>>()

    const wrapRef = ref(null)
    //内部默认props
    const innerPropsRef = ref<Partial<BasicTableProps>>()

    //获取合并的props
    const getProps = computed(() => {
      return { ...props, ...unref(innerPropsRef) } as BasicTableProps
    })

    //ts-ignore
    const pageSizeRef = ref(props.pagination?.pageSize ?? PAGE_SIZE)
    //ts-ignore
    const currentPageRef = ref(props.pagination?.currentPage ?? 1)

    //获取loading状态
    const { getLoading, setLoading } = useLoading(getProps)
    //获取分页信息
    const {
      getPaginationInfo,
      getPagination,
      setPagination,
      setShowPagination,
      getShowPagination
    } = usePagination(getProps)

    //列表数据
    const tableData = ref<Recordable[]>([])

    //获取选中信息
    const { getSelectRowKeys, getSelectRows, clearSelectedRowKeys, setSelectedRows } =
      useRowSelection(
        getProps,
        tableData,
        emit,
        // @ts-ignore
        tableElRef
      )

    const {
      handleTableChange: onTableChange,
      getDataSourceRef,
      getDataSource,
      getRawDataSource,
      setTableData,
      updateTableDataRecord,
      deleteTableDataRecord,
      insertTableDataRecord,
      findTableDataRecord,
      fetch,
      reload,
      updateTableData
    } = useTableData(
      getProps,
      {
        tableData,
        getPaginationInfo,
        setLoading,
        setPagination,
        clearSelectedRowKeys
      },
      emit
    )

    /*watch(
      () => pageSizeRef,
      (newVal) => {
        console.log(newVal, 'newValnewValnewVal')
      }
    )

    watch(
      () => currentPageRef,
      (newVal) => {
        console.log(newVal, '11212121')
      }
    )*/

    function handleTableChange(data) {
      emit('change', data)
      onTableChange(data)
      /* onTableChange.call(undefined, ...args)
      
      // 解决通过useTable注册onChange时不起作用的问题
      const { onChange } = unref(getProps)
      onChange && isFunction(onChange) && onChange.call(undefined, ...args) */
    }

    const {
      getViewColumns,
      getColumns,
      setCacheColumns,
      setColumns,
      setLocalColumns,
      getCacheColumns
    } = useColumns(getProps, getPaginationInfo)

    const getBindValues = computed(() => {
      let propsData: Recordable = {
        ...attrs,
        ...unref(getProps),
        tableLayout: 'fixed'
      }
      propsData = omit(propsData, [
        'class',
        'onChange',
        'columns',
        'sortFn',
        'dataSource',
        'fetchSetting',
        'schema',
        'filterFn'
      ])

      return propsData
    })

    function setProps(props: Partial<BasicTableProps>) {
      innerPropsRef.value = { ...unref(innerPropsRef), ...props }
    }

    function columnChange(columns: ColumnProps[]) {}

    const tableAction: any = {
      reload,
      getSelectRows,
      setSelectedRows,
      clearSelectedRowKeys,
      getSelectRowKeys,
      setPagination,
      setTableData,
      updateTableDataRecord,
      deleteTableDataRecord,
      insertTableDataRecord,
      findTableDataRecord,
      setColumns,
      setLoading,
      getDataSource,
      getRawDataSource,
      setProps,
      getPaginationRef: getPagination,
      getColumns,
      getViewColumns,
      setLocalColumns,
      getCacheColumns,
      emit,
      updateTableData,
      setCacheColumns
    }

    expose(tableAction)
    emit('register', tableAction)
    createTableContext({ ...tableAction, wrapRef, getBindValues })
    /******************tsx渲染***********************/

    //渲染头部数据
    const renderTableHeader = () => {
      const { title, showTableSetting, titleHelpMessage, tableSetting } = unref(getProps)

      return (
        <ZtTableHeader
          title={title}
          showTableSetting={showTableSetting}
          titleHelpMessage={titleHelpMessage}
          tableSetting={tableSetting}
          v-slots={{
            toolbar: slots.toolbar
          }}
          onColumnChange={(columns) => {
            columnChange(columns)
          }}
        ></ZtTableHeader>
      )
    }

    //渲染自定义合计数据活着其他数据(官方合计只能是列合计，太具有局限性)
    const renderTableFooter = () => {
      //TODO
      const getIsEmptyData = computed(() => {
        return (unref(getDataSourceRef) || []).length === 0
      })

      if (!unref(getProps).showDescSummary) return

      const { summaryData,schema } = unref(getProps)

      return <ztTableFooter schema={schema}  summaryData={summaryData} ></ztTableFooter>
    }

    //渲染空白数据
    const renderTableEmpty = () => {
      return <ElEmpty description="暂无数据"></ElEmpty>
    }

    //渲染树节点
    const renderTreeTableColumn = (columns: ColumnProps[]) => {
      return <div></div>
    }

    //渲染自定义列表头
    const renderCutomTableHeader = (column: ColumnProps) => {
      //自定义最优先。其次是默认的help ，最后是默认的
      if (getSlot(slots, `${column.prop}-header`)) {
        return getSlot(slots, `${column.prop}-header`)
      } else if (column.helpMessage) {
        return (
          <ztTableHeaderHelp
            helpMessage={column.helpMessage}
            title={column.label}
          ></ztTableHeaderHelp>
        )
      } else {
        return column.label
      }
    }
    //渲染列表格
    const renderElTableColumn = () => {
      return unref(getViewColumns).map((column) => {
        let columnProps = omit(column, ['label', 'prop'])

        return (
          <ElTableColumn label={column.label} prop={column.prop} {...columnProps} >
            {{
              default: (data: TableSlotDefault) =>
                column.children && column.children.length
                  ? renderTreeTableColumn(column.children)
                  : // @ts-ignore
                    getSlot(slots, column.prop, data) ||
                    //自定义渲染支持任何tsx返回
                    column?.customRender?.(
                      data.row,
                      data.column,
                      data.row[column.prop],
                      data.$index
                    ) ||
                    data.row[column.prop!],
              // @ts-ignore
              header: () => renderCutomTableHeader(column)
            }}
          </ElTableColumn>
        )
      })
    }

    //这个computed是因为 分页组件的pageSize和currentPage 不能和el-table的v-model绑定，否则会导致分页无法点击
    const paginationSettingRef = computed(() => {
      let tem = getPaginationInfo.value
      if (tem) {
        //omit 会导致 分页无法点击
        //omit(tem,['pageSize','currentPage'])
        delete tem.pageSize
        delete tem.currentPage
      }

      return tem
    })

    //获取用户自定义append
    let appendSlots = getSlot(slots, 'append')
    return () => (
      <div class={['el-table', ' p-[5px]', prefixCls]} ref={wrapRef}>
        {renderTableHeader()}
        <ElTable
          border
          ref={tableElRef}
          data={unref(getDataSourceRef)}
          v-loading={unref(getLoading)}
          v-slots={{
            append: appendSlots ? appendSlots : null,
            empty: () => renderTableEmpty()
          }}
          {...unref(getBindValues)}
        >
          {renderElTableColumn()}
        </ElTable>
        {renderTableFooter()}
        {getPaginationInfo && unref(getPaginationInfo) ? (
          // update by 芋艿：保持和 Pagination 组件一致
          //垃圾element 结构直接不生效
          //ts-ignore
          <ElPagination
            background
            v-model:pageSize={pageSizeRef.value}
            v-model:currentPage={currentPageRef.value}
            class="float-right mb-15px mt-15px"
            {...paginationSettingRef.value}
            onChange={(currentPage, pageSize) => {
              handleTableChange({ currentPage, pageSize })
            }}
          ></ElPagination>
        ) : undefined}
      </div>
    )
  }
})
</script>
