<template>
    <el-form
        size="large"
        label-width="auto"
        :model="formData"
        ref="formRef"
        :rules="rules"
        class="add-and-edit-form"
    >
        <el-form-item label="分组名称" prop="groupName">
            <el-input
                clearable
                maxlength="50"
                show-word-limit
                placeholder="请输入分组名称"
                v-model.trim="formData.groupName"
            />
        </el-form-item>

        <el-form-item label="选择组员" prop="workerList" class="member-select-item">
            <div class="member-select-container">
                <!-- 左侧：可选人员列表 -->
                <div class="member-list-left">
                    <div class="search-bar">
                        <el-row style="width: 100%">
                            <el-col :span="12">
                                <el-input
                                    v-model="searchDept"
                                    placeholder="输入部门名称"
                                    clearable
                                    prefix-icon="Search"
                                    style="width: 99%"
                                />
                            </el-col>
                            <el-col :span="12" style="text-align: right">
                                <el-input
                                    v-model="searchName"
                                    placeholder="输入人员姓名"
                                    clearable
                                    prefix-icon="Search"
                                    style="width: 99%"
                                />
                            </el-col>
                        </el-row>
                    </div>
                    <div class="table-container">
                        <el-auto-resizer>
                            <template #default="{ height, width }">
                                <el-table-v2
                                    ref="personTableRef"
                                    :columns="tableColumns"
                                    :data="filteredPersonList"
                                    :width="width"
                                    :height="height"
                                    row-key="id"
                                    fixed
                                />
                            </template>
                        </el-auto-resizer>
                    </div>
                </div>

                <!-- 右侧：已选人员列表 -->
                <div class="member-list-right">
                    <div class="selected-header">
                        <span>已选人员</span>
                        <el-button
                            type="text"
                            size="small"
                            @click="handleClearAll"
                            :disabled="selectedMembers.length === 0"
                        >
                            清空
                        </el-button>
                    </div>
                    <div class="selected-list">
                        <div
                            v-for="member in selectedMembers"
                            :key="member.id"
                            class="selected-item"
                        >
                            <span>{{ member.workerName }}</span>
                            <el-icon class="remove-icon" @click="handleRemoveMember(member.id)">
                                <Close />
                            </el-icon>
                        </div>
                        <div v-if="selectedMembers.length === 0" class="empty-tip">
                            暂无已选人员
                        </div>
                    </div>
                </div>
            </div>
        </el-form-item>

        <el-form-item label="备注" prop="remark">
            <el-input
                type="textarea"
                :rows="3"
                maxlength="200"
                show-word-limit
                placeholder="请输入备注"
                v-model.trim="formData.remark"
            />
        </el-form-item>
    </el-form>
</template>

<script setup name="AddAndEditForm">
import { ref, computed, watch, onMounted, nextTick, h } from 'vue'
import { ElCheckbox } from 'element-plus'
import { getAllPersonAPI } from '@/api/personManage/person.js'
import { Close } from '@element-plus/icons-vue'
import { debounce } from '@/utils'

const props = defineProps({
    formData: {
        type: Object,
        default: () => ({}),
    },
})

const formRef = ref(null)
const personTableRef = ref(null)
const searchDept = ref('') // 部门搜索关键词
const searchName = ref('') // 姓名搜索关键词
const personList = ref([])
const selectedPersonList = ref([])
// 标志位：是否正在同步选中状态，防止循环触发
const isSyncing = ref(false)
// 已选人员Map缓存（优化性能）
const selectedMembersMap = ref(new Map())
// 防抖后的过滤函数
const debouncedFilter = ref(null)
// 已选中行的keys（用于虚拟化表格）
const selectedRowKeys = ref([])
// 已选中行的Set（优化查找性能）
const selectedIdsSet = computed(() => {
    if (!props.formData.workerList || props.formData.workerList.length === 0) {
        return new Set()
    }
    return new Set(props.formData.workerList.map((id) => Number(id)))
})

// 虚拟化表格列配置
const tableColumns = computed(() => {
    return [
        {
            key: 'selection',
            width: 55,
            cellRenderer: ({ rowData }) => {
                const isSelected = selectedRowKeys.value.includes(rowData.id)
                return h(ElCheckbox, {
                    modelValue: isSelected,
                    'onUpdate:modelValue': (val) => {
                        handleRowSelect({ row: rowData, checked: val })
                    },
                })
            },
            headerCellRenderer: () => {
                const allSelected =
                    filteredPersonList.value.length > 0 &&
                    filteredPersonList.value.every((row) => selectedRowKeys.value.includes(row.id))
                const someSelected = filteredPersonList.value.some((row) =>
                    selectedRowKeys.value.includes(row.id),
                )

                return h(ElCheckbox, {
                    modelValue: allSelected,
                    indeterminate: someSelected && !allSelected,
                    'onUpdate:modelValue': (val) => {
                        handleSelectAll({ checked: val })
                    },
                })
            },
        },
        {
            key: 'orgName',
            dataKey: 'orgName',
            title: '人员所属',
            width: 150,
        },
        {
            key: 'workerName',
            dataKey: 'workerName',
            title: '姓名',
            width: 120,
        },
        {
            key: 'sex',
            dataKey: 'sex',
            title: '性别',
            width: 80,
            cellRenderer: ({ rowData }) => {
                return rowData.sex == 1 ? '男' : '女'
            },
        },
        {
            key: 'phone',
            dataKey: 'phone',
            title: '电话',
            width: 200,
        },
    ]
})

// 表单验证规则
const rules = {
    groupName: [{ required: true, message: '请输入分组名称', trigger: 'blur' }],
    workerList: [
        {
            required: true,
            message: '请至少选择一个组员',
            trigger: 'change',
            validator: (rule, value, callback) => {
                if (!value || value.length === 0) {
                    callback(new Error('请至少选择一个组员'))
                } else {
                    callback()
                }
            },
        },
    ],
}

// 过滤后的人员列表（使用ref避免频繁计算）
const filteredPersonList = ref([])

// 执行过滤操作（优化后的版本）
const performFilter = () => {
    if (personList.value.length === 0) {
        filteredPersonList.value = []
        return
    }

    let filtered = personList.value

    // 部门过滤
    if (searchDept.value) {
        const deptKeyword = searchDept.value.toLowerCase()
        filtered = filtered.filter((item) => {
            const org = (item.orgName || '').toLowerCase()
            return org.includes(deptKeyword)
        })
    }

    // 姓名过滤
    if (searchName.value) {
        const nameKeyword = searchName.value.toLowerCase()
        filtered = filtered.filter((item) => {
            const name = (item.workerName || '').toLowerCase()
            return name.includes(nameKeyword)
        })
    }

    filteredPersonList.value = filtered

    // 过滤后同步选中状态
    nextTick(() => {
        syncTableSelection()
    })
}

// 创建防抖过滤函数
const createDebouncedFilter = () => {
    debouncedFilter.value = debounce(performFilter, 300)
}

// 已选人员列表（优化：使用Map缓存，避免频繁遍历）
const selectedMembers = computed(() => {
    if (!props.formData.workerList || props.formData.workerList.length === 0) {
        selectedMembersMap.value.clear()
        return []
    }

    // 如果Map已存在且大小匹配，直接使用缓存
    if (selectedMembersMap.value.size === props.formData.workerList.length) {
        const cachedIds = Array.from(selectedMembersMap.value.keys())
        const currentIds = props.formData.workerList.map((id) => Number(id))
        const idsMatch =
            cachedIds.every((id) => currentIds.includes(id)) &&
            currentIds.every((id) => cachedIds.includes(id))
        if (idsMatch) {
            return Array.from(selectedMembersMap.value.values())
        }
    }

    // 重新构建Map和数组
    selectedMembersMap.value.clear()
    const result = []
    const selectedIdsSet = new Set(props.formData.workerList.map((id) => Number(id)))

    // 只遍历一次，同时构建Map和数组
    for (const item of personList.value) {
        if (selectedIdsSet.has(Number(item.id))) {
            selectedMembersMap.value.set(Number(item.id), item)
            result.push(item)
        }
    }

    return result
})

// 获取人员列表
const getPersonList = async () => {
    try {
        const result = await getAllPersonAPI()

        if (result.code === 200) {
            // 处理返回数据，可能是 result.rows 或 result.data 或直接是数组
            const data = result.rows || result.data || result || []
            personList.value = data.map((item) => ({
                id: item.id,
                workerName: item.workerName,
                orgName: item.orgName,
                sex: item.sex,
                phone: item.phone,
            }))

            // 初始化过滤列表
            performFilter()

            // 人员列表加载完成后，watch 监听器会自动处理选中状态同步
            // 不需要在这里手动调用 syncTableSelection，避免循环触发
        }
    } catch (error) {
        console.error('获取人员列表失败:', error)
        // 重置同步标志，防止卡死
        isSyncing.value = false
    }
}

// 监听formData.workerList变化，同步表格选中状态
watch(
    () => props.formData.workerList,
    (newVal, oldVal) => {
        // 如果正在同步中，跳过，防止循环触发
        if (isSyncing.value) {
            return
        }
        // 只有当人员列表已加载时才同步（包括空数组的情况）
        if (personList.value.length > 0) {
            // 检查值是否真的变化了（避免不必要的同步）
            const newValStr = JSON.stringify((newVal || []).sort())
            const oldValStr = oldVal ? JSON.stringify(oldVal.sort()) : ''
            if (newValStr !== oldValStr) {
                nextTick(() => {
                    syncTableSelection()
                })
            }
        }
    },
    { deep: true },
)

// 监听人员列表加载完成，同步选中状态
watch(
    () => personList.value.length,
    (newLength, oldLength) => {
        // 如果正在同步中，跳过
        if (isSyncing.value) {
            return
        }
        // 当人员列表从0变为有数据时，如果有已选人员，同步选中状态
        if (
            oldLength === 0 &&
            newLength > 0 &&
            props.formData.workerList &&
            props.formData.workerList.length > 0
        ) {
            nextTick(() => {
                syncTableSelection()
            })
        }
    },
)

// 同步表格选中状态（优化：使用Set提高查找性能，批量操作）
const syncTableSelection = () => {
    // 如果正在同步中，跳过，避免重复同步
    if (isSyncing.value) {
        return
    }

    // 设置同步标志，防止触发 watch
    isSyncing.value = true

    if (!props.formData.workerList || props.formData.workerList.length === 0) {
        // 如果没有选中项，清空所有选中状态
        selectedRowKeys.value = []
        nextTick(() => {
            isSyncing.value = false
        })
        return
    }

    // 使用computed的Set提高查找性能
    const idsSet = selectedIdsSet.value

    // 只同步当前过滤列表中可见的选中项
    const visibleSelectedKeys = filteredPersonList.value
        .filter((row) => idsSet.has(Number(row.id)))
        .map((row) => row.id)

    selectedRowKeys.value = visibleSelectedKeys

    // 同步完成后，延迟重置标志位
    nextTick(() => {
        isSyncing.value = false
    })
}

// 虚拟化表格：单行选择变化
const handleRowSelect = ({ row, checked }) => {
    if (isSyncing.value) {
        return
    }

    isSyncing.value = true

    const rowId = Number(row.id)
    const allSelectedIds = new Set(props.formData.workerList || [])

    if (checked) {
        allSelectedIds.add(rowId)
        if (!selectedRowKeys.value.includes(row.id)) {
            selectedRowKeys.value.push(row.id)
        }
    } else {
        allSelectedIds.delete(rowId)
        const index = selectedRowKeys.value.indexOf(row.id)
        if (index > -1) {
            selectedRowKeys.value.splice(index, 1)
        }
    }

    props.formData.workerList = Array.from(allSelectedIds)

    nextTick(() => {
        isSyncing.value = false
    })
}

// 虚拟化表格：全选/取消全选（优化：批量处理，避免逐个操作）
const handleSelectAll = ({ checked }) => {
    if (isSyncing.value) {
        return
    }

    isSyncing.value = true

    const allSelectedIds = new Set(props.formData.workerList || [])
    const currentFilteredIds = filteredPersonList.value.map((item) => Number(item.id))

    if (checked) {
        // 全选：添加当前过滤列表中的所有项
        currentFilteredIds.forEach((id) => {
            allSelectedIds.add(id)
        })
        selectedRowKeys.value = filteredPersonList.value.map((row) => row.id)
    } else {
        // 取消全选：只移除当前过滤列表中的项
        currentFilteredIds.forEach((id) => {
            allSelectedIds.delete(id)
        })
        // 清空当前可见的选中keys
        selectedRowKeys.value = []
    }

    props.formData.workerList = Array.from(allSelectedIds)

    nextTick(() => {
        isSyncing.value = false
    })
}

// 移除单个已选人员（优化：直接过滤，避免查找，并同步更新选中状态）
const handleRemoveMember = (memberId) => {
    if (!props.formData.workerList) {
        props.formData.workerList = []
        selectedRowKeys.value = []
        return
    }

    const memberIdNum = Number(memberId)

    // 设置同步标志，防止 watch 触发时重复处理
    isSyncing.value = true

    // 更新 workerList
    props.formData.workerList = props.formData.workerList.filter((id) => Number(id) !== memberIdNum)

    // 立即更新 selectedRowKeys，确保左侧表格选中状态同步
    // 从 selectedRowKeys 中移除该人员（无论是否在当前过滤列表中）
    const index = selectedRowKeys.value.findIndex((id) => Number(id) === memberIdNum)
    if (index > -1) {
        selectedRowKeys.value.splice(index, 1)
    }

    // 重置同步标志，并确保选中状态完全同步
    // 使用 nextTick 确保 DOM 更新完成后再同步
    nextTick(() => {
        isSyncing.value = false
        // 再次同步，确保状态一致（处理该人员不在当前过滤列表中的情况）
        syncTableSelection()
    })
}

// 清空所有已选人员（优化：直接清空，避免遍历）
const handleClearAll = () => {
    // 设置同步标志，防止触发 watch
    isSyncing.value = true
    props.formData.workerList = []
    selectedRowKeys.value = []
    nextTick(() => {
        isSyncing.value = false
    })
}

// 监听搜索关键词变化，使用防抖优化性能
watch([() => searchDept.value, () => searchName.value], () => {
    if (personList.value.length > 0) {
        // 使用防抖函数，避免频繁过滤
        if (debouncedFilter.value) {
            debouncedFilter.value()
        } else {
            performFilter()
        }
    }
})

onMounted(() => {
    // 创建防抖过滤函数
    createDebouncedFilter()
    // 获取人员列表
    getPersonList()
})

// 暴露校验方法和重置方法给父组件
defineExpose({
    validate: () => formRef.value.validate(),
    resetFields: () => formRef.value.resetFields(),
    clearValidate: () => formRef.value.clearValidate(),
})
</script>

<style lang="scss" scoped>
.add-and-edit-form {
    padding: 10px 20px;

    .member-select-item {
        :deep(.el-form-item__content) {
            width: 100%;
        }
    }

    .member-select-container {
        display: flex;
        gap: 20px;
        width: 100%;
        border: 1px solid #dcdfe6;
        border-radius: 4px;
        padding: 15px;
        background: #fafafa;
    }

    .member-list-left {
        flex: 1;
        display: flex;
        flex-direction: column;

        .search-bar {
            margin-bottom: 10px;

            :deep(.el-row) {
                width: 100%;
            }

            :deep(.el-col) {
                padding: 0;
            }
        }

        .table-container {
            flex: 1;
            border: 1px solid #dcdfe6;
            border-radius: 4px;
            overflow: hidden;
            background: #fff;
            height: 300px;
            min-height: 300px;
        }
    }

    .member-list-right {
        width: 200px;
        display: flex;
        flex-direction: column;
        border: 1px solid #dcdfe6;
        border-radius: 4px;
        background: #fff;

        .selected-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 10px 15px;
            border-bottom: 1px solid #dcdfe6;
            font-weight: 500;
        }

        .selected-list {
            flex: 1;
            padding: 10px;
            overflow-y: auto;
            max-height: 300px;

            .selected-item {
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding: 2px 10px;
                margin-bottom: 5px;
                background: #f0f9ff;
                border: 1px solid #b3d8ff;
                border-radius: 4px;
                cursor: pointer;
                transition: all 0.3s;

                &:hover {
                    background: #e1f3ff;
                    border-color: #409eff;
                }

                .remove-icon {
                    color: #909399;
                    cursor: pointer;
                    font-size: 16px;

                    &:hover {
                        color: #f56c6c;
                    }
                }
            }

            .empty-tip {
                text-align: center;
                color: #909399;
                padding: 20px;
            }
        }
    }
}
</style>

