<template>
  <div class="select-table-list">
    <el-input
      v-model="displayValue"
      :placeholder="placeholder"
      :readonly="readonly || disabled"
      :disabled="disabled"
      clearable
      @input="handleInputPrevent"
      @click="openSelector"
      @clear="handleClear"
    >
      <template #suffix>
        <el-icon
          v-if="!readonly && !disabled"
          class="search-icon"
          @click="openSelector"
        >
          <Search />
        </el-icon>
      </template>
    </el-input>

    <!-- 选择弹窗 -->
    <el-dialog
      :title="title"
      v-model="dialogVisible"
      :width="width"
      :height="height"
      :close-on-click-modal="false"
      append-to-body
      class="noPadding-body-dialog"
    >
      <TableList
        ref="tableRef"
        :config="tableConfig"
        @selection-change="handleSelection"
      />
      <template #footer>
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="confirmSelection">确 定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { Search } from '@element-plus/icons-vue'
import TableList from '@/components/TableList/index.vue'
import type { TableListConfig } from '@/components/TableList/types'

export interface SelectTableListProps {
  // 基础配置
  modelValue?: any // v-model绑定的值
  placeholder?: string // 输入框占位符
  title?: string // 弹窗标题
  width?: string // 弹窗宽度
  height?: string // 弹窗高度
  disabled?: boolean // 是否禁用
  readonly?: boolean // 是否只读
  
  // 选择配置
  multiple?: boolean // 是否多选
  labelKey?: string // 显示字段名
  valueKey?: string // 值字段名
  
  // 字段映射
  fieldMapping?: Record<string, string> // 字段映射关系
  
  // 表格配置
  tableConfig: TableListConfig // 表格配置
  
  // 显示值配置
  displayValue?: string // 显示的值
}

export interface SelectTableListEmits {
  (e: 'update:modelValue', value: any): void
  (e: 'update:displayValue', value: string): void
  (e: 'change', data: SelectionChangeData): void
  (e: 'clear', data: ClearData): void
  (e: 'selection-confirm', data: SelectionConfirmData): void
}

export interface SelectionChangeData {
  selectedRows: any[]
  selectedValues: any[]
  selectedLabels: string[]
  mode: 'single' | 'multiple'
}

export interface ClearData {
  field: string
  clearedFields: string[]
}

export interface SelectionConfirmData {
  selectedRows: any[]
  selectedValues: any[]
  selectedLabels: string[]
  mappedFields?: Record<string, any>
  mode: 'single' | 'multiple'
}

const props = withDefaults(defineProps<SelectTableListProps>(), {
  placeholder: '请选择',
  title: '选择数据',
  width: '900px',
  height: '600px',
  disabled: false,
  readonly: false,
  multiple: false,
  labelKey: 'id',
  valueKey: 'id'
})

const emit = defineEmits<SelectTableListEmits>()

// 响应式数据
const dialogVisible = ref(false)
const selectedRows = ref<any[]>([])
const tableRef = ref()

// 计算属性
const displayValue = computed({
  get: () => props.displayValue || '',
  set: (value: string) => {
    emit('update:displayValue', value)
  }
})

// 内部表格配置
const internalTableConfig = computed(() => {
  const config = { ...props.tableConfig }
  // 确保表格选择模式与props.multiple一致
  if (config.table) {
    config.table.selection = props.multiple
  }
  return config
})

/** 打开选择器 */
const openSelector = () => {
  if (props.readonly || props.disabled) return
  dialogVisible.value = true
  selectedRows.value = []
}

/** 阻止输入框直接输入 */
const handleInputPrevent = (event: any) => {
  // 立即将值还原，防止用户直接输入
  nextTick(() => {
    if (selectedRows.value.length === 0) {
      emit('update:displayValue', '')
    }
  })
}

/** 清空选择 */
const handleClear = () => {
  if (props.readonly || props.disabled) return

  // 清空值
  emit('update:modelValue', props.multiple ? [] : '')
  emit('update:displayValue', '')

  // 清空选择的数据
  selectedRows.value = []

  // 计算需要清空的字段
  const clearedFields = ['modelValue', 'displayValue']
  if (props.fieldMapping) {
    clearedFields.push(...Object.keys(props.fieldMapping))
  }

  // 触发清空事件
  emit('clear', {
    field: 'selectTableList',
    clearedFields
  })

  // 触发变化事件
  emit('change', {
    selectedRows: [],
    selectedValues: props.multiple ? [] : '',
    selectedLabels: [],
    mode: props.multiple ? 'multiple' : 'single'
  })
}

/** 处理表格选择变化 */
const handleSelection = (rows: any[]) => {
  selectedRows.value = rows
}

/** 确认选择 */
const confirmSelection = () => {
  if (selectedRows.value.length === 0) {
    dialogVisible.value = false
    return
  }

  const valueKey = props.valueKey
  const labelKey = props.labelKey

  let selectedValues: any
  let selectedLabels: string[]
  let mappedFields: Record<string, any> = {}

  if (props.multiple) {
    // 多选模式
    selectedValues = selectedRows.value.map(row => row[valueKey])
    selectedLabels = selectedRows.value.map(row => row[labelKey])
    
    // 处理字段映射（多选模式下，只取第一行的映射值）
    if (props.fieldMapping && selectedRows.value.length > 0) {
      const firstRow = selectedRows.value[0]
      Object.entries(props.fieldMapping).forEach(([targetField, sourceField]) => {
        mappedFields[targetField] = firstRow[sourceField]
      })
    }
  } else {
    // 单选模式
    const selectedRow = selectedRows.value[0]
    selectedValues = selectedRow[valueKey]
    selectedLabels = [selectedRow[labelKey]]
    
    // 处理字段映射
    if (props.fieldMapping) {
      Object.entries(props.fieldMapping).forEach(([targetField, sourceField]) => {
        mappedFields[targetField] = selectedRow[sourceField]
      })
    }
  }

  // 更新值
  emit('update:modelValue', selectedValues)
  emit('update:displayValue', selectedLabels.join(', '))

  // 触发变化事件
  emit('change', {
    selectedRows: selectedRows.value,
    selectedValues,
    selectedLabels,
    mode: props.multiple ? 'multiple' : 'single'
  })

  // 触发确认事件
  emit('selection-confirm', {
    selectedRows: selectedRows.value,
    selectedValues,
    selectedLabels,
    mappedFields,
    mode: props.multiple ? 'multiple' : 'single'
  })

  dialogVisible.value = false
}

/** 暴露方法给父组件 */
defineExpose({
  openSelector,
  clearSelection: handleClear
})
</script>

<style scoped>
.select-table-list {
  .search-icon {
    cursor: pointer;
    color: var(--el-text-color-regular);
    
    &:hover {
      color: var(--el-color-primary);
    }
  }
}

:deep(.noPadding-body-dialog .el-dialog__body) {
  padding: 0;
}
</style>