<template>
	<el-select
		ref="selectRef"
		popper-class="deviceSelectorPopper"
		class="deviceSelector"
		v-model="data"
		placeholder="请选择设备"
		@visible-change="visibleChange"
		clearable
		filterable
		remote
		:remote-method="remoteMethod"
		:loading="loading"
		@change="onSelectChange"
	>
		<el-option
			v-for="item in options"
			:key="item[tableConfig.value]"
			:label="item[tableConfig.label]"
			:value="item[tableConfig.value]"
		>
			<div class="option-item">{{ item[tableConfig.label] }}
				<!-- <span class="option-label"></span>
				<span v-if="item.code" class="option-code">{{ item.code }}</span> -->
			</div>
		</el-option>
		<template #empty>
			<div v-if="!loading" class="empty-content">
				<div v-if="options.length === 0" class="no-data">暂无数据</div>
				<div v-else-if="hasMore" class="load-more-wrapper">
					<el-button 
						link 
						type="primary" 
						@click="loadMore"
						:loading="loadingMore"
					>
						加载更多
					</el-button>
				</div>
				<div v-else class="no-more-data">没有更多数据了</div>
			</div>
		</template>
	</el-select>
</template>

<script setup lang="ts">
import { defineProps, reactive, ref, watch, useAttrs, computed, nextTick, onUnmounted } from 'vue';
import { request } from '/@/utils/service';
import { useUi } from '@fast-crud/fast-crud';

const props = defineProps({
	modelValue: {},
	tableConfig: {
		url: null,
		label: null, //显示值
		value: null, //数据值
		columns: [], //每一项对应的列表项
	},
	displayLabel: {},
} as any);

const attrs = useAttrs();

const emit = defineEmits(['update:modelValue', 'change']);

// 获取表单校验上下文
const { ui } = useUi();
const formValidator = ui.formItem.injectFormItemContext();

// select组件引用
const selectRef = ref();
// template上使用data
const data = ref();
// 选项列表
const options = ref<any[]>([]);
// 加载状态
const loading = ref(false);
const loadingMore = ref(false);
// 搜索关键词
const searchKeyword = ref('');
// 分页配置
const pageConfig = reactive({
	page: 1,
	limit: 20,
	total: 0,
});

// 计算tableConfig
const tableConfig = computed(() => props.tableConfig);

// 是否有更多数据
const hasMore = computed(() => {
	return options.value.length < pageConfig.total;
});

// 滚动事件处理
let scrollHandler: ((e: Event) => void) | null = null;

/**
 * 远程搜索方法
 */
const remoteMethod = async (query: string) => {
	searchKeyword.value = query;
	pageConfig.page = 1;
	
	// 保存当前选中的项，避免清空后无法显示
	const currentSelected = props.modelValue ? options.value.find(
		(item: any) => item[tableConfig.value.value] === props.modelValue
	) : null;
	
	options.value = [];
	
	// 如果有选中的项，先添加回去
	if (currentSelected) {
		options.value = [currentSelected];
	}
	
	await fetchData(false);
	
	// 搜索后，确保选中的项仍在选项中
	if (currentSelected && props.modelValue) {
		const exists = options.value.find(
			(item: any) => item[tableConfig.value.value] === props.modelValue
		);
		if (!exists) {
			options.value = [currentSelected, ...options.value];
		}
	}
};

/**
 * 加载更多数据
 */
const loadMore = async () => {
	if (loadingMore.value || !hasMore.value) return;
	pageConfig.page += 1;
	await fetchData(true);
};

/**
 * 获取数据
 */
const fetchData = async (isLoadMore: boolean = false) => {
	const url = tableConfig.value.url;
	const params: any = {
		page: pageConfig.page,
		limit: pageConfig.limit,
		has_inventory: 1,
	};
	
	// 如果有搜索关键词，添加到参数中
	if (searchKeyword.value) {
		params.search = searchKeyword.value;
	}
	
	try {
		if (isLoadMore) {
			loadingMore.value = true;
		} else {
			loading.value = true;
		}
		
		const response = await request({
			url: url,
			params: params,
		});
		
		if (response.code === 2000) {
			const newData = response.data || [];
			pageConfig.total = response.total || 0;
			
			if (isLoadMore) {
				// 加载更多时追加数据，但要避免重复
				const existingIds = new Set(options.value.map((item: any) => item[tableConfig.value.value]));
				const newItems = newData.filter((item: any) => !existingIds.has(item[tableConfig.value.value]));
				options.value = [...options.value, ...newItems];
			} else {
				// 首次加载或搜索时替换数据，但要保留当前选中的项
				const currentSelected = props.modelValue ? options.value.find(
					(item: any) => item[tableConfig.value.value] === props.modelValue
				) : null;
				
				options.value = newData;
				
				// 如果当前有选中的值且不在新数据中，添加回去
				if (currentSelected && props.modelValue) {
					const exists = options.value.find(
						(item: any) => item[tableConfig.value.value] === props.modelValue
					);
					if (!exists) {
						options.value = [currentSelected, ...options.value];
					}
				} else if (props.modelValue && !currentSelected) {
					// 如果选项中没有选中的项，尝试加载
					const selectedItem = options.value.find(
						(item: any) => item[tableConfig.value.value] === props.modelValue
					);
					if (!selectedItem) {
						await loadSelectedItem();
					}
				}
			}
		}
	} catch (error) {
		console.error('获取设备列表失败:', error);
		if (!isLoadMore) {
			options.value = [];
		}
	} finally {
		loading.value = false;
		loadingMore.value = false;
	}
};

/**
 * 加载已选中的项（用于编辑时显示）
 */
const loadSelectedItem = async (deviceId?: any) => {
	const targetId = deviceId || props.modelValue;
	if (!targetId) return;
	
	try {
		const response = await request({
			url: `${tableConfig.value.url}${targetId}/`,
			method: 'get',
		});
		
		if (response.code === 2000 && response.data) {
			const selectedItem = response.data;
			// 检查是否已经在选项中，如果不在则添加
			const exists = options.value.find(
				(item: any) => item[tableConfig.value.value] === selectedItem[tableConfig.value.value]
			);
			if (!exists) {
				options.value = [selectedItem, ...options.value];
			}
			return selectedItem;
		}
	} catch (error) {
		console.error('加载选中项失败:', error);
	}
	return null;
};

/**
 * 下拉框展开/关闭
 */
const visibleChange = async (bool: any) => {
	if (bool) {
		// 重置分页和搜索
		if (options.value.length === 0) {
			pageConfig.page = 1;
			searchKeyword.value = '';
			await fetchData(false);
		}
		
		// 添加滚动监听
		await nextTick();
		setupScrollListener();
	} else {
		// 移除滚动监听
		removeScrollListener();
	}
};

/**
 * 设置滚动监听
 */
const setupScrollListener = () => {
	if (!selectRef.value) return;
	
	const popper = document.querySelector('.deviceSelectorPopper .el-select-dropdown__wrap');
	if (!popper) return;
	
	scrollHandler = (e: Event) => {
		const target = e.target as HTMLElement;
		const scrollTop = target.scrollTop;
		const scrollHeight = target.scrollHeight;
		const clientHeight = target.clientHeight;
		
		// 当滚动到底部附近时（距离底部20px），加载更多
		if (scrollHeight - scrollTop - clientHeight < 20 && hasMore.value && !loadingMore.value && !loading.value) {
			loadMore();
		}
	};
	
	popper.addEventListener('scroll', scrollHandler);
};

/**
 * 移除滚动监听
 */
const removeScrollListener = () => {
	if (scrollHandler) {
		const popper = document.querySelector('.deviceSelectorPopper .el-select-dropdown__wrap');
		if (popper && scrollHandler) {
			popper.removeEventListener('scroll', scrollHandler);
		}
		scrollHandler = null;
	}
};

onUnmounted(() => {
	removeScrollListener();
});

/**
 * select change事件
 */
const onSelectChange = async (value: any) => {
	// 如果选择了值，确保该值在选项中（这样el-select才能正确显示）
	if (value) {
		const selectedItem = options.value.find(
			(item: any) => item[tableConfig.value.value] === value
		);
		
		// 如果选项中没有选中的项，尝试加载该项
		if (!selectedItem) {
			await loadSelectedItem(value);
		}
	}
	
	// data已经是value了，不需要再更新
	// data.value 已经在watch中同步了，这里直接emit即可
	emit('update:modelValue', value);
	// 触发校验
	formValidator?.onChange();
	formValidator?.onBlur();
	// 触发change事件
	emit('change', value);
	// 如果通过attrs传入了onChange回调，调用它
	if (attrs.onChange && typeof attrs.onChange === 'function') {
		attrs.onChange(value);
	}
};

// 监听modelValue的变化，同步到data（el-select需要value，不是label）
watch(
	() => props.modelValue,
	async (value) => {
		// el-select的v-model应该绑定value（设备ID），不是label（设备名称）
		data.value = value;
		
		// 如果选项中没有该项，尝试加载，确保能正确显示
		if (value) {
			const item = options.value.find(
				(item: any) => item[tableConfig.value.value] === value
			);
			if (!item) {
				// 如果选项中没有，尝试加载该项
				await loadSelectedItem(value);
			}
		}
	},
	{ immediate: true }
);

// 监听displayLabel的变化（用于编辑时回显）
watch(
	() => props.displayLabel,
	(value) => {
		// displayLabel仅用于参考，实际显示还是依赖于modelValue和options
		// 如果modelValue存在但options中没有，可能需要触发加载
		if (props.modelValue && value && options.value.length === 0) {
			loadSelectedItem();
		}
	},
	{ immediate: true }
);
</script>

<style scoped lang="scss">
.option-item {
	display: flex;
	justify-content: space-between;
	align-items: center;
	
	.option-label {
		flex: 1;
	}
	
	.option-code {
		font-size: 12px;
		color: #909399;
		margin-left: 10px;
	}
}

.empty-content {
	padding: 10px;
	text-align: center;
	
	.no-data {
		color: #909399;
		font-size: 12px;
		padding: 10px 0;
	}
	
	.load-more-wrapper {
		padding: 10px 0;
	}
	
	.no-more-data {
		color: #909399;
		font-size: 12px;
		padding: 10px 0;
	}
}
</style>

<style lang="scss">
.deviceSelectorPopper {
	.el-select-dropdown__wrap {
		max-height: 300px;
	}
}
</style>

