<!-- @ts-nocheck - Vue 2 el-table-column slot 透传类型与 useSlots 联合类型存在已知限制 -->
<template>
    <el-table-column
    v-if="column.children && column.children.length > 0"
    :label="column.title"
    :align="column.align || 'left'"
    :fixed="column.fixed"
    :width="column.width"
    :min-width="getColumnWidth(column)"
  >
    <template v-for="child in column.children">
      <TableColumnGroup
        v-if="shouldShowColumn(child)"
        :key="child.key || child.dataIndex || child.title"
        :column="child"
        :effective-props="effectiveProps"
        :get-column-width="getColumnWidth"
        :scoped-slots="mergedSlots"
      />
    </template>
  </el-table-column>
  <el-table-column
    v-else
    :prop="column.dataIndex"
    :label="column.title"
    :min-width="getColumnWidth(column)"
    :fixed="column.fixed"
    :align="column.align || 'left'"
    :sortable="column.sortable"
    :formatter="column.formatter"
    :show-overflow-tooltip="column.ellipsis !== false && effectiveProps.ellipsis !== false"
  >
    <template #default="{ row, $index }">
      <template v-if="column.dataIndex && mergedSlots[column.dataIndex]">
        <RenderSlot :slot-fn="asSlotFn(mergedSlots[column.dataIndex])" :slot-props="{ row, column, index: $index, value: row[column.dataIndex] }" />
      </template>
      <template v-else-if="mergedSlots['bodyCell']">
        <RenderSlot :slot-fn="asSlotFn(mergedSlots['bodyCell'])" :slot-props="{ column, row, record: row, index: $index, value: row[column.dataIndex], customRender: column.customRender, valueEnum: column.valueEnum }" />
      </template>
      <DefaultCellRenderer
        v-else
        :column="column"
        :record="row"
        :index="$index"
        :value="row[column.dataIndex]"
      />
    </template>
    <template #header>
      <template v-if="column.dataIndex && mergedSlots[`header-${column.dataIndex}`]">
        <RenderSlot :slot-fn="asSlotFn(mergedSlots[`header-${column.dataIndex}`])" :slot-props="{ column }" />
      </template>
      <template v-else-if="mergedSlots['headerCell']">
        <RenderSlot :slot-fn="asSlotFn(mergedSlots['headerCell'])" :slot-props="{ column }" />
      </template>
      <template v-else>
        <span>{{ column.title }}</span>
        <el-tooltip v-if="column.helpMessage" class="ecp-pro-table__col-help" placement="top" effect="dark">
          <template #content>
            <span v-if="Array.isArray(column.helpMessage)">
              <div v-for="(msg, i) in column.helpMessage" :key="i">{{ msg }}</div>
            </span>
            <span v-else>{{ column.helpMessage }}</span>
          </template>
          <i class="el-icon-question" />
        </el-tooltip>
      </template>
    </template>
  </el-table-column>
</template>

<script setup lang="ts">
import { useSlots, computed, defineComponent } from 'vue'
import type { ProColumn, ProTableProps } from '../types'
import { DefaultCellRenderer } from './CellRenderers'

const props = defineProps<{
  column: ProColumn
  effectiveProps: ProTableProps
  getColumnWidth: (col: ProColumn) => number | string | undefined
  scopedSlots?: Record<string, ReturnType<typeof useSlots>>
}>()

const $slots = useSlots()

/** 合并父组件透传的 slots 与自身 slots，优先使用自身 */
const mergedSlots = computed(() => ({
  ...(props.scopedSlots ?? {}),
  ...$slots,
}))

const shouldShowColumn = (col: ProColumn) => {
  if (col.ifShow === false) return false
  if (typeof col.ifShow === 'function') return col.ifShow({ column: col })
  return true
}

/** 类型断言辅助函数，解决 Vue 模板中 Slot|Slots 无法赋值给 Function 的问题 */
const asSlotFn = (slot: Function | unknown): Function => slot as unknown as Function

/** 渲染 slot 函数的包装组件 */
const RenderSlot = defineComponent({
  name: 'RenderSlot',
  props: {
    slotFn: { type: Function, required: true },
    slotProps: { type: Object, default: () => ({}) },
  },
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  render(this: any) {
    return this.$props.slotFn(this.$props.slotProps)
  },
})
</script>
