<script setup lang="ts">
import { ref, onMounted, reactive, toRefs, nextTick } from "vue";

interface ContentItem {
	id: string;
	type: 'text' | 'input';
	value: string;
	placeholder?: string;
}

const props = defineProps({
	content: {
		type: Array,
		default: () => []
	}
})

const data = reactive({
	//   content: [
	//     { id: '1', type: 'text', value: '11111' },
	//     { id: '2', type: 'input', value: '222', placeholder: '[请输入内容]' },
	//     { id: '3', type: 'text', value: '333333' },
	//     { id: '4', type: 'input', value: '', placeholder: '[请输入内容]' }
	//   ] as ContentItem[]
	content: props.content
})

const editableArea = ref<HTMLElement>()
const { content } = toRefs(data)

const cursorState = ref({
	isContainerClick: false
})

// 检查并删除末尾的空文本框
const removeLastEmptyTextIfNeeded = () => {
	const lastItem = content.value[content.value.length - 1]
	if (lastItem && lastItem.type === 'text' && lastItem.value === '') {
		content.value.pop()
		return true
	}
	return false
}

// 确保末尾有空文本框
const ensureEmptyTextAtEnd = () => {
	const lastItem = content.value[content.value.length - 1]
	if (!lastItem || lastItem.type !== 'text' || lastItem.value !== '') {
		const newItem: ContentItem = {
			id: Date.now().toString(),
			type: 'text',
			value: ''
		}
		content.value.push(newItem)
		return true
	}
	return false
}

// 元素信息获取
const getCurrentElementInfo = () => {
	const selection = window.getSelection()
	if (!selection || selection.rangeCount === 0) return null

	const range = selection.getRangeAt(0)
	const node = range.startContainer
	let element: HTMLElement | null = null

	if (node.nodeType === Node.TEXT_NODE) {
		element = (node as Text).parentElement
	} else {
		element = node as HTMLElement
	}

	if (!element) return null

	let index = -1
	let type: 'text' | 'input' = 'text'
	let isAtStart = false
	let isAtEnd = false

	if (element.classList.contains('text-field')) {
		index = parseInt(element.getAttribute('data-index') || '-1')
		type = 'text'
		const textContent = element.textContent || ''
		isAtStart = range.startOffset === 0
		isAtEnd = range.startOffset === textContent.length
	} else if (element.classList.contains('input-content')) {
		const parent = element.parentElement
		index = parseInt(parent?.getAttribute('data-index') || '-1')
		type = 'input'

		const item = content.value[index]
		if (element.classList.contains('has-placeholder')) {
			// placeholder状态下，光标在任意位置都认为是"在元素内"
			isAtStart = range.startOffset === 0
			isAtEnd = true
		} else {
			// 正常内容状态
			const textContent = item.value
			isAtStart = range.startOffset === 0
			isAtEnd = range.startOffset === textContent.length
		}
	}

	return { index, type, element, isAtStart, isAtEnd }
}

//光标设置
const setCursorToElement = (element: HTMLElement, position: 'start' | 'end') => {
	const selection = window.getSelection()
	const range = document.createRange()

	if (element.classList.contains('input-content') && element.classList.contains('has-placeholder')) {
		// placeholder状态的特殊处理
		range.selectNodeContents(element)
		range.collapse(position === 'start')
	} else if (element.childNodes.length > 0) {
		const targetNode = position === 'start' ? element.firstChild! : element.lastChild!
		if (targetNode.nodeType === Node.TEXT_NODE) {
			const offset = position === 'start' ? 0 : (targetNode.textContent || '').length
			range.setStart(targetNode, offset)
			range.setEnd(targetNode, offset)
		} else {
			range.selectNodeContents(element)
			range.collapse(position === 'start')
		}
	} else {
		range.selectNodeContents(element)
		range.collapse(position === 'start')
	}

	selection?.removeAllRanges()
	selection?.addRange(range)
}

// 键盘事件处理
const handleKeydown = (event: KeyboardEvent) => {
	const elementInfo = getCurrentElementInfo()
	if (!elementInfo) return

	const { index, type, isAtStart, isAtEnd } = elementInfo

	switch (event.key) {
		case 'Backspace':
			if (isAtStart && index > 0) {
				event.preventDefault()
				handleCrossElementDelete(index)
			} else if (type === 'input' && elementInfo.element?.classList.contains('has-placeholder')) {
				event.preventDefault()
			}
			// 其他情况让浏览器正常处理删除
			break

		case 'ArrowLeft':
			if (isAtStart && index > 0) {
				event.preventDefault()
				navigateToElement(index - 1, 'end')
			}
			break

		case 'ArrowRight':
			if (isAtEnd && index < content.value.length - 1) {
				event.preventDefault()
				navigateToElement(index + 1, 'start')
			} else if (isAtEnd && index === content.value.length - 1) {
				// 在最后一个元素末尾按右箭头，确保有一个空文本框
				ensureEmptyTextAtEnd()
				nextTick(() => {
					navigateToElement(index + 1, 'start')
				})
			}
			break
	}
}

// 跨元素删除逻辑
const handleCrossElementDelete = (currentIndex: number) => {
	const prevIndex = currentIndex - 1
	const prevItem = content.value[prevIndex]

	if (prevItem.type === 'input') {
		if (prevItem.value.trim() === '') {
			// 删除空输入框
			content.value.splice(prevIndex, 1)
			nextTick(() => {
				// 删除输入框后，先删除末尾的空文本框
				removeLastEmptyTextIfNeeded()
				// 然后聚焦到正确的位置
				if (prevIndex < content.value.length) {
					focusElement(prevIndex, 'end')
				} else if (content.value.length > 0) {
					focusElement(content.value.length - 1, 'end')
				}
			})
		} else {
			// 删除输入框最后一个字符，但保留输入框
			const newValue = prevItem.value.slice(0, -1)
			content.value[prevIndex].value = newValue
			updateInputDisplay(prevIndex)
			nextTick(() => focusElement(prevIndex, 'end'))
		}
	} else {
		// 文本框：移动到前一个文本框末尾，让浏览器正常删除
		// 先删除末尾的空文本框
		removeLastEmptyTextIfNeeded()
		focusElement(prevIndex, 'end')
	}
}

// 导航到元素
const navigateToElement = (targetIndex: number, position: 'start' | 'end') => {
	const targetItem = content.value[targetIndex]
	const element = targetItem.type === 'text'
		? editableArea.value?.querySelector(`.text-field[data-index="${targetIndex}"]`) as HTMLElement
		: editableArea.value?.querySelector(`.input-field[data-index="${targetIndex}"] .input-content`) as HTMLElement

	if (element) setCursorToElement(element, position)
}

// 焦点设置
const focusElement = (index: number, position: 'start' | 'end') => {
	const item = content.value[index]
	const element = item.type === 'text'
		? editableArea.value?.querySelector(`.text-field[data-index="${index}"]`) as HTMLElement
		: editableArea.value?.querySelector(`.input-field[data-index="${index}"] .input-content`) as HTMLElement

	if (element) setCursorToElement(element, position)
}

// 输入框显示管理
const updateInputDisplay = (index: number) => {
	const item = content.value[index]
	if (item.type !== 'input') return

	const inputElement = editableArea.value?.querySelector(
		`.input-field[data-index="${index}"] .input-content`
	) as HTMLElement

	if (!inputElement) return

	const showPlaceholder = item.value.trim() === '' && item.placeholder

	if (showPlaceholder) {
		inputElement.classList.add('has-placeholder')
		inputElement.textContent = item.placeholder
	} else {
		inputElement.classList.remove('has-placeholder')
		inputElement.textContent = item.value
	}
}

// 输入框内容变化处理
const handleInputChange = (index: number, event: Event) => {
	const target = event.target as HTMLSpanElement
	const item = content.value[index]

	// 如果当前显示placeholder，不更新实际值
	if (!target.classList.contains('has-placeholder')) {
		const newValue = target.textContent || ''
		content.value[index].value = newValue

		// 如果内容变空，显示placeholder
		if (newValue.trim() === '' && item.placeholder) {
			target.classList.add('has-placeholder')
			target.textContent = item.placeholder
		}
	}
}

// 输入框键盘事件
const handleInputKeydown = (event: KeyboardEvent, index: number) => {
	const target = event.target as HTMLSpanElement

	if (event.key === 'Backspace') {
		// 如果显示placeholder，阻止删除
		if (target.classList.contains('has-placeholder')) {
			event.preventDefault()
			return
		}

		const selection = window.getSelection()
		if (selection && selection.rangeCount > 0) {
			const range = selection.getRangeAt(0)
			const isAtStart = range.startOffset === 0

			// 如果光标在输入框开头，阻止默认行为，让外部的handleBackspace处理
			if (isAtStart) {
				event.preventDefault()
				return
			}
		}
	} else if (event.key.length === 1 && !event.ctrlKey && !event.metaKey) {
		// 普通字符输入
		if (target.classList.contains('has-placeholder')) {
			event.preventDefault()
			target.textContent = event.key
			target.classList.remove('has-placeholder')
			content.value[index].value = event.key

			// 移动光标到末尾
			nextTick(() => {
				setCursorToElement(target, 'end')
			})
		}
	}
}

const handleInputBlur = (index: number) => {
	updateInputDisplay(index)
}

// 容器点击处理
const handleContainerClick = (event: MouseEvent) => {
	const target = event.target as HTMLElement

	if (target === editableArea.value) {
		event.preventDefault()
		cursorState.value.isContainerClick = true

		// 确保末尾有空文本框并聚焦到它
		ensureEmptyTextAtEnd()
		nextTick(() => {
			focusElement(content.value.length - 1, 'start')
		})
	}
}

// 初始化
const initPlaceholders = () => {
	nextTick(() => {
		content.value.forEach((_, index) => updateInputDisplay(index))
		// 确保初始状态下有一个空文本框
		ensureEmptyTextAtEnd()
	})
}

const getFullText = () => {
	return content.value.map(item => {
		if (item.type === 'text') {
			return item.value
		} else {
			// 只获取用户实际输入的值，即使为空也显示空括号
			return `${item.value}`
		}
	}).join('')
}

onMounted(() => {
	initPlaceholders()
})

defineExpose({
	getFullText,
	content
})
</script>

<template>
	<div ref="editableArea" class="promptInput" @keydown="handleKeydown" @click="handleContainerClick">
		<template v-for="(item, index) in content" :key="item.id">
			<span v-if="item.type === 'text'" class="text-field" :data-index="index" contenteditable="plaintext-only">{{
				item.value }}</span>

			<span v-else class="input-field" :data-index="index">
				<span class="input-content" contenteditable="plaintext-only" @input="(e) => handleInputChange(index, e)"
					@keydown="(e) => handleInputKeydown(e, index)" @blur="() => handleInputBlur(index)"></span>
			</span>
		</template>
	</div>
</template>

<style lang="less" scoped>
.promptInput {
	--promptInputBorderRadius: 10px;
	--promptInputBorder: 2px solid #dcdfe6;
	--promptInputPadding: 1.5rem;

	width: 100%;
	min-height: 12rem;
	border-radius: var(--promptInputBorderRadius);
	border: var(--promptInputBorder);
	padding: var(--promptInputPadding);
	background: white;
	line-height: 1.6;
	outline: none;
	white-space: pre-wrap;
	user-select: text;
	cursor: text;

	.text-field {
		display: inline;
		outline: none;
		padding: .2rem 0;
		font-size: 1.8rem;
		min-width: 2px;
		/* 确保空文本框也能点击 */
	}

	.input-field {
		display: inline-block;
		background: #e3f2fd;
		border: 1px solid #bbdefb;
		margin: 0 .2rem;
		padding: .2rem 1rem;
		font-size: 1.8rem;
		border-radius: 4px;

		.input-content {
			outline: none;
			color: #1976d2;
			display: inline-block;
			min-width: 2rem;

			&.has-placeholder {
				color: #95a5a6;
				font-style: italic;
			}
		}
	}
}
</style>