<template>
  <div class="ecp-pro-table">
    <!-- 标题栏 -->
    <div v-if="showTitleBar" class="ecp-pro-table__header">
      <div class="ecp-pro-table__title-wrapper">
        <span class="ecp-pro-table__title">{{ effectiveProps.title }}</span>
        <el-tooltip v-if="effectiveProps.titleHelpMessage" class="ecp-pro-table__help" placement="top">
          <template slot="content">
            <span v-if="Array.isArray(effectiveProps.titleHelpMessage)">
              <div v-for="(msg, i) in effectiveProps.titleHelpMessage" :key="i">{{ msg }}</div>
            </span>
            <span v-else>{{ effectiveProps.titleHelpMessage }}</span>
          </template>
          <i class="el-icon-question" />
        </el-tooltip>
      </div>
      <div class="ecp-pro-table__toolbar">
        <slot name="tableTitle" />
        <slot name="toolbar" />
        <slot name="toolbar-right">
          <el-button
            v-if="effectiveProps.tableSetting?.redo !== false"
            type="text"
            icon="el-icon-refresh"
            size="small"
            @click="handleReload"
          >
            刷新
          </el-button>
        </slot>
      </div>
    </div>

    <!-- 表格主体（Element UI el-table 无 loading 属性，使用 v-loading 指令） -->
    <div ref="tableWrapRef" class="ecp-pro-table__body" v-loading="loading">
      <el-table
        ref="tableRef"
        :data="innerData"
        :row-key="effectiveProps.rowKey"
        :border="effectiveProps.bordered"
        :stripe="effectiveProps.striped"
        :size="effectiveProps.size"
        :max-height="effectiveProps.maxHeight"
        :height="effectiveProps.height"
        :default-sort="effectiveProps.defaultSort"
        :span-method="spanMethodAdapter"
        :tree-props="effectiveProps.treeProps"
        :default-expand-all="effectiveProps.defaultExpandAll"
        :expand-row-keys="effectiveProps.expandRowKeys || []"
        :lazy="effectiveProps.lazy"
        :load="effectiveProps.load"
        v-bind="effectiveProps.tableProps"
        :row-class-name="effectiveProps.rowClassName"
        @row-click="handleRowClick"
        @row-dblclick="handleRowDblclick"
        @sort-change="handleSortChange"
        @expand-change="handleExpandChange"
      >
        <!-- 选择列：自定义实现，参考 VbenAdmin，支持单选/多选/禁用/跨页 -->
        <el-table-column
          v-if="effectiveProps.rowSelection"
          :width="effectiveProps.rowSelection.width || 48"
          :fixed="effectiveProps.rowSelection.fixed"
          align="center"
        >
          <template slot="header" slot-scope="_">
            <!-- 多选：表头全选 -->
            <el-checkbox
              v-if="effectiveProps.rowSelection.type !== 'radio'"
              :value="isAllCurrentPageSelected"
              :indeterminate="isIndeterminate"
              :disabled="!hasSelectableRows"
              @change="handleSelectAll"
            />
            <span v-else />
          </template>
          <template slot-scope="scope">
            <!-- 多选 -->
            <el-checkbox
              v-if="effectiveProps.rowSelection.type !== 'radio'"
              :value="isRowSelected(scope.row)"
              :disabled="getCheckboxDisabled(scope.row)"
              @change="(val) => handleCheckboxChange(scope.row, val)"
              @click.native.stop
            />
            <!-- 单选 -->
            <el-radio
              v-else
              :value="selectedRows[0]?.[rowKeyField]"
              :label="scope.row[rowKeyField]"
              :disabled="getRadioDisabled(scope.row)"
              @change="handleRadioSelect(scope.row)"
              @click.native.stop
            >
              <span />
            </el-radio>
          </template>
        </el-table-column>
        <!-- 序号列 -->
        <el-table-column
          v-if="effectiveProps.showIndexColumn"
          type="index"
          :label="effectiveProps.indexColumnProps?.title || '序号'"
          :width="effectiveProps.indexColumnProps?.width || 60"
          :fixed="effectiveProps.indexColumnProps?.fixed"
          :align="effectiveProps.indexColumnProps?.align || 'center'"
        />
        <!-- 数据列（支持多级表头） -->
        <template v-for="col in displayColumns">
          <TableColumnGroup
            v-if="shouldShowColumn(col)"
            :key="col.key || col.dataIndex || col.title"
            :column="col"
            :effective-props="effectiveProps"
            :get-column-width="getColumnWidth"
            :scoped-slots="$scopedSlots"
          />
        </template>
        <!-- 操作列 -->
        <el-table-column
          v-if="effectiveProps.actionColumn"
          :label="effectiveProps.actionColumn.title || '操作'"
          :width="effectiveProps.actionColumn.width || 150"
          :fixed="effectiveProps.actionColumn.fixed || 'right'"
          :align="effectiveProps.actionColumn.align || 'center'"
        >
          <template slot-scope="scope">
            <!-- 优先使用具名 #action 插槽，与 bodyCell 完全解耦 -->
            <slot
              v-if="$scopedSlots['action']"
              name="action"
              :row="scope.row"
              :record="scope.row"
              :column="effectiveProps.actionColumn"
              :index="scope.$index"
            />
            <BodyCellRenderer
              v-else-if="$scopedSlots['bodyCell']"
              :slot-render="$scopedSlots['bodyCell']"
              :column="effectiveProps.actionColumn"
              :record="scope.row"
              :index="scope.$index"
              :value="undefined"
              :custom-render="effectiveProps.actionColumn.customRender"
              :value-enum="effectiveProps.actionColumn.valueEnum"
            />
          </template>
        </el-table-column>
      </el-table>
    </div>

    <!-- 分页 -->
    <div v-if="showPagination" class="ecp-pro-table__pagination">
      <el-pagination
        :current-page="pagination.page"
        :page-sizes="pagination.pageSizes"
        :page-size="pagination.pageSize"
        :total="pagination.total"
        :small="paginationSmall"
        :background="paginationBackground"
        :layout="(effectiveProps.pagination && typeof effectiveProps.pagination === 'object' ? effectiveProps.pagination.layout : null) || 'total, sizes, prev, pager, next, jumper'"
        v-bind="(effectiveProps.pagination && typeof effectiveProps.pagination === 'object' && effectiveProps.pagination.props) || {}"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
// @ts-nocheck - Vue 2 el-table-column slot-scope 类型推断存在已知限制，暂用此方式消除模板内 scope 相关告警
import { ref, computed, watch, onMounted, onUnmounted, useSlots, nextTick } from 'vue'
import { useComponentSetting } from '../useComponentSetting'
import type { ProColumn, ProTableProps, TableActionType, FetchSetting, FetchParams } from './types'
import TableColumnGroup from './components/TableColumnGroup.vue'
import { DefaultCellRenderer, BodyCellRenderer } from './components/CellRenderers'

const props = withDefaults(
  defineProps<{
    columns?: ProColumn[]
    dataSource?: Record<string, unknown>[]
    api?: (params: Record<string, unknown>) => Promise<{ list?: unknown[]; items?: unknown[]; total?: number }>
    rowKey?: string
    title?: string
    titleHelpMessage?: string | string[]
    bordered?: boolean
    striped?: boolean
    size?: 'medium' | 'small' | 'large'
    loading?: boolean
    maxHeight?: number | string
    height?: number | string
    ellipsis?: boolean
    showIndexColumn?: boolean
    indexColumnProps?: Partial<ProColumn>
    actionColumn?: Partial<ProColumn>
    rowSelection?: { type?: 'checkbox' | 'radio'; width?: number; fixed?: 'left' | 'right'; getCheckboxProps?: (r: Record<string, unknown>) => { disabled?: boolean }; getRadioProps?: (r: Record<string, unknown>) => { disabled?: boolean } }
    clearSelectOnPageChange?: boolean
    pagination?: false | { pageSize?: number; pageSizes?: number[]; layout?: string; small?: boolean; background?: boolean; props?: Record<string, unknown> } | Record<string, unknown>
    tableSetting?: { redo?: boolean; size?: boolean; setting?: boolean; fullScreen?: boolean }
    fetchSetting?: FetchSetting
    beforeFetch?: (params: Record<string, unknown>) => Record<string, unknown>
    afterFetch?: (data: unknown) => unknown
    immediate?: boolean
    searchInfo?: Record<string, unknown>
    defaultSort?: { prop: string; order: 'ascending' | 'descending' }
    tableProps?: Record<string, unknown>
    rowClassName?: string | ((params: { row: Record<string, unknown>; rowIndex: number }) => string)
    spanMethod?: (params: { row: Record<string, unknown>; column: Record<string, unknown>; rowIndex: number; columnIndex: number }) => [number, number] | { rowspan: number; colspan: number }
    treeProps?: { hasChildren?: string; children?: string }
    defaultExpandAll?: boolean
    expandRowKeys?: (string | number)[]
    lazy?: boolean
    load?: (row: Record<string, unknown>, treeNode: { level: number; expanded: boolean; loaded: boolean }, resolve: (data: Record<string, unknown>[]) => void) => void
  }>(),
  {
    rowKey: 'id',
    clearSelectOnPageChange: false,
    bordered: false,
    striped: true,
    size: 'medium',
    loading: false,
    ellipsis: true,
    showIndexColumn: true,
    pagination: () => ({ pageSize: 10, pageSizes: [10, 20, 50, 100] }),
    tableSetting: () => ({ redo: false }),
    fetchSetting: () => ({
      pageField: 'page',
      sizeField: 'pageSize',
      listField: 'list',
      totalField: 'total',
    }),
    immediate: true,
  }
)

const emit = defineEmits<{
  (e: 'register', action: TableActionType): void
  (e: 'fetch-success', data: { items: unknown[]; total: number }): void
  (e: 'fetch-error', error: unknown): void
  (e: 'selection-change', data: { keys: (string | number)[]; rows: Record<string, unknown>[] }): void
  (e: 'row-click', record: Record<string, unknown>, event: Event): void
  (e: 'row-dblclick', record: Record<string, unknown>, event: Event): void
  (e: 'sort-change', sortInfo: { prop: string; order: string }): void
  (e: 'expand-change', row: Record<string, unknown>, expanded: boolean | Record<string, unknown>[]): void
}>()

const slots = useSlots()
const tableRef = ref()
const tableWrapRef = ref()
const containerWidth = ref(0)
const loading = ref(props.loading ?? false)
const localFullData = ref<Record<string, unknown>[]>([])
/** 本地模式数据；API 模式下存服务端返回的当前页数据 */
const innerData = computed(() => {
  const data = localFullData.value
  // 不分页时展示全量数据
  if (!showPagination.value) return data
  // 远程加载数据时，不进行切片
  if (typeof props.api === 'function') {
    return data
  }
  if (!data.length) return data
  const { page, pageSize } = pagination.value
  const start = (page - 1) * pageSize
  return data.slice(start, start + pageSize)
})
const rawDataSource = ref<Record<string, unknown>>({})
const innerColumns = ref<ProColumn[]>([])
const innerProps = ref<Partial<ProTableProps>>({})
const selectedRows = ref<Record<string, unknown>[]>([])
const showPaginationRef = ref<boolean | null>(null)

const { mergeSettings } = useComponentSetting()
const effectiveProps = computed(() => mergeSettings<ProTableProps>('ProTable', { ...props, ...innerProps.value }))

/** 从 effectiveProps.pagination 读取分页默认值（已通过深度合并） */
const defaultPagination = computed(() => {
  const paginationConfig = effectiveProps.value.pagination
  if (paginationConfig && typeof paginationConfig === 'object') {
    return {
      pageSize: (paginationConfig as Record<string, unknown>).pageSize ?? 10,
      pageSizes: ((paginationConfig as Record<string, unknown>).pageSizes as number[]) ?? [10, 20, 50, 100],
    }
  }
  return { pageSize: 10, pageSizes: [10, 20, 50, 100] as number[] }
})

const pagination = ref({
  page: 1,
  pageSize: defaultPagination.value.pageSize,
  pageSizes: defaultPagination.value.pageSizes,
  total: 0,
})

const showTitleBar = computed(() => !!effectiveProps.value.title || !!slots.tableTitle || !!slots.toolbar)
const showPagination = computed(() => {
  if (showPaginationRef.value !== null) return showPaginationRef.value
  return !!props.pagination && typeof props.pagination === 'object'
})

/** 分页 small 属性：从 pagination 配置或全局设置中读取 */
const paginationSmall = computed(() => {
  if (effectiveProps.value.pagination && typeof effectiveProps.value.pagination === 'object') {
    return !!(effectiveProps.value.pagination as Record<string, unknown>).small
  }
  return false
})

/** 分页 background 属性：从 pagination 配置或全局设置中读取 */
const paginationBackground = computed(() => {
  if (effectiveProps.value.pagination && typeof effectiveProps.value.pagination === 'object') {
    return !!(effectiveProps.value.pagination as Record<string, unknown>).background
  }
  return false
})

const rowKeyField = computed(() => effectiveProps.value.rowKey || 'id')

/** 选中行 key 集合（用于快速判断） */
const selectedKeysSet = computed(() => new Set(selectedRows.value.map((r) => r[rowKeyField.value] as string | number)))

/** 显示列 */
const displayColumns = computed(() =>{
  return innerColumns.value.filter((c) => !c.hideInTable && !c.defaultHidden)
})

/** 扁平列映射：columnId -> 原始 ProColumn（供 spanMethod 使用） */
const flatColumnsMap = computed(() => {
  const map = new Map<string, ProColumn>()
  const flatten = (cols: ProColumn[]) => {
    for (const col of cols) {
      if (col.children && col.children.length > 0) {
        flatten(col.children)
      } else {
        if (col.dataIndex) map.set(col.dataIndex, col)
      }
    }
  }
  flatten(displayColumns.value)
  return map
})

/** 所有可见叶子列（支持多级表头） */
const allFlatColumns = computed(() => Array.from(flatColumnsMap.value.values()))

/** 固定列总宽度 */
const fixedColumnsWidth = computed(() => {
  let w = 0
  if (effectiveProps.value.rowSelection) w += Number(effectiveProps.value.rowSelection.width) || 48
  if (effectiveProps.value.showIndexColumn) w += Number(effectiveProps.value.indexColumnProps?.width) || 60
  if (effectiveProps.value.actionColumn) w += Number(effectiveProps.value.actionColumn?.width) || 150
  return w
})

const isRatioWidth = (w: number | string | undefined) => typeof w === 'number' && w > 0
const totalRatio = computed(() => {
  const cols = allFlatColumns.value.filter((c) => shouldShowColumn(c) && isRatioWidth(c.width))
  return cols.reduce((sum, c) => sum + (typeof c.width === 'number' ? c.width : 0), 0)
})

const fixedDataColumnsWidth = computed(() => {
  const cols = allFlatColumns.value.filter((c) => shouldShowColumn(c) && typeof c.width === 'string')
  return cols.reduce((sum, c) => sum + (Number(getColumnWidth(c)) || 80), 0)
})

const parseWidthPx = (v: number | string | undefined): number | null =>
  v == null ? null : typeof v === 'number' ? v : parseInt(String(v).replace(/px$/i, ''), 10) || null

/** spanMethod 适配器：给用户回调注入原始 ProColumn */
const spanMethodAdapter: TableProps<any>['spanMethod'] = (
  param: { row: any; column: any; rowIndex: number; columnIndex: number }
) => {
  if (!effectiveProps.value.spanMethod) return [1, 1]
  const original = flatColumnsMap.value.get(param.column.property)
  return effectiveProps.value.spanMethod({
    ...param,
    column: original ? {...original,...param.column } : { ...param.column, dataIndex: param.column.property, title: param.column.label },
  })
}

const getColumnWidth = (col: ProColumn): number | string | undefined => {
  const w = col.width
  if (isRatioWidth(w) && totalRatio.value > 0 && containerWidth.value > 0 && typeof w === 'number') {
    const available = containerWidth.value - fixedColumnsWidth.value - fixedDataColumnsWidth.value
    let result = Math.floor((available * w) / totalRatio.value)
    const minPx = parseWidthPx(col.minWidth) ?? 60
    const maxPx = parseWidthPx(col.maxWidth)
    result = Math.max(minPx, result)
    if (maxPx != null) result = Math.min(maxPx, result)
    return result
  }
  if (typeof w === 'string') {
    const basePx = parseWidthPx(w) ?? 80
    const minPx = parseWidthPx(col.minWidth)
    const maxPx = parseWidthPx(col.maxWidth)
    let result = basePx
    if (minPx != null) result = Math.max(minPx, result)
    if (maxPx != null) result = Math.min(maxPx, result)
    return result
  }
  return col.minWidth
}

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

/** 当前页可选行（未禁用） */
const selectableRows = computed(() => {
  const getDisabled = effectiveProps.value.rowSelection?.getCheckboxProps
  if (!getDisabled) return innerData.value
  return innerData.value.filter((row) => !getDisabled(row)?.disabled)
})

const hasSelectableRows = computed(() => selectableRows.value.length > 0)

/** 当前页是否全选 */
const isAllCurrentPageSelected = computed(() => {
  if (selectableRows.value.length === 0) return false
  return selectableRows.value.every((row) => selectedKeysSet.value.has(row[rowKeyField.value] as string | number))
})

/** 半选状态 */
const isIndeterminate = computed(() => {
  const selectedCount = selectableRows.value.filter((row) => selectedKeysSet.value.has(row[rowKeyField.value] as string | number)).length
  return selectedCount > 0 && selectedCount < selectableRows.value.length
})

const isRowSelected = (row: Record<string, unknown>) =>
  selectedKeysSet.value.has(row[rowKeyField.value] as string | number)

const getCheckboxDisabled = (row: Record<string, unknown>) =>
  effectiveProps.value.rowSelection?.getCheckboxProps?.(row)?.disabled ?? false

const getRadioDisabled = (row: Record<string, unknown>) =>
  effectiveProps.value.rowSelection?.getRadioProps?.(row)?.disabled ?? false

const emitSelectionChange = () => {
  const keys = selectedRows.value.map((r) => r[rowKeyField.value] as string | number)
  emit('selection-change', { keys, rows: selectedRows.value })
}

const handleCheckboxChange = (row: Record<string, unknown>, checked: boolean) => {
  const key = row[rowKeyField.value] as string | number
  if (checked) {
    selectedRows.value = [...selectedRows.value.filter((r) => r[rowKeyField.value] !== key), row]
  } else {
    selectedRows.value = selectedRows.value.filter((r) => r[rowKeyField.value] !== key)
  }
  emitSelectionChange()
}

const handleRadioSelect = (row: Record<string, unknown>) => {
  selectedRows.value = [row]
  emitSelectionChange()
}

const handleSelectAll = (checked: boolean) => {
  if (checked) {
    const keySet = new Set(selectedRows.value.map((r) => r[rowKeyField.value]))
    const toAdd = selectableRows.value.filter((row) => !keySet.has(row[rowKeyField.value]))
    selectedRows.value = [...selectedRows.value, ...toAdd]
  } else {
    const currentPageKeys = new Set(innerData.value.map((r) => r[rowKeyField.value]))
    selectedRows.value = selectedRows.value.filter((r) => !currentPageKeys.has(r[rowKeyField.value]))
  }
  emitSelectionChange()
}

const fetchData = async (opt?: FetchParams) => {
  if (!props.api) {
    if (props.dataSource) return
    localFullData.value = []
    return
  }
  loading.value = true
  try {
    const fs = effectiveProps.value.fetchSetting ?? {}
    const pageField = fs.pageField ?? 'page'
    const sizeField = fs.sizeField ?? 'pageSize'
    const listField = fs.listField ?? 'list'
    const totalField = fs.totalField ?? 'total'
    const params: Record<string, unknown> = {
      [pageField]: opt?.page ?? pagination.value.page,
      [sizeField]: opt?.pageSize ?? pagination.value.pageSize,
      ...props.searchInfo,
      ...opt?.searchInfo,
    }
    if (opt?.page != null) pagination.value.page = opt.page
    if (opt?.pageSize != null) pagination.value.pageSize = opt.pageSize
    const processedParams = props.beforeFetch ? props.beforeFetch(params) : params
    const res = await props.api!(processedParams)
    rawDataSource.value = (res || {}) as Record<string, unknown>
    const data = (props.afterFetch ? props.afterFetch(res) : res) as Record<string, unknown>
    const list = (data[listField] ?? data.items ?? data.list ?? []) as unknown[]
    const total = (data[totalField] ?? 0) as number
    localFullData.value = list as Record<string, unknown>[]
    pagination.value.total = total
    emit('fetch-success', { items: list, total })
  } catch (e) {
    localFullData.value = []
    emit('fetch-error', e)
  } finally {
    loading.value = false
  }
}

const handleReload = () => fetchData(undefined)
const handleSizeChange = (size: number) => {
  if (effectiveProps.value.clearSelectOnPageChange) {
    selectedRows.value = []
  }
  pagination.value.pageSize = size
  pagination.value.page = 1
  fetchData(undefined)
}
const handleCurrentChange = (page: number) => {
  if (effectiveProps.value.clearSelectOnPageChange) {
    selectedRows.value = []
  }
  pagination.value.page = page
  fetchData(undefined)
}
const handleRowClick = (row: Record<string, unknown>, _column: unknown, event: Event) => emit('row-click', row, event)
const handleRowDblclick = (row: Record<string, unknown>, _column: unknown, event: Event) => emit('row-dblclick', row, event)
const handleSortChange = ({ prop, order }: { prop: string; order: string }) => emit('sort-change', { prop, order })
const handleExpandChange = (row: Record<string, unknown>, expanded: boolean | Record<string, unknown>[]) => emit('expand-change', row, expanded)

const tableAction: TableActionType = {
  setProps: (p) => { innerProps.value = { ...innerProps.value, ...p } },
  reload: (opt) => fetchData(opt),
  redoHeight: () => { tableRef.value?.doLayout?.() },
  setLoading: (v) => { loading.value = v },
  /** 返回全量数据（API 模式为服务端返回的当前页数据，本地模式为原始全量数据） */
  getDataSource: () => localFullData.value,
  getRawDataSource: () => rawDataSource.value,
  /** 设置本地全量数据，同时同步 total */
  setTableData: (data) => {
    localFullData.value = data ?? []
    if (props.pagination !== false) pagination.value.total = (data ?? []).length
  },
  getColumns: () => innerColumns.value,
  setColumns: (cols) => {
    if (Array.isArray(cols) && cols.length > 0 && typeof cols[0] === 'string') {
      const keyList = cols as string[]
      const fromProps = (props.columns ?? []).filter((c) => keyList.includes((c.key ?? c.dataIndex) as string))
      const ordered = keyList.map((k) => fromProps.find((c) => (c.key ?? c.dataIndex) === k)).filter(Boolean) as ProColumn[]
      if (ordered.length) innerColumns.value = ordered
    } else {
      innerColumns.value = (cols as ProColumn[]) ?? []
    }
  },
  setPagination: (info) => {
    if (info?.page) pagination.value.page = info.page
    if (info?.pageSize) pagination.value.pageSize = info.pageSize
    if (info?.total !== undefined) pagination.value.total = info.total
  },
  getSelectRowKeys: () => selectedRows.value.map((r) => r[rowKeyField.value] as string | number),
  getSelectRows: () => selectedRows.value,
  clearSelectedRowKeys: () => { selectedRows.value = []; emitSelectionChange() },
  setSelectedRowKeys: (keys) => {
    const keySet = new Set(keys)
    const rows = localFullData.value.filter((r) => keySet.has(r[rowKeyField.value] as string | number))
    keys.forEach((k) => {
      if (!rows.some((r) => r[rowKeyField.value] === k)) {
        rows.push({ [rowKeyField.value]: k } as Record<string, unknown>)
      }
    })
    selectedRows.value = rows
    emitSelectionChange()
  },
  deleteSelectRowByKey: (key) => {
    selectedRows.value = selectedRows.value.filter((r) => r[rowKeyField.value] !== key)
    emitSelectionChange()
  },
  /** index 为当前页索引，自动转换为全量索引 */
  updateTableData: (index, key, value) => {
    const { page, pageSize } = pagination.value
    const fullIndex = (page - 1) * pageSize + index
    if (fullIndex < 0 || fullIndex >= localFullData.value.length) return
    localFullData.value = [...localFullData.value]
    localFullData.value[fullIndex] = { ...localFullData.value[fullIndex], [key]: value }
  },
  updateTableDataRecord: (rowKey, record) => {
    const idx = localFullData.value.findIndex((r) => r[rowKeyField.value] === rowKey)
    if (idx < 0) return
    localFullData.value = [...localFullData.value]
    localFullData.value[idx] = { ...localFullData.value[idx], ...record }
    return localFullData.value[idx]
  },
  deleteTableDataRecord: (rowKey) => {
    const keys = Array.isArray(rowKey) ? rowKey : [rowKey]
    const keySet = new Set(keys)
    localFullData.value = localFullData.value.filter((r) => !keySet.has(r[rowKeyField.value] as string | number))
    if (props.pagination !== false) pagination.value.total = localFullData.value.length
  },
  insertTableDataRecord: (record, index) => {
    const arr = [...localFullData.value]
    if (index == null || index >= arr.length) arr.push(record)
    else arr.splice(index, 0, record)
    localFullData.value = arr
    if (props.pagination !== false) pagination.value.total = localFullData.value.length
    return record
  },
  getPaginationRef: () =>
    showPagination.value
      ? { page: pagination.value.page, pageSize: Number(pagination.value.pageSize) || 10, total: pagination.value.total }
      : false,
  getShowPagination: () => showPagination.value,
  setShowPagination: (show) => { showPaginationRef.value = show },
  getRowSelection: () => effectiveProps.value.rowSelection,
  expandAll: () => {
    const childrenKey = effectiveProps.value.treeProps?.children ?? 'children'
    const flattenRows = (rows: Record<string, unknown>[]): Record<string, unknown>[] => {
      const result: Record<string, unknown>[] = []
      rows.forEach((row) => {
        result.push(row)
        const children = row[childrenKey] as Record<string, unknown>[] | undefined
        if (Array.isArray(children) && children.length > 0) {
          result.push(...flattenRows(children))
        }
      })
      return result
    }
    const allRows = flattenRows(localFullData.value)
    allRows.forEach((row) => tableRef.value?.toggleRowExpansion?.(row, true))
  },
  collapseAll: () => {
    const childrenKey = effectiveProps.value.treeProps?.children ?? 'children'
    const flattenRows = (rows: Record<string, unknown>[]): Record<string, unknown>[] => {
      const result: Record<string, unknown>[] = []
      rows.forEach((row) => {
        result.push(row)
        const children = row[childrenKey] as Record<string, unknown>[] | undefined
        if (Array.isArray(children) && children.length > 0) {
          result.push(...flattenRows(children))
        }
      })
      return result
    }
    const allRows = flattenRows(localFullData.value)
    allRows.forEach((row) => tableRef.value?.toggleRowExpansion?.(row, false))
  },
  scrollToColumn: (column: string | number) => {
    nextTick(() => {
      const table = tableRef.value
      if (!table) return
      const body = table.$el.querySelector('.el-table__body-wrapper') as HTMLElement
      if (!body) return

      const tableCols = (table as any).columns as {
        id: string
        columnIndex: number
        width: number | string
        colSpan: number
        isReal: boolean
        fixed: boolean | string
      }[]

      let columnId: string | undefined
      let targetCol: typeof tableCols[0] | undefined
      if (typeof column === 'number') {
        targetCol = tableCols[column]
        if (!targetCol) return
        columnId = targetCol.id
      } else {
        targetCol = tableCols.find((c) => c.id === column) ?? tableCols.find((c) => (c as any).property === column)
        if (!targetCol) return
        columnId = targetCol.id
      }

      const fixed = targetCol.fixed
      const isFixedLeft = fixed === true || fixed === 'left'
      const isFixedRight = fixed === 'right'

      if (isFixedLeft) {
        return
      }

      // 从 DOM 获取左侧固定列的真实渲染宽度
      const fixedLeftWrapper = table.$el.querySelector('.el-table__fixed') as HTMLElement | null
      let fixedLeftWidth = 0
      if (fixedLeftWrapper) {
        fixedLeftWidth = fixedLeftWrapper.offsetWidth
      }

      const headerTarget = table.$el.querySelector(`.${columnId}`) as HTMLElement | null
      if (!headerTarget) return

      // scrollLeft = 目标列左侧边缘相对滚动区域起始的位置
      // 滚动区域不含左侧固定列，所以需要减去固定列宽度
      const scrollLeft = headerTarget.offsetLeft - fixedLeftWidth

      body.scrollTo({ left: scrollLeft, behavior: 'smooth' })
    })
  },
}

defineExpose(tableAction)

const $scopedSlots = useSlots()
console.log($scopedSlots)
const syncColumns = () => {
  const assignIds = (cols: ProColumn[], parentKey = ''): ProColumn[] =>
    cols.map((c, i) => {
      const key = `${c.dataIndex}`
      return {
        ...c,
        dataIndex: key,
        children: c.children ? assignIds(c.children, key) : undefined,
      }
    })
  innerColumns.value = assignIds(props.columns ?? [])
}

const loadData = () => {
  if (props.api && effectiveProps.value.immediate !== false) {
    fetchData(undefined)
  } else if (props.dataSource) {
    localFullData.value = [...props.dataSource]
    if (!props.api && props.pagination !== false) {
      pagination.value.total = props.dataSource.length
    }
  }
}

const updateContainerWidth = () => {
  if (tableWrapRef.value) containerWidth.value = tableWrapRef.value.offsetWidth || 0
}

let resizeObserver: ResizeObserver | null = null
let observedEl: Element | null = null

onMounted(() => {
  syncColumns()
  emit('register', tableAction)
  loadData()
  if (typeof window !== 'undefined') {
    window.addEventListener('resize', updateContainerWidth)
    resizeObserver = new ResizeObserver(updateContainerWidth)
    nextTick(() => {
      updateContainerWidth()
      observedEl = tableWrapRef.value
      if (observedEl) resizeObserver?.observe(observedEl)
    })
  }
})

onUnmounted(() => {
  if (typeof window !== 'undefined') {
    window.removeEventListener('resize', updateContainerWidth)
    if (resizeObserver && observedEl) {
      resizeObserver.unobserve(observedEl)
      observedEl = null
    }
  }
})

watch(() => props.columns, syncColumns, { deep: true })
watch(() => props.dataSource, () => {
  if (!props.api && props.dataSource) {
    localFullData.value = [...props.dataSource]
    if (props.pagination !== false) pagination.value.total = props.dataSource.length
  }
}, { deep: true })
watch(() => props.loading, (v) => { loading.value = v ?? false })
</script>

<style>
.ecp-pro-table {
  padding: 16px;
  background: #fff;
  width: 100%;
  box-sizing: border-box;
}
.ecp-pro-table :deep(.el-table) {
  width: 100% !important;
}
.ecp-pro-table__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}
.ecp-pro-table__title-wrapper {
  display: flex;
  align-items: center;
  gap: 4px;
}
.ecp-pro-table__title {
  font-size: 16px;
  font-weight: 600;
}
.ecp-pro-table__help {
  color: #909399;
  cursor: help;
}
.ecp-pro-table__toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
}
.ecp-pro-table__body {
  width: 100%;
}
.ecp-pro-table__pagination {
  margin-top: 16px;
  display: flex;
  justify-content: flex-end;
}
.ecp-pro-table__col-help {
  margin-left: 4px;
  color: #909399;
  cursor: help;
}
</style>
