<template>
  <Dialog :title="title" v-model="dialogVisible" :appendToBody="true" width="1080">
    <ContentWrap>
      <!-- 新增查询表单区域 -->
      <div v-if="$slots.header" class="search-container">
        <slot name="header"></slot>
      </div>

      <el-table
        ref="tableRef"
        v-loading="loading"
        :data="list"
        :row-key="resolveRowKey"
        :show-overflow-tooltip="true"
        :stripe="true"
        @selection-change="handleSelectionChange"
        @row-click="handleRowClick"
      >
        <el-table-column
          type="selection"
          width="55"
          reserve-selection
          :selectable="isSelectionColumnSelectable"
        />
        <el-table-column
          v-for="column in columns"
          :key="column.prop || column.slotName"
          :label="column.label"
          :prop="column.slotName ? undefined : column.prop"
          :width="column.width"
          :min-width="column.minWidth"
          :align="column.align || 'center'"
          :fixed="column.fixed"
        >
          <template v-if="column.slotName" #default="scope">
            <slot :name="column.slotName" :row="scope.row"></slot>
          </template>
        </el-table-column>
      </el-table>
      <Pagination
        v-model:page="queryParams.pageNo"
        v-model:limit="queryParams.pageSize"
        :total="total"
        @pagination="getList"
      />
    </ContentWrap>
    <template #footer>
      <el-button type="primary" @click="submitSelection">确 定</el-button>
      <el-button @click="dialogVisible = false">取 消</el-button>
    </template>
  </Dialog>
</template>

<script setup lang="ts">
import type { ElTable } from 'element-plus'

defineOptions({ name: 'TableSelectDialog' })

type TableColumn = {
  label: string
  prop?: string
  slotName?: string
  width?: string | number
  minWidth?: string | number
  align?: 'left' | 'center' | 'right'
  fixed?: string | boolean
}

const props = withDefaults(
  defineProps<{
    title: string
    columns: TableColumn[]
    fetchApi: (params: Record<string, any>) => Promise<{ list: any[]; total: number }>
    selectionType?: 'single' | 'multiple'
    rowKey?: string
    pageSize?: number
    initialRows?: any[]
    queryParams?: Record<string, any>  // 新增
    selectable?: (row: any, index: number) => boolean
    /** ✅ 新增 */
    defaultSelectedKeys?: (string | number)[]
  }>(),
  {
    selectionType: 'multiple',
    rowKey: 'id',
    pageSize: 10,
    initialRows: () => [],
    queryParams: () => ({}),  // 默认值
    defaultSelectedKeys: () => []
  }
)

const emit = defineEmits<{
  (e: 'confirm', value: { ids: (number | string)[]; rows: any[] }): void
}>()

const dialogVisible = ref(false)
const loading = ref(false)
const list = ref<any[]>([])
const total = ref(0)
const tableRef = ref<InstanceType<typeof ElTable>>()
const queryParams = reactive({
  pageNo: 1,
  pageSize: props.pageSize
})
const selectedMap = ref(new Map<number | string, any>())
const syncingSelection = ref(false)
const isSingleSelect = computed(() => props.selectionType === 'single')

const resolveRowKey = (row: Record<string, any>) => row[props.rowKey]
const isRowSelectable = (row: any, index = list.value.findIndex((item) => resolveRowKey(item) === resolveRowKey(row))) => {
  return props.selectable ? props.selectable(row, index) : true
}
const isSelectionColumnSelectable = (row: any, index: number) => isRowSelectable(row, index)

const removeUnselectableSelections = () => {
  list.value.forEach((row, index) => {
    if (!isRowSelectable(row, index)) {
      selectedMap.value.delete(resolveRowKey(row))
    }
  })
}

const refreshSelectionOnTable = async () => {
  await nextTick()
  const table = tableRef.value
  if (!table) return
  syncingSelection.value = true
  try {
    table.clearSelection()
    const selectedIds = selectedMap.value
    list.value.forEach((row, index) => {
      const rowId = resolveRowKey(row)
      if (selectedIds.has(rowId) && isRowSelectable(row, index)) {
        table.toggleRowSelection(row, true)
      }
    })
  } finally {
    syncingSelection.value = false
  }
}
/**
 * ✅ 新增：根据 defaultSelectedKeys 初始化选中状态
 */
const initDefaultSelection = () => {
  if (!props.defaultSelectedKeys.length) return

  props.defaultSelectedKeys.forEach((key) => {
    selectedMap.value.set(key, { [props.rowKey]: key })
  })
}

const getList = async () => {
  loading.value = true
  try {
    const params = getQueryParams()
    const data = await props.fetchApi(params)
    list.value = data.list || []
    total.value = data.total || 0
    removeUnselectableSelections()
    await refreshSelectionOnTable()
  } finally {
    loading.value = false
  }
}

const handleSelectionChange = (rows: any[]) => {
  if (syncingSelection.value) return
  const selectableRows = rows.filter((row) => isRowSelectable(row))
  if (isSingleSelect.value) {
    selectedMap.value.clear()
    const latestRow = selectableRows.length ? selectableRows[selectableRows.length - 1] : undefined
    if (latestRow) {
      selectedMap.value.set(resolveRowKey(latestRow), latestRow)
    }
    void refreshSelectionOnTable()
    return
  }
  const pageIdSet = new Set(list.value.map((item) => resolveRowKey(item)))
  pageIdSet.forEach((id) => {
    selectedMap.value.delete(id)
  })
  selectableRows.forEach((row) => {
    selectedMap.value.set(resolveRowKey(row), row)
  })
}

const handleRowClick = (row: any) => {
  if (!isSingleSelect.value) return
  if (!isRowSelectable(row)) return
  const table = tableRef.value
  if (!table) return
  syncingSelection.value = true
  try {
    table.clearSelection()
    table.toggleRowSelection(row, true)
  } finally {
    syncingSelection.value = false
  }
  selectedMap.value.clear()
  selectedMap.value.set(resolveRowKey(row), row)
}

const open = async (rows?: any[]) => {
 /* selectedMap.value.clear()
  const initialRows = rows || props.initialRows
  const nextRows = isSingleSelect.value ? initialRows.slice(0, 1) : initialRows
  nextRows.forEach((row) => {
    selectedMap.value.set(resolveRowKey(row), row)
  })
  queryParams.pageNo = 1
  queryParams.pageSize = props.pageSize
  dialogVisible.value = true
  await getList()*/
  selectedMap.value.clear()

  // ✅ 优先使用 defaultSelectedKeys
  if (props.defaultSelectedKeys.length) {
    initDefaultSelection()
  }

  // ✅ 兼容原来的 initialRows / rows
  const initialRows = rows || props.initialRows
  const nextRows = isSingleSelect.value ? initialRows.slice(0, 1) : initialRows
  nextRows.forEach((row) => {
    selectedMap.value.set(resolveRowKey(row), row)
  })

  queryParams.pageNo = 1
  queryParams.pageSize = props.pageSize
  dialogVisible.value = true
  await getList()
}

const submitSelection = () => {
  const rows = Array.from(selectedMap.value.values())
  const ids = rows.map((row) => resolveRowKey(row))
  emit('confirm', { ids, rows })
  dialogVisible.value = false
}

// 暴露给父组件的方法
const reload =async () => {
  loading.value = true
  // 这里是你组件内部原有的加载数据逻辑
  await getList()
}

// 3. 合并参数：将父组件传入的 queryParams 与内部参数合并
const getQueryParams = () => {
  return {
    pageNo: queryParams.pageNo || 1,
    pageSize: queryParams.pageSize || 10,
    ...props.queryParams  // 父组件传入的查询条件
  }
}
// 4. 监听父组件参数变化
watch(() => props.queryParams, async () => {
  await getList()
}, { deep: true })

defineExpose({ open,  reload })
</script>
<style scoped>
.search-container {
  margin-bottom: 10px;
  padding: 0 0px;
}
</style>
