<template>
	<div class="var-select">
		<el-popover
			v-model:visible="visible"
			trigger="click"
			width="320"
			popper-class="var-select__popover"
			placement="bottom-start"
		>
			<template #reference>
				<div class="var-select__trigger">
					<el-input-tag
						:model-value="innerValue ? [innerValue] : undefined"
						:placeholder="t('common.nodeBase.varSelect.selectVariable')"
						:aria-label="t('common.nodeBase.varSelect.selectVariable')"
						clearable
						@clear="handleClear"
						@remove-tag="handleClear"
						autocomplete
						v-bind="$attrs"
					>
						<template #tag>
							<VarLabel :label="innerValue" />
						</template>
					</el-input-tag>
				</div>
			</template>

			<div class="var-select__panel">
				<el-input
					v-model="keyword"
					clearable
					size="small"
					:placeholder="t('common.nodeBase.varSelect.searchVariable')"
					class="var-select__search"
				/>

				<div class="var-select__list">
					<!-- 变量列表 -->
					<div v-for="group in filteredVars" class="var-select__group">
						<div class="var-select__group-title">{{ group.name }}</div>
						<div
							v-for="item in group.variableList"
							:key="item.expression"
							class="var-select__item"
							@click="
								handleSelect({
									value: item.expression,
									type: item.type
								})
							"
						>
							<span
								class="var-select__item-prefix env text-10px"
								:style="{ background: nodeMap[group?.type ?? '']?.iconColor ?? '' }"
							>
								<span v-if="group.id === 'env'" class="text-6px">ENV</span>
								<span v-if="group.id === 'sys'" class="text-6px">SYS</span>
								<img
									v-else-if="isImageIcon(nodeMap[group?.type ?? '']?.icon)"
									:src="nodeMap[group?.type ?? '']?.icon"
									alt="node icon"
									class="w-18px h-18px object-contain"
								/>
								<Icon v-else-if="group?.type" :icon="nodeMap[group?.type]?.icon!" :size="18" />
							</span>
							<span class="var-select__item-name" :title="item.name">{{ item.name }}</span>
							<span class="var-select__item-type">{{ normalizeTypeLabel(item.type) }}</span>
						</div>
					</div>

					<div v-if="!filteredVars.length" class="var-select__empty">
						{{ t('common.nodeBase.varSelect.empty') }}
					</div>
				</div>
			</div>
		</el-popover>
	</div>
</template>

<script setup lang="ts">
import { computed, ref, watch, inject, type Ref } from 'vue'
import { Icon } from '@repo/ui'
import { nodeMap } from '@/nodes'
import { VARIABLE_TYPE_OPTIONS } from '@/constant'
import { useI18n } from '@/composables/useI18n'
import VarLabel from '@/components/VarLabel/index.vue'

import type { NodeVar, VarType } from '@/types/var'

interface Props {
	/**
	 * 选中的变量，格式 #{xxx.var}
	 */
	modelValue: string
	/**
	 * 过滤方法
	 */
	filterFn?: (list: NodeVar[]) => NodeVar[]
	/**
	 * 绑定类型
	 */
	varType?: VarType | ''
}

const props = withDefaults(defineProps<Props>(), {
	modelValue: ''
})

const emit = defineEmits<{
	(e: 'update:modelValue', value: string): void
	(e: 'update:varType', value?: VarType | ''): void
	(e: 'change', value: { value: string; type: VarType }): void
	(e: 'clear'): void
}>()
const { t } = useI18n()

const nodeVars = inject<Ref<NodeVar[]>>('nodeVars')

const visible = ref(false)
const keyword = ref('')
const innerValue = ref<string>(props.modelValue)
const innerType = ref<VarType | '' | undefined>(props.varType)

watch(
	() => props.modelValue,
	(val) => {
		if (val !== innerValue.value) {
			innerValue.value = val
		}
	},
	{ deep: true }
)

const handleClear = () => {
	innerValue.value = ''
	innerType.value = ''
	emit('update:varType', '')
	emit('update:modelValue', '')
	emit('clear')
}

watch(
	() => innerValue.value,
	(val) => {
		emit('update:modelValue', val)
	}
)
watch(
	() => innerType.value,
	(val) => {
		emit('update:varType', val)
	}
)
const normalizeTypeLabel = (type?: VarType) => {
	if (!type) return ''
	const labelMap: Record<string, string> = {
		string: t('common.nodeBase.valueTypes.string'),
		number: t('common.nodeBase.valueTypes.number'),
		boolean: t('common.nodeBase.valueTypes.boolean'),
		object: t('common.nodeBase.valueTypes.object'),
		'array[string]': t('common.nodeBase.valueTypes.arrayString'),
		'array[number]': t('common.nodeBase.valueTypes.arrayNumber'),
		'array[boolean]': t('common.nodeBase.valueTypes.arrayBoolean'),
		'array[object]': t('common.nodeBase.valueTypes.arrayObject'),
		'array[file]': t('common.nodeBase.valueTypes.arrayFile')
	}

	return labelMap[type] || VARIABLE_TYPE_OPTIONS.find((item) => item.value === type)?.label || ''
}

const isImageIcon = (icon?: string) => !!icon && icon.startsWith('data:image/')

/**
 * 过滤变量列表
 */
const filteredVars = computed(() => {
	const kw = keyword.value.trim().toLowerCase()

	let list = nodeVars?.value || []
	// 先根据 filterFn 过滤一遍
	if (props.filterFn) {
		list = props.filterFn(list)
	}

	const options = list?.filter((item) => item.variableList.find((i) => i.name.includes(kw)))

	return options || []
})

const handleSelect = (variable: { value: string; type: VarType }) => {
	innerValue.value = variable.value
	innerType.value = variable.type
	visible.value = false
	keyword.value = ''
	emit('change', variable)
}
</script>

<style scoped lang="less">
.var-select {
	width: 100%;
	&__trigger {
		width: 100%;
		cursor: pointer;
	}
}

.var-select__popover {
	padding: 8px !important;
}

.var-select__panel {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.var-select__search {
	:deep(.el-input__wrapper) {
		box-shadow: none;
		border-radius: 8px;
		background-color: #f5f5f5;
	}
}

.var-select__list {
	max-height: 260px;
	overflow-y: auto;
}

.var-select__group + .var-select__group {
	margin-top: 8px;
	border-top: 1px solid #f2f2f2;
	padding-top: 8px;
}

.var-select__group-title {
	font-size: 12px;
	color: #999;
	margin-bottom: 4px;
}

.var-select__item {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 4px 6px;
	border-radius: 6px;
	cursor: pointer;
	font-size: 12px;
	color: #333;

	&:hover {
		background-color: #f5f7ff;
	}
}

.var-select__item-prefix {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 20px;
	height: 20px;
	border-radius: 6px;
	color: #fff;
	flex-shrink: 0;

	&.env {
		background: #6366f1;
	}

	&.sys {
		background: #f97316;
	}
}

.var-select__item-name {
	flex: 1;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.var-select__item-type {
	color: #999;
	flex-shrink: 0;
}

.var-select__empty {
	padding: 12px 4px;
	font-size: 12px;
	color: #999;
	text-align: center;
}

:deep(.el-input-tag__inner) {
	flex-wrap: nowrap;
}
</style>
