<template>
  <el-table v-bind="computedProps.props" ref="tableRef" class="base-table">
    <template v-for="(column, i) in computedProps.columns" :key="column.columnKey || column.index || column.prop || i">
      <el-table-column v-if="column.type && ['index', 'selection'].includes(column.type)" v-bind="column" />
      <el-table-column v-else-if="column.type === 'expand'" v-bind="column" #="scope">
        <slot name="expand" v-bind="scope"></slot>
      </el-table-column>
      <component :is="columnRender(column, i, slots)" v-else></component>
    </template>
    <template #append>
      <slot name="append"></slot>
    </template>
    <template #empty>
      <slot name="empty">
        <common-empty>
          <template v-if="showRefresh">
            <el-button type="primary" text @click="$emit('refresh')">
              <template #icon>
                <el-icon><refresh /></el-icon>
              </template>
              刷新
            </el-button>
          </template>
        </common-empty>
      </slot>
    </template>
  </el-table>
</template>

<script setup lang="tsx" name="EpTable">
import { shallowRef, computed, useSlots, useAttrs } from 'vue'
import { ElTable, ElTableColumn, ElButton, ElIcon } from 'element-plus'
import { Refresh } from '@element-plus/icons-vue'
import CommonEmpty from '@/components/common/Empty.vue'
import type { SetupContext, VNode, Slot } from 'vue'
import type { EpTableProps, EpTableColumn } from 'global-type'

interface BaseEpTableProps<T = any> extends EpTableProps<T> {
  columns?: EpTableProps<T>['columns']
}

const props = defineProps<BaseEpTableProps>()

const attrs = useAttrs()
const slots = useSlots()

const computedProps = computed(() => {
  const { columns, ...tableProps } = props
  return {
    columns: columns,
    props: tableProps,
  }
})

/** 数据为空时是否展示刷新按钮 */
const showRefresh = computed(() => typeof attrs.onRefresh === 'function')

const tableRef = shallowRef<InstanceType<typeof ElTable>>()

defineExpose({ tableRef })

/** 不同列的slot名称 */
function getColumnSlotName(column: EpTableColumn, index: number) {
  let tag = (column.slotName || column.columnKey || column.prop || column.index || index) ?? undefined
  if (typeof tag === 'function') {
    tag = tag(index)
  }
  return {
    header: 'column-header-' + tag,
    def: 'column-' + tag,
  }
}

/** 列渲染 */
function columnRender(column: EpTableColumn, index: number, inputSlots: SetupContext['slots']) {
  const { header, def } = getColumnSlotName(column, index)
  const columnSlots: Record<string, (...args: any) => VNode[]> = {}

  if (typeof inputSlots[header] === 'function') {
    columnSlots.header = (scope: any) => {
      return (inputSlots[header] as Slot)({ column: scope.column, $index: scope.$index })
    }
  }

  if (typeof inputSlots[def] === 'function') {
    columnSlots.default = (scope: any) => {
      return (inputSlots[def] as Slot)({ row: scope.row, column: scope.column, $index: scope.$index })
    }
  }

  return <ElTableColumn {...{ showOverflowTooltip: true, ...column }}>{columnSlots}</ElTableColumn>
}
</script>

<style scoped lang="scss"></style>
