<template>
    <div class="editable-table">
        <el-form ref="formRef" :model="{}" label-width="120px" size="small">
            <el-button type="primary" size="default" style="margin: 12px 0" @click="addRow" :disabled="disabled">
                添加一行
            </el-button>
            <el-table :data="internalData" border style="width: 100%" :row-style="{ height: '48px' }"
                :cell-style="{ padding: '6px 0' }">
                <el-table-column v-for="field in rowConfig" :key="field.prop" :label="field.label" :width="field.width"
                    :min-width="field.minWidth">
                    <template #default="{ row }">
                        <component :is="getFieldComponent(field.type)" v-bind="getFieldProps(field, row.data)"
                            @update:model-value="val => handleFieldChange(val, field, row)"
                            @option-change="option => handleOptionChange(option, field, row)"
                            @focus="() => loadRemoteOptions(field)"
                            @filter-change="keyword => handleFilterChange(keyword, field)"
                            :disabled="!!field.disabled || disabled" />
                    </template>
                </el-table-column>

                <el-table-column label="操作" width="100" fixed="right">
                    <template #default="{ $index }">
                        <el-button type="danger" size="small" link @click="removeRow($index)" :disabled="disabled">
                            删除
                        </el-button>
                    </template>
                </el-table-column>
            </el-table>


            <!-- <el-button
        type="success"
        size="small"
        style="margin-left: 12px"
        @click="batchSave"
        :disabled="disabled"
      >
        批量保存
      </el-button> -->
        </el-form>
    </div>
</template>

<script setup>
import { ref, watch, nextTick } from 'vue'
import SelectField from '@/components/csf-form/fields/SelectField.vue'
import InputField from '@/components/csf-form/fields/InputField.vue'
import UploadField from '@/components/csf-form/fields/UploadField.vue'
import { deepEqual } from '@/utils/csf-deepEqual'
import request from '@/utils/request'
const props = defineProps({
    modelValue: {
        type: Array,
        default: () => []
    },
    rowConfig: {
        type: Array,
        required: true
    },
    disabled: {
        type: Boolean,
        default: false
    }
})

const emit = defineEmits(['update:modelValue', 'batch-save'])

const formRef = ref()
const internalData = ref([])

// 远程加载状态 & 缓存
const remoteLoading = ref({})
const optionsCache = ref(new Map()) // prop -> options

// 初始化 internalData
watch(
    () => props.modelValue,
    (newVal) => {
        if (!Array.isArray(newVal)) {
            console.warn('[EditableTable] modelValue is not an array, reset to empty array')
            internalData.value = []
            return
        }

        const currentPlain = internalData.value.map(row => {
            const { id, ...rest } = row.data
            return { ...rest, id: row.id }
        })

        if (!deepEqual(newVal, currentPlain)) {
            internalData.value = newVal.map((item, index) => ({
                id: item.id || Symbol(`row-${index}`),
                data: { ...(item || {}) }
            }))
        }
    },
    { immediate: true }
)

// 同步 internalData → modelValue
let isEmitting = false
watch(
    internalData,
    (newVal) => {
        if (isEmitting) return

        const plainData = newVal.map(row => {
            const { id, ...rest } = row.data
            return { ...rest, id: row.id }
        })

        if (!deepEqual(plainData, props.modelValue)) {
            isEmitting = true
            emit('update:modelValue', plainData)
            nextTick(() => {
                isEmitting = false
            })
        }
    },
    { deep: true }
)

// 字段组件映射
function getFieldComponent(type) {
    switch (type) {
        case 'select':
            return SelectField
        case 'input':
            return InputField
        case 'upload':
            return UploadField
        default:
            return InputField
    }
}

// 获取字段属性
function getFieldProps(field, rowData) {
    const base = {
        modelValue: rowData[field.prop],
        'onUpdate:modelValue': (val) => {
            rowData[field.prop] = val
        }
    }

    switch (field.type) {
        case 'select':
            return {
                ...base,
                multiple: !!field.multiple,
                clearable: true,
                filterable: true,
                loading: remoteLoading.value[field.prop] || false,
                options: optionsCache.value.get(field.prop) || field.options || [],
                placeholder: field.placeholder || `请选择${field.label}`
            }
        case 'input':
            return {
                ...base,
                placeholder: field.placeholder || `请输入${field.label}`
            }
        case 'upload':
            return {
                ...base,
                uploadUrl: field.uploadUrl,
                maxCount: field.maxCount || 1,
                showFileList: field.showFileList !== false
            }
        default:
            return base
    }
}

// 处理字段变更（基础）
function handleFieldChange(val, field, row) {
    row.data[field.prop] = val
}

// 处理 select 选中（带完整 option）
function handleOptionChange(option, field, row) {
    if (!option || !field.onChangeExtraFields) return

    // 兼容对象和数组格式
    let extras = []
    if (Array.isArray(field.onChangeExtraFields)) {
        extras = field.onChangeExtraFields
    } else if (typeof field.onChangeExtraFields === 'object') {
        extras = Object.entries(field.onChangeExtraFields).map(([targetProp, sourceKey]) => ({
            targetProp,
            sourceKey
        }))
    }

    for (const { targetProp, sourceKey } of extras) {
        if (!targetProp || sourceKey == null) continue
        const getValue = (obj, path) => path.split('.').reduce((o, k) => o?.[k], obj)
        const extraValue = getValue(option, sourceKey)
        row.data[targetProp] = extraValue
    }
}

// 加载远程选项（初始加载）
async function loadRemoteOptions(field) {
    if (!field.api || optionsCache.value.has(field.prop)) return

    const key = field.prop
    remoteLoading.value[key] = true
    try {
        const params = {
            ...(field.requestParams || {}),
            [field.keywordField || 'keyword']: ''
        }
        const res = await request(field.api, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            data: JSON.stringify(params)
        }).then(r => r)

        const list = field.transform ? field.transform(res) : (res?.data?.records || [])
        optionsCache.value.set(key, list)
    } catch (err) {
        console.error(`Failed to load options for ${field.prop}:`, err)
    } finally {
        remoteLoading.value[key] = false
    }
}

// 搜索过滤（暂不实现，可扩展）
function handleFilterChange(keyword, field) {
    // 可在此实现远程搜索
}

// 行操作
function addRow() {
    internalData.value.push({
        data: {}
    })
}

function removeRow(index) {
    internalData.value.splice(index, 1)
}

function batchSave() {
    emit('batch-save', internalData.value.map(row => ({ ...row.data, id: row.id })))
}
</script>

<style scoped>
.editable-table :deep(.el-input__wrapper),
.editable-table :deep(.el-select__wrapper) {
    box-shadow: none !important;
}
</style>