<script setup lang="ts">
import { computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { Delete, Plus, Warning } from '@element-plus/icons-vue'
import { VARIABLE_TYPE_OPTIONS } from '@/constant'

export interface SchemaNode {
	name: string
	type: string
	description: string
	enumValues: string
	required: boolean
	children?: SchemaNode[]
}

defineOptions({
	name: 'SchemaTreeNode'
})

const props = defineProps<{
	modelValue: SchemaNode
	index: number
	isRoot?: boolean
	siblings?: SchemaNode[]
}>()

const emit = defineEmits<{
	(e: 'update:modelValue', value: SchemaNode): void
	(e: 'remove'): void
}>()

const node = computed({
	get: () => props.modelValue,
	set: (val) => emit('update:modelValue', val)
})

// 判断是否显示子节点编辑区
const showChildren = computed(() => {
	const t = node.value.type
	if (t === 'object') return true
	if (t.startsWith('array[object]')) return true
	return false
})

const getArrayItemType = (type: string) => type.match(/^array\[(.*)\]$/)?.[1] || 'string'

// 字段名要求符合 JS 变量命名规则
const JS_IDENTIFIER_REGEXP = /^[A-Za-z_$][A-Za-z0-9_$]*$/

const isNameInvalid = computed(() => {
	if (props.isRoot) return false
	const currentName = node.value.name?.trim()
	if (!currentName) return false
	return !JS_IDENTIFIER_REGEXP.test(currentName)
})

// 校验名称是否重复
const isNameDuplicate = computed(() => {
	const currentName = node.value.name?.trim()
	if (!props.siblings || !currentName) return false
	return props.siblings.some(
		(sibling, idx) => idx !== props.index && sibling.name?.trim() === currentName
	)
})

const nameErrorText = computed(() => {
	if (isNameInvalid.value) return '字段名需符合 JS 变量命名规则'
	if (isNameDuplicate.value) return '字段名重复'
	return ''
})

const hasNameError = computed(() => isNameInvalid.value || isNameDuplicate.value)

// 监听类型变化
watch(
	() => node.value.type,
	(newType, oldType) => {
		// 如果类型没有变化，不要做任何事，保护已有数据
		if (newType === oldType) return

		if (newType.startsWith('array[')) {
			const itemType = getArrayItemType(newType)

			// 对于 array[object]
			if (itemType === 'object') {
				// array[object] 的子节点直接表示对象属性，不保留 item 包装层
				if (node.value.children && node.value.children.length === 1 && node.value.children[0]?.name === 'item') {
					node.value.children = node.value.children[0]?.children || []
				}
				if (!node.value.children) {
					node.value.children = []
				}
				return
			}

			// 对于其他数组类型（如 array[string]），需要确保有一个 item 节点
			if (!node.value.children || node.value.children.length === 0) {
				node.value.children = [
					{
						name: 'item',
						type: itemType,
						description: '',
						enumValues: '',
						required: false,
						children: []
					}
				]
			} else {
				// 如果已有子节点，更新第一个子节点的类型
				const firstChild = node.value.children[0]
				if (firstChild) {
					firstChild.type = itemType
					if (itemType !== 'object') {
						firstChild.children = []
					}
				}
				// 保持只有一个子节点 (item)
				if (node.value.children.length > 1) {
					node.value.children = [node.value.children[0]!]
				}
			}
		} else if (newType === 'object') {
			if (node.value.children && node.value.children.length === 1 && node.value.children[0]?.name === 'item') {
				node.value.children = node.value.children[0]?.children || []
			}
			if (!node.value.children) {
				node.value.children = []
			}
		} else {
			// 基本类型，清空 children
			node.value.children = []
		}
	},
	{ immediate: true }
)

const addChild = () => {
	if (!node.value.children) {
		node.value.children = []
	}

	// 如果是 Array 类型，区分处理
	if (node.value.type.startsWith('array[')) {
		const itemType = node.value.type.match(/^array\[(.*)\]$/)?.[1] || 'string'

		// 只有非 object 的数组类型（如 array[string]）才禁止添加子节点
		if (itemType !== 'object') {
			ElMessage.warning('简单类型数组只能定义一种项结构，无法添加子字段')
			return
		}
	}

	// Object 或 array[object] 类型，正常添加子字段
	node.value.children.push({
		name: '',
		type: 'string',
		description: '',
		enumValues: '',
		required: false,
		children: []
	})
}

const removeChild = (idx: number) => {
	if (node.value.children) {
		// 如果是 Array 类型，区分处理
		if (node.value.type.startsWith('array[')) {
			const itemType = node.value.type.match(/^array\[(.*)\]$/)?.[1] || 'string'

			// 只有非 object 的数组类型，且只剩一个子节点（item）时，禁止删除
			if (itemType !== 'object' && node.value.children.length === 1) {
				ElMessage.warning('数组必须包含至少一个项结构定义')
				return
			}
		}

		node.value.children.splice(idx, 1)
	}
}
</script>

<template>
	<div
		class="schema-node"
		:class="{
			'is-root': isRoot,
			'is-array-item': node.type.startsWith('array[')
		}"
	>
		<!-- 节点头部 -->
		<div class="node-header">
			<div class="node-info">
				<!-- 字段名输入 -->
				<el-tooltip v-if="hasNameError" :content="nameErrorText" placement="top">
					<el-input
						v-if="!isRoot"
						v-model="node.name"
						placeholder="Key"
						size="small"
						class="name-input"
						:class="{ 'is-error': hasNameError }"
					>
						<template #prefix>
							<el-icon v-if="hasNameError" class="error-icon"><Warning /></el-icon>
						</template>
					</el-input>
				</el-tooltip>

				<el-input
					v-else-if="!isRoot"
					v-model="node.name"
					placeholder="字段名"
					size="small"
					class="name-input"
				/>

				<span v-else class="root-name">structured_output</span>

				<!-- 类型选择 -->
				<el-select
					v-model="node.type"
					:options="VARIABLE_TYPE_OPTIONS"
					placeholder="Type"
					size="small"
					class="type-select"
				/>

				<!-- 必填勾选 (仅非根节点) -->
				<el-tooltip content="是否必填" placement="top" v-if="!isRoot">
					<el-checkbox v-model="node.required" size="small" border class="required-check"
						>必填</el-checkbox
					>
				</el-tooltip>
			</div>

			<!-- 删除按钮 (仅非根节点) -->
			<div class="node-actions" v-if="!isRoot">
				<el-button size="small" type="danger" link @click="emit('remove')">
					<el-icon><Delete /></el-icon>
				</el-button>
			</div>
		</div>

		<!-- 节点详细配置 (描述、枚举) -->
		<div class="node-body">
			<el-form size="small" label-width="70px" class="config-form">
				<el-form-item label="描述">
					<el-input v-model="node.description" placeholder="字段描述" />
				</el-form-item>

				<!-- 枚举值：仅对简单类型显示 -->
				<el-form-item v-if="['string', 'number', 'integer'].includes(node.type)" label="枚举值">
					<el-input
						v-model="node.enumValues"
						placeholder="例: name1, name2"
						type="textarea"
						:rows="1"
						autosize
					/>
				</el-form-item>
			</el-form>
		</div>

		<!-- 子节点区域 (递归) -->
		<div v-if="showChildren" class="children-container">
			<div class="children-header">
				<span class="children-title">
					<template v-if="node.type.startsWith('array[')">
						<el-tag size="small" type="warning" effect="plain">Array Items</el-tag>
						<span class="ml-2">数组项结构 ({{ node.type.match(/^array\[(.*)\]$/)?.[1] }})</span>
					</template>
					<template v-else> 子属性 (Properties) </template>
				</span>
				<!-- 在 object 和 array[object] 下都显示添加按钮 -->
				<el-button
					v-if="node.type === 'object' || node.type.startsWith('array[object]')"
					size="small"
					type="primary"
					link
					@click="addChild"
				>
					<el-icon><Plus /></el-icon> 添加
				</el-button>
			</div>

			<div v-for="(child, idx) in node.children" :key="idx" class="child-wrapper">
				<SchemaTreeNode
					v-model="node.children![idx]!"
					:index="idx"
					:siblings="node.children"
					@remove="removeChild(idx)"
				/>
			</div>

			<div v-if="!node.children || node.children.length === 0" class="empty-tip">
				{{ node.type.startsWith('array[') ? '请定义数组项的结构' : '暂无子项' }}
			</div>
		</div>
	</div>
</template>

<style scoped>
.schema-node {
	border: 1px solid #e4e7ed;
	border-radius: 6px;
	padding: 12px;
	margin-bottom: 12px;
	background: #fff;
	position: relative;
	transition: all 0.3s;
}

.is-root {
	background: #f5f7fa;
	border-color: #dcdfe6;
}

.is-array-item {
	border-left: 4px solid #e6a23c;
}

.node-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 12px;
	padding-bottom: 8px;
	border-bottom: 1px dashed #ebeef5;
}

.node-info {
	display: flex;
	align-items: center;
	gap: 8px;
	flex: 1;
}

.name-input {
	width: 140px;
}

.name-input.is-error :deep(.el-input__wrapper) {
	box-shadow: 0 0 0 1px #f56c6c inset;
}

.error-icon {
	color: #f56c6c;
}

.type-select {
	width: 130px;
}

.required-check {
	margin-left: 4px;
}

.root-name {
	font-weight: bold;
	color: #409eff;
	margin-right: 10px;
	font-size: 14px;
}

.node-body {
	margin-bottom: 12px;
}

.config-form :deep(.el-form-item) {
	margin-bottom: 8px;
}

.children-container {
	margin-top: 12px;
	padding-left: 24px;
	border-left: 2px solid #f0f2f5;
}

.children-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 10px;
}

.children-title {
	font-size: 12px;
	color: #909399;
	font-weight: 600;
	display: flex;
	align-items: center;
	gap: 6px;
}

.ml-2 {
	margin-left: 8px;
}

.child-wrapper {
	margin-top: 8px;
}

.empty-tip {
	font-size: 12px;
	color: #c0c4cc;
	text-align: center;
	padding: 8px 0;
	font-style: italic;
}
</style>
