<template>
	<div class="agent-container flex flex-col">
		<div class="agent-header flex align-center space-between">
			<div class="header-title-wrapper">
				<div class="agent-title">{{ props.title }}</div>
				<div class="agent-name">AI Assistant 1.0</div>
			</div>
			<!-- <SvgIcon name="equal" color="#0d0d0d" size="24" /> -->
		</div>
		<div class="agent-body flex-1 flex flex-col">
			<List ref="listRef" :message-list="messageList" @regenerate="handleRegenerate" />
			<Input
				ref="inputRef"
				is-agent-mode
				:generating="isGenerating"
				@send="handleSendMessage"
				@pause="handlePause"
			/>
		</div>
	</div>
</template>

<script setup lang="ts">
	import { ref, reactive, computed, onUnmounted, onMounted, nextTick, watch } from 'vue'
	import List from './List.vue'
	import Input from '../../components/Input.vue'
	import { chatUrl } from '@/api/agent'
	import type { AgentParamsType } from '@/api/agent'
	import { useUserInfoStore, useProjectStore, useAgentStore } from '@/stores'
	import MyEvent from '@/utils/myEvent'

	const userStore = useUserInfoStore()
	const agentStore = useAgentStore()
	const projectStore = useProjectStore()

	const reportsContent = ref('')
	const isGeneratingReport = ref(false)

	const emits = defineEmits(['update:sketchList', 'setTitle'])
	const props = withDefaults(
		defineProps<{
			title: string
		}>(),
		{
			title: 'Retro Sofa Sketch'
		}
	)

	const messageList = ref([])

	const listRef = ref()
	const inputRef = ref()
	const isGenerating = ref(false)
	const isPaused = ref(false) // 标记是否为主动暂停
	const params = reactive<AgentParamsType>({
		projectID: projectStore.state.id,
		message: '',
		token: userStore.state.token,
		versionID: '',
		needSuggestion: false,
		useReport: false,
		configParams: {
			type: '',
			region: '',
			style: ''
		},
		imageUrlList: []
	})

	const sketchList = ref([])
	watch(
		sketchList,
		(newVal) => {
			emits('update:sketchList', newVal)
		},
		{ deep: true }
	)

	// 每次请求时创建新的 AbortController
	let abort: AbortController

	const createAbortController = () => {
		// 如果已有未完成的中止，先中止它
		if (abort) {
			abort.abort()
		}
		abort = new AbortController()
		return abort
	}

	onUnmounted(() => {
		abort?.abort()
	})

	onMounted(() => {
		// 检查 store 中是否有初始项目数据
		// projectStore.setId('1') // 临时设置项目ID为1，实际应用中应根据上下文动态设置
		const initialData = agentStore.getInitialProjectData
		if (initialData) {
			// 等待页面渲染完成后自动发送初始消息
			params.configParams = {
				type: initialData.type,
				region: initialData.area,
				style: initialData.style,
				temperature: 0.7
			}
			params.needSuggestion = initialData.needSuggestion || false
			params.useReport = initialData.useReport
			handleSendMessage({
				text: initialData.text,
				images: initialData.images,
				useReport: initialData.useReport,
				tempImages: initialData.tempImages
			})
			// 更新 configParams

			// 清空初始数据
			agentStore.clearInitialProjectData()
		}
	})

	const handleSendMessage = async (
		message: {
			text: string
			images: Array<{ url: string; name: string }>
			tempImages: any[]
			useReport: boolean
		},
		skipUserMessage = false
	) => {
		isPaused.value = false
		isGenerating.value = true
		params.message = message.text
		if (message.hasOwnProperty('useReport')) {
			params.useReport = message.useReport
		}

		params.imageUrlList = message.images || []

		// 如果不是重新生成模式，则添加用户消息到列表
		if (!skipUserMessage) {
			messageList.value.push({
				id: messageList.value.length + 1,
				text: message.text,
				isUser: true,
				imageUrls: message.tempImages
			})
		}

		// Add AI loading message
		const aiMessage = reactive({
			id: messageList.value.length + 1,
			text: '',
			isUser: false,
			sessionId: projectStore.state.id,
			loading: true,
			thinking: false,
			thinkingText: '',
			thinkingCollapsed: false,
			streaming: true
		})
		messageList.value.push(aiMessage)

		// 创建新的 AbortController
		const abortController = createAbortController()

		// console.log('token---', params.token, '参数---', params)

		try {
			const urlParams = new URLSearchParams<AgentParamsType>({
				...params,
				configParams: JSON.stringify(params.configParams)
			})
			const BASEURL = import.meta.env.VITE_APP_URL
			const response = await fetch(`${BASEURL}${chatUrl}?${urlParams.toString()}`, {
				method: 'GET',
				signal: abortController.signal
			})

			// 检查响应内容类型，判断是否为流式响应
			const contentType = response.headers.get('content-type') || ''
			const isStreamResponse =
				contentType.includes('text/event-stream') || contentType.includes('stream')

			if (!response.ok) {
				// 非流式错误响应，使用 text() 读取错误信息
				const errorText = await response.text()
				console.error('请求错误:', errorText)
				if (!isPaused.value) {
					aiMessage.text = '发送失败,请重试'
				}
				aiMessage.streaming = false
				aiMessage.loading = false
				isGenerating.value = false
				return
			}

			// 不是流式响应，使用 text()读取错误信息
			if (!isStreamResponse) {
				const text = await response.text()
				try {
					const errorData = JSON.parse(text)
					console.error('非流式响应:', errorData)
				} catch (e) {
					console.error('非流式响应文本:', text)
				}
				if (!isPaused.value) {
					aiMessage.text = '发送失败,请重试'
				}
				aiMessage.streaming = false
				aiMessage.loading = false
				isGenerating.value = false
				return
			}

			// 流式响应处理
			let contentBody = ''
			let buffer = ''
			const reader = response.body?.getReader()
			if (!reader) throw new Error('无法获取流读取器')

			const decoder = new TextDecoder()
			let previousEventName = '' // 记录上一个事件名称
			let hasReportStarted = false // 标记 report 是否已经开始
			try {
				let flag = true
				while (flag) {
					const { done, value } = await reader.read()
					if (done) {
						// console.log('传输结束 end---', contentBody)
						aiMessage.streaming = false
						aiMessage.loading = false
						isGenerating.value = false
						flag = false
						break
					}

					buffer += decoder.decode(value, { stream: true })

					// 优先按空行拆分事件块（SSE标准）
					let events = buffer.split(/\n\n/)
					buffer = events.pop() // 保留不完整块

					for (let event of events) {
						if (!event.trim()) continue

						const eventName = event
							.split(/\n/)
							.find((line) => line.startsWith('event:'))
							?.replace(/^event:\s*/, '')
							?.trim()

						if (!hasReportStarted && eventName === 'report') {
							isGeneratingReport.value = true
							contentBody += `<slot slot-name="card" title="123" content="123">123</slot>`
							hasReportStarted = true
						}

						if (
							previousEventName === 'report' &&
							eventName !== 'report' &&
							reportsContent.value
						) {
							isGeneratingReport.value = false
							sessionStorage.setItem(
								'reportsContent_' + projectStore.state.id,
								reportsContent.value
							)
						}

						previousEventName = eventName

						// console.log('eventName:', eventName, 'event:', event)

						// 根据事件名称精确判断，而不是用 includes
						if (eventName === 'error') {
							aiMessage.text = '出现错误,请重试'
							aiMessage.streaming = false
							aiMessage.loading = false
							isGenerating.value = false
							flag = false
							break
						}
						if (eventName === 'todo') {
							continue
						}

						let isNodeIdEvent = eventName === 'nodeId'

						let hasSketch = eventName === 'sketchIDAndUrl'

						const dataLines = event
							.split(/\n/)
							.filter((line) => line.startsWith('data:'))
							.map((line) => line.replace(/^data:\s*/, ''))
							.filter((content) => content.startsWith('{') || content.startsWith('['))
						// console.log('dataLInes', dataLines)
						if (isNodeIdEvent) {
							const versionID = event
								.split(/\n/)
								.filter((line) => line.startsWith('data:'))
								.map((line) => line.replace(/^data:\s*/, ''))[0]
							params.versionID = versionID
							projectStore.setProject({ nodeId: versionID })
						}
						// if (eventName === 'webAddress') {
						// 	console.log('webAddress111111111111111', eventName, dataLines)
						// 	debugger
						// }

						if (eventName === 'tool') {
							MyEvent.emit('loading-sketch')
						}

						if (dataLines.length === 0) continue
						const jsonText = dataLines.join('\n')

						try {
							const jsonData = JSON.parse(jsonText)
							// console.log('jsonData', jsonData)
							if (jsonData.webAddress) {
								aiMessage.webAddress = JSON.parse(jsonData.webAddress)
								contentBody += `<slot slot-name="url">123</slot>`
							}
							if (jsonData.title) {
								emits('setTitle', jsonData.title)
							}

							if (hasSketch) {
								sketchList.value.push({
									[Object.keys(jsonData)[0]]: jsonData[Object.keys(jsonData)[0]]
								})
								MyEvent.emit('OpenSketch')
							}
							if (eventName === 'report') {
								reportsContent.value += jsonData.report
							} else {
								if (jsonData.reasoning) {
									aiMessage.thinking = true
									aiMessage.loading = false
									aiMessage.thinkingText += jsonData.reasoning
								} else {
									aiMessage.thinking = false
									if (
										jsonData.content &&
										jsonData.content.length > 0 &&
										jsonData.type !== 'end'
									) {
										contentBody += jsonData.content
										aiMessage.text = contentBody
										aiMessage.loading = false
									}
								}
							}
							if (jsonData.type === 'end') {
								aiMessage.streaming = false
								aiMessage.loading = false
								isGenerating.value = false
								flag = false
								break
							}
						} catch (e) {
							// 检查是否为纯文本 [DONE]
							if (jsonText.trim() === '[DONE]') {
								console.log('结束-----------------------')
								aiMessage.streaming = false
								aiMessage.loading = false
								isGenerating.value = false
								flag = false
								break
							}
							// JSON 不完整：保留到下一次循环
							if (!jsonText.trim().endsWith('}')) {
								buffer = 'data: ' + jsonText // 重新放回缓存
								continue
							} else {
								console.warn('⚠️ JSON 格式错误，跳过:', jsonText)
							}
						}

						// 更新上一个事件名称
						previousEventName = eventName
					}
				}
			} catch (error) {
				console.error('流式传输错误:', error)
				if (!isPaused.value) {
					aiMessage.text = '发送失败,请重试'
				}
				aiMessage.streaming = false
				aiMessage.loading = false
				isGenerating.value = false
			} finally {
				reader.releaseLock()
			}
		} catch (error) {
			console.error('fetch请求失败:', error)
			if (!isPaused.value) {
				aiMessage.text = '发送失败,请重试'
			}
			aiMessage.streaming = false
			aiMessage.loading = false
			isGenerating.value = false
		}
	}

	const handlePause = () => {
		isPaused.value = true
		isGenerating.value = false
		abort?.abort()
	}

	const handleRegenerate = async (aiMessage: any) => {
		// 找到当前 AI 消息在列表中的索引
		const aiIndex = messageList.value.findIndex((msg) => msg.id === aiMessage.id)
		if (aiIndex === -1) return

		// 找到对应的用户消息（AI 消息前面的最近一条用户消息）
		let userMessage = null
		for (let i = aiIndex - 1; i >= 0; i--) {
			if (messageList.value[i].isUser) {
				userMessage = messageList.value[i]
				break
			}
		}
		if (!userMessage) return

		// 删除当前的 AI 回复消息
		messageList.value.splice(aiIndex, 1)

		// 重新调用 API（跳过用户消息添加，因为用户消息已存在）
		await handleSendMessage(
			{
				text: userMessage.text,
				images: userMessage.images || []
			},
			true
		)
	}

	// 处理对话列表，将连续的 assistant 消息合并为一条
	const processDialogue = (dialogue, startIndex, existingImgList, sessionId) => {
		if (!dialogue || dialogue.length === 0) return []

		const result = []
		let i = startIndex

		while (i < dialogue.length) {
			const item = dialogue[i]
			if (item.role === 'user') {
				// user 角色直接添加
				result.push({
					...item,
					text: item.content,
					isUser: true,
					id: result.length + 1,
					sessionId: sessionId
				})
				i++
			} else if (item.role === 'assistant') {
				// assistant 角色，拼接直到下一个 user
				let combinedContent = item.content || ''
				let combinedThinkingText = item.reasoning || ''
				// 继续往后找连续的 assistant 消息
				let j = i + 1
				while (j < dialogue.length && dialogue[j].role === 'assistant') {
					combinedContent += dialogue[j].content || ''
					combinedThinkingText += dialogue[j].reasoning || ''
					j++
				}

				result.push({
					...item,
					content: combinedContent,
					thinkingText: combinedThinkingText,
					text: combinedContent,
					isUser: false,
					id: result.length + 1,
					sessionId: sessionId
				})

				i = j
			} else {
				// 其他角色直接添加
				result.push({
					...item,
					text: item.content,
					isUser: item.role === 'user',
					id: result.length + 1,
					sessionId: sessionId
				})
				i++
			}
		}

		return result
	}
	const processSession = (session, imgList, ancestorsList, idCounterRef) => {
		if (!session) return

		// 1. 在 dialogue 第一个 report 有值的项的 content 中插入报告卡片
		if (session.dialogue) {
			for (let i = 0; i < session.dialogue.length; i++) {
				if (session.dialogue[i].report) {
					session.dialogue[i].content =
						`<slot slot-name="card" title="123" content="123">123</slot>` +
						(session.dialogue[i].content || '')
					break
				}
			}
		}

		// 2. 收集 report 内容并保存到 localStorage
		let reportStr = ''
		session.dialogue?.forEach((item) => {
			if (item.report) {
				reportStr += item.report
			}
		})
		if (reportStr && session.id) {
			sessionStorage.setItem(`reportsContent_${session.id}`, reportStr)
		}

		// 3. 收集 sketchIDAndUrl 到 imgList
		if (session.sketchIDAndUrl) {
			imgList.push(session.sketchIDAndUrl)
		}

		// 4. 处理 dialogue
		const list = processDialogue(session.dialogue, 0, imgList, session.id)
		list.forEach((el) => {
			el.id = idCounterRef.value++
		})
		ancestorsList.push(...list)
	}

	const setChatInfo = (info) => {
		const initialData = agentStore.getInitialProjectData
		if (isGenerating.value || initialData) return

		const data = info.conversation
		let project = info.project
		if (info.id) {
			project = info
		}

		params.versionID = ''
		sketchList.value = []
		if (project) {
			params.configParams.type = project.type
			params.configParams.region = project.area
			params.configParams.style = project.style
			params.configParams.temperature = project.temperature
		}
		// 如果没有数据，直接返回
		if (!data) {
			messageList.value = []
			return
		}
		const { ancestors, current } = data

		// 处理单个会话（ancestor 或 current）

		const imgList = []
		const ancestorsList = []
		const idCounterRef = { value: 1 }

		// 处理所有 ancestors
		ancestors?.forEach((item) => {
			processSession(item, imgList, ancestorsList, idCounterRef)
		})

		// 处理 current
		processSession(current, imgList, ancestorsList, idCounterRef)

		// 延迟设置新数据，确保 UI 有时间响应清空操作
		nextTick(() => {
			messageList.value = [...ancestorsList]
			params.versionID = current?.id
			sketchList.value = imgList
		})
	}

	defineExpose({
		setChatInfo
	})
</script>

<style lang="less" scoped>
	.c-svg {
		width: initial;
	}
	.agent-container {
		// width: 39%;
		// width: 63.4rem;
		// flex: 1;
		width: 67.4rem;
		margin-right: 2.7rem;
		background-color: #fff;
		border-radius: 2rem;
		box-shadow: 0px 15px 21px 0px #0000000d;

		.agent-header {
			height: 7.4rem;
			border-bottom: 0.1rem solid #c9c9c9;
			padding: 1.4rem 3.4rem 1.4rem 3.1rem;

			.agent-title {
				font-size: 1.8rem;
				margin-bottom: 0.6rem;
			}

			.agent-name {
				font-size: 1.4rem;
			}
		}
		.agent-body {
			padding: 3.2rem;
			overflow: hidden;
			row-gap: 2.4rem;
			.assist-input-wrapper {
				width: 100%;
				// height: 14.4rem;
				min-height: 14.4rem !important;
				max-height: 18.1rem !important;
			}
		}
		.input-wrapper {
			height: 14.4rem;
			padding: 0 2rem 3rem;
		}
	}
</style>
