import { ElLoading, ElPagination, ElTable, ElTableColumn } from 'element-plus'
import BaseColumn from './baseColumn.vue'
import { isUndefined } from '@/utils/is'
import { computed, defineComponent, nextTick, reactive, type PropType } from 'vue'
import './baseTable.scss'

function getDefaultSort(attrs: Record<string, any>): any {
  return attrs['default-sort'] || attrs.defaultSort
}

export default defineComponent({
  name: 'XTable',
  directives: {
    loading: ElLoading.directive
  },
  inheritAttrs: false,
  props: {
    /**
     * 表格的列描述信息
     */
    columns: {
      type: Array as PropType<XTableColumn[]>,
      required: true
    },

    /**
     * 表格的数据
     */
    dataSource: {
      type: Array as PropType<XTableData[]>,
      required: true
    },

    /**
     * loading
     */
    loading: {
      type: Boolean,
      default: false
    },

    /**
     * 最大高度，包含分页高度
     */
    maxHeight: {
      type: [Number, String] as PropType<number | 'auto'>,
      default: 'auto'
    },

    /**
     * 是否显示分页
     * 为 always 时，将一直显示
     * 为 false 时，总是不显示
     * 为 true 时，只有有数据时才显示
     */
    pageable: {
      type: [Boolean, String] as PropType<boolean | 'always'>,
      default: true,
      validator(value: boolean | 'always') {
        return ['always', true, false].includes(value)
      }
    },

    /**
     * 分页布局
     */
    pagerLayout: {
      type: String,
      default: 'total, sizes, prev, pager, next, jumper',
      validator(value: string) {
        return value
          .split(',')
          .map((item) => item.trim())
          .every((item) => ['total', 'sizes', 'prev', 'pager', 'next', 'jumper'].includes(item))
      }
    },

    /**
     * 总条数
     */
    total: {
      type: Number,
      default: 0
    },

    /**
     * 每页显示数量
     */
    pageSize: {
      type: Number,
      default: 10
    },

    /**
     * 页码
     */
    page: {
      type: Number,
      default: 1
    },

    /**
     * 分页选择器的选项设置
     */
    pageSizes: {
      type: Array as PropType<number[]>,
      default() {
        return [10, 20, 30, 40]
      }
    },

    /**
     * 行数据的 Key
     */
    rowKey: {
      type: [Function, String] as PropType<(row: XTableData) => string | string>,
      default: 'id'
    },

    /**
     * 打开自定义列
     */
    visibleColumn: {
      type: Boolean,
      default: undefined
    },

    /**
     * 固定分页器
     */
    isFixedPagination: {
      type: Boolean,
      default: true
    }

    // handleDel: {
    //   type: Function,
    //   default: () => {}
    // }
    // customActions: {
    //   type: Function,
    //   default: () => {}
    // }
  },
  emits: ['change', 'columnChange', 'update:visibleColumn', 'actions'],
  setup(props, { slots, attrs, emit }) {
    const nonPropsAttrs = attrs
    const { prop: sortBy, order: sortOrder } = getDefaultSort(attrs) || {}
    const tableState = reactive<XTableState>({
      tid: 0,
      sortBy,
      sortOrder
    })

    const showPagination = computed(() => {
      if (props.pageable === 'always') return true
      return props.pageable && props.dataSource.length > 0
    })

    const mHeight = computed(() => {
      if (props.maxHeight === 'auto') {
        return 'auto'
      }
      return showPagination.value ? props.maxHeight - 44 : props.maxHeight
    })

    /**
     * 获取插槽
     */
    function getSlot(column: XTableColumn, suffix?: string) {
      const name = column.prop || column.type
      if (name) {
        const key = suffix ? `${name}-${suffix}` : name
        return slots[key]
      }
    }

    /**
     * 改变表格列的排序和分页
     */
    function onChange(data: XTableChangeData) {
      emit('change', data)
    }

    /**
     * 改变页数
     */
    function handlePageNumChange(page: number) {
      const { sortBy, sortOrder } = tableState
      const { pageSize } = props
      onChange({
        page,
        pageSize,
        prop: sortBy,
        order: sortOrder,
        type: 'number'
      })
    }

    /**
     * 改变每页显示的条数
     */
    function handlePageSizeChange(pageSize: number) {
      const { sortBy, sortOrder } = tableState
      nextTick(() => {
        // 下拉框溢出可能导致溢出 body 出现滚动条
        // 加个延迟，等下拉隐藏
        onChange({
          page: 1,
          pageSize,
          prop: sortBy,
          order: sortOrder,
          type: 'size'
        })
      })
    }

    /**
     * 排序
     */
    function handleTableSortChange({ prop, order }: XTableSort) {
      const { pageSize } = props
      onChange({ page: 1, pageSize, prop, order, type: 'sort' })
    }

    /**
     * 自定义列回调
     */
    function handleColumnChange(cols: XTableColumn[]) {
      emit('columnChange', cols)
    }

    /**
     * 自定义列隐藏
     */
    function handleVisibleChange(val: boolean) {
      emit('update:visibleColumn', val)
    }

    /**
     * 获取表格列的属性
     */
    function getColumnProps(column: XTableColumn) {
      const col = { ...column }
      Reflect.deleteProperty(col, 'children')
      Reflect.deleteProperty(col, 'hidden')
      col.key = column.key || column.prop || column.type
      col.showOverflowTooltip = col.showOverflowTooltip ?? true
      col.showOverflowTooltip = column.prop === 'action' ? false : column.showOverflowTooltip
      return col
    }

    /**
     * 渲染特殊列
     */
    function renderTypeColumn(column: XTableColumn) {
      if (column.type === 'expand') {
        return (
          <ElTableColumn {...getColumnProps(column)}>
            {{
              default: (scope: Record<string, any>) => {
                const slot = getSlot(column)
                return slot?.(scope)
              }
            }}
          </ElTableColumn>
        )
      }
      if (column.type === 'action') {
        return (
          <ElTableColumn {...getColumnProps(column)}>
            {{
              default: ({ row }: { row: Record<string, any> }) => {
                return (
                  <div>
                    {slots.actionBar && <div>{slots.actionBar({ row })}</div>}
                    {/* <ul>
                      <li
                        class="flex items-center"
                        style={{ fontSize: "14px", color: "#E80D0D" }}
                        onClick={() => handleDel(row)}
                      >
                        <i class="iconfont icon-shanchu pr-[8px]"></i>
                        <el-button type="text">
                          <span
                            style={{
                              fontSize: "14px",
                              color: "#E80D0D"
                            }}
                          >
                            删除
                          </span>
                        </el-button>
                      </li>
                    </ul> */}
                  </div>
                )
              }
            }}
          </ElTableColumn>
        )
      }
      return <ElTableColumn {...getColumnProps(column)} />
    }

    /**操作按钮事件 */

    // function handleDel(row) {
    //   console.log(row, "handleDel");
    //   emit("actions", {
    //     type: "delete",
    //     data: { ...row }
    //   });
    // }

    /**
     * 渲染普通列
     */
    function renderBaseColumn(column: XTableColumn) {
      const columnSlots: {
        default?: (scope: Record<string, any>) => any
        header?: (scope: Record<string, any>) => any
      } = {}
      const slot = getSlot(column)
      const headerSlot = getSlot(column, 'header')

      if (slot) {
        columnSlots.default = (scope) => slot(scope)
      }

      if (headerSlot) {
        columnSlots.header = (scope) => headerSlot(scope)
      }

      return <ElTableColumn {...getColumnProps(column)}>{columnSlots}</ElTableColumn>
    }

    /**
     * 渲染列
     */
    function renderTableColumn(column: XTableColumn) {
      if (column.hidden) return
      if (column.type) {
        return renderTypeColumn(column)
      }
      return renderBaseColumn(column)
    }

    /**
     * 渲染多级列
     */
    function renderColumnChildren(
      column: XTableColumn,
      children: Required<XTableColumn>['children']
    ) {
      if (column.hidden) return
      return (
        <ElTableColumn {...getColumnProps(column)}>
          {children.map((column) => renderTableColumn(column))}
        </ElTableColumn>
      )
    }

    /**
     * 渲染分页
     */
    function renderPagination() {
      const paginationProps = {
        size: 'small',
        background: false,
        total: props.total,
        layout: props.pagerLayout,
        pageSize: props.pageSize,
        pageSizes: props.pageSizes,
        currentPage: props.page,
        onSizeChange: handlePageSizeChange,
        onCurrentChange: handlePageNumChange
      }

      return (
        <div
          class={[
            'x-table-pagination pagination_wrap flex justify-center items-center',
            props.isFixedPagination ? 'fixed_pagination' : 'noneFixed_pagination'
          ]}
        >
          <ElPagination {...paginationProps} />
          <span className="ds-pagination__goto_next">
            页
          </span>
        </div>
      )
    }

    /**
     * 渲染自定义列
     */
    function renderCustomColumn() {
      const customColumnProps = {
        columns: props.columns,
        visible: props.visibleColumn,
        onChange: handleColumnChange,
        onVisibleChange: handleVisibleChange
      }

      return <BaseColumn {...customColumnProps} />
    }

    return () => {
      const tableProps = {
        ref: 'elTableRef',
        ...nonPropsAttrs,
        maxHeight: mHeight.value,
        data: props.dataSource,
        rowKey: props.rowKey,
        onSortChange: handleTableSortChange
      }

      const extraSlots: {
        append?: () => any
        empty?: () => any
      } = {}

      if (slots.append) {
        extraSlots.append = () => slots.append?.()
      }

      if (slots.empty) {
        extraSlots.empty = () => slots.empty?.()
      }

      return (
        <div class="x-table baseTable_wrap">
          <ElTable
            class="baseTable_box"
            {...tableProps}
            v-loading={props.loading}
            v-slots={extraSlots}
          >
            {props.columns.map((column) => {
              if (Array.isArray(column.children)) {
                return renderColumnChildren(column, column.children)
              }
              return renderTableColumn(column)
            })}
            {/* 使用插槽引入操作栏的内容 */}
          </ElTable>
          {showPagination.value && renderPagination()}
          {!isUndefined(props.visibleColumn) && renderCustomColumn()}
        </div>
      )
    }
  }
})
