<script setup>
	import {
		onMounted,
		ref,
		nextTick,
		watch,
		onUnmounted
	} from 'vue';
	import {
		useRoute
	} from 'vue-router';
	import {
		getFlowChatStatus,
		getHistoryChatList
	} from '@/api/ai'
	import {
		Top,
		Plus,
		Check,
		Loading,
		Monitor
	} from '@element-plus/icons-vue'
	import {
		useUserStore
	} from '@/store'
	import {
		marked
	} from 'marked';
	import hljs from 'highlight.js/lib/common';
	// 引入 github 代码主题
	import 'highlight.js/styles/github.css';
	import config from '@/config'
	import {
		fetchEventSource
	} from '@microsoft/fetch-event-source';
	const emits = defineEmits(['updateURL']);
	const user = ref(useUserStore().userData);
	// 对话历史
	const chatHistory = ref([]);
	// 加载状态
	const loading = ref(false);
	// 输入框内容
	const prompt = ref('');
	// 当前AI流式响应内容
	const currentAIResponse = ref('');
	const paramId = ref(useRoute().params.id);
	const paramType = ref(useRoute().params.type);
	const conversationId = ref('');
	const chatBody = ref(null);
	const previewUrl = ref('');
	onMounted(() => {
		if (paramId.value.trim()) init();
	})
	// 监听对话历史变化，自动滚动到底部
	watch(chatHistory, () => {
		scrollToBottom();
	}, {
		deep: true
	})
	let timerId = null;
	const init = async () => {
		if (paramType.value === 'chat') {
			conversationId.value = paramId.value;
			initChatList();
			return;
		}
		let flowChatData = await getFlowChatStatus(paramId.value);
		if (flowChatData.state) {
			if (flowChatData.data.status === 'succeeded') {
				conversationId.value = flowChatData.data.conversationId;
				loading.value = false;
				initChatList();
				stopTimer();
			} else {
				let inputs = JSON.parse(flowChatData.data.inputs);
				chatHistory.value = [{
					query: inputs.query,
					AIoutputs: ''
				}]
				loading.value = true;
				startTimer();
			}
		}
	}
	// 启动定时器
	const startTimer = () => {
		if (timerId) return
		timerId = setInterval(() => {
			init();
		}, 3000)
	}

	// 停止定时器
	const stopTimer = () => {
		if (timerId) {
			clearInterval(timerId)
			timerId = null;
		}
	}
	const initChatList = async () => {
		let flowData = await getHistoryChatList(conversationId.value);
		if (flowData.state) {
			versionIndex.value = 1;
			chatHistory.value = flowData.data.data.map(node => {
				node['AIoutputs'] = returnAIoutputs(node.answer);
				return node
			});
			hljs.highlightAll();
			if (previewUrl.value) emits('updateURL', previewUrl.value);
		}
	}
	const reloadMessage = (value) => {
		prompt.value = value;
		sendMessage();
	}
	const sendMessage = () => {
		if (!prompt.value.trim() || loading.value) return;
		AIMessage(prompt.value)
	}
	const returnAIoutputs = (data) => {
		let str = '';
		if (data.indexOf('```markdown') > -1) {
			str = data.replaceAll('\n', '</n>').replaceAll('```markdown', '').replaceAll('```', '');
		} else {
			str = data;
		}
		let obj = str.split('<workark>');
		let newData = obj.map(node => {
			try {
				return JSON.parse(node)
			} catch {
				return {}
			}
		});
		return deduplicateByTypeAndId(newData);
	}
	const AIMessage = async (userMessage) => {
		try {
			// 1. 添加用户消息到历史记录
			chatHistory.value.push({
				isUser: true,
				query: userMessage,
				AIoutputs: ''
			})
			// 2. 初始化状态
			loading.value = true;
			currentAIResponse.value = ''
			prompt.value = '' // 清空输入框
			let result = '';
			let setTime = null;
			fetchEventSource(`${config.baseURL}/api/ai/chat/run/7`, {
				method: 'POST',
				headers: {
					'Accept': 'text/event-stream',
					"Content-Type": "application/json",
					"token": useUserStore().token
				},
				timeout: 1200000000000000, // 超时
				openWhenHidden: true,
				body: JSON.stringify({
					query: userMessage,
					conversationId: conversationId.value,
					inputs: {
						websiteURL: "",
						fileURL: ""
					}
				}),
				onmessage(event) {
					// 处理接收到的消息
					result += event.data;
					if (!setTime) {
						setTime = setTimeout(() => {
							if (result.indexOf('markdown') > -1) {
								initChatList();
							} else {
								chatHistory.value[chatHistory.value.length - 1].AIoutputs =
									returnAIoutputs(result);
								scrollToBottom();
								clearTimeout(setTime);
								loading.value = false;
								setTime = null;
							}
						}, 1000)
					}
				},
				onopen(response) {
					// 连接打开时的回调
					console.log('Connection opened:', response.status);
				},
				onerror(error) {
					// 错误处理
					console.error('Error:', error);
				},
				onclose() {
					console.log('close');
					// 连接关闭时的回调
					loading.value = false;
				}
			})
		} catch (error) {
			console.error("请求失败：", error);
		}
	}
	const scrollToBottom = () => {
		nextTick(() => {
			if (chatBody.value) {
				chatBody.value.scrollTop = chatBody.value.scrollHeight
			}
		})
	}
	const returnUserInputs = (data) => {
		if (!data) return '';
		return JSON.parse(data).query;
	}
	const deduplicateByTypeAndId = (arr) => {
		const map = new Map();

		arr.forEach(item => {
			const key = item.type === 'step' && item.id ? `${item.type}-${item.id}` : item.type;
			map.set(key, item); // 后面覆盖前面的
		});

		return Array.from(map.values());
	}
	/**
	 * 使用 marked 解析 Markdown
	 * @param markdown 解析的文本
	 */
	const versionIndex = ref(1);
	const renderMarkdown = markdown => {
		const renderer = new marked.Renderer();
		renderer.code = ({
			text,
			lang,
			escaped
		}) => {
			const language = hljs.getLanguage(lang) ? lang : 'plaintext';
			const highlighted = hljs.highlight(text, {
				language
			}).value;
			return `<div class="hljs-box"><div class="hljs-title">${language.toLocaleUpperCase()}</div><pre class="hljs-pre"><code class="hljs language-${language}">${highlighted}</code></pre></div>`;
		};
		renderer.link = (href) => {
			let divBox = document.createElement('div');
			let div = document.createElement('div');
			div.innerHTML = `version-${versionIndex.value}`
			div.id = href.href;
			div.className = 'version-href'
			versionIndex.value++;
			divBox.appendChild(div);
			previewUrl.value = href.href;
			return divBox.innerHTML;
		};
		return marked('```markdown' + markdown.replaceAll('</n>', '\n') + '```', {
			renderer
		});
	};
	const AIClick = (url) => {
		emits('updateURL', url);
	}
	const selectVisible = ref(false);
	const functionList = ref(['登录功能']);
	const selectFunction = data => {
		AIMessage('新增' + data);
		selectVisible.value = false;
	}
	// 组件卸载时清除定时器（重要！）
	onUnmounted(() => {
		stopTimer()
	})
	const showLine = (type, item, list) => {
		let arr = list.filter(node => node.type === 'step');
		let index = arr.findIndex(node => node.id === item.id);
		if (type === 'top') {
			if (index <= 0) return false;
		} else {
			if (index >= arr.length - 1) return false;
		}
		return true;
	}
</script>
<template>
	<div class="ai-chat-container">
		<div class="chat-body" ref="chatBody">
			<div v-for="(message, index) in chatHistory" :key="index">
				<div class="user-message">
					<div class="message user-message-box">
						<div class="message-content" v-if="message.query" v-html="message.query"></div>
					</div>
				</div>
				<div class="message ai-message" v-if="!loading || message.AIoutputs" style="margin-top: 15px;">
					<div class="message-header">
						<el-avatar :size="30"
							src="https://file-node.oss-cn-shanghai.aliyuncs.com/youji/f9617c7f80da485cb3cc72b6accc62ed">
						</el-avatar>
						<div class="message-header-label" style="width: 100px;">AI助手</div>
					</div>
					<div class="message-content">
						<div class="ai-website-boxs">
							<div v-for="(item,index) in message.AIoutputs">
								<div class="wk-query" v-if="item.type === 'query'">{{item.label}}</div>
								<div class="wk-markdown wk-query" v-if="item.type === 'markdown'"
									v-html="renderMarkdown(item.label)">
								</div>
								<div :class="'wk-step timeline-'+item.type" v-if="item.type === 'step'">
									<div :class="'step-icon ' + item.status">
										<el-icon>
											<Check v-if="item.status === 'success'" />
											<Loading v-else />
										</el-icon>
									</div>
									<div class="wk-content">
										<div class="title">{{ item.label }}</div>
										<div class="content" v-if="item.status === 'success'">
											<el-icon>
												<Monitor />
											</el-icon>
											<span class="content-label">{{ item.label }}</span>
											<span class="content-describe">{{ item.describe }}</span>
										</div>
									</div>
									<div class="line line-top" v-if="showLine('top',item,message.AIoutputs)"></div>
									<div class="line line-bottom" v-if="showLine('bottom',item,message.AIoutputs)">
									</div>
								</div>
								<div class="wk-url" v-if="item.type === 'url'">
									<div class="label">{{item.label || '网站生成成功'}}</div>
									<el-button size="small" type="primary" @click="AIClick(item.url)">点击查看</el-button>
								</div>
							</div>
						</div>
						<!-- <el-button size="small" @click="reloadMessage(message.query)" :disabled="loading"
							style="margin-top: 10px;" v-if="message.AIoutputs.indexOf('系统繁忙，请重试')>-1">
							点击重试
						</el-button> -->
					</div>
				</div>
			</div>
			<div v-if="loading" class="typing-indicator">
				<div class="typing-dot"></div>
				<div class="typing-dot"></div>
				<div class="typing-dot"></div>
				<span style="margin-left: 10px;">思考中...</span>
			</div>
		</div>
		<div class="input-container">
			<div class="input-box">
				<el-input type="textarea" v-model="prompt" placeholder="给AI发送消息" resize="none" :rows="4"
					:autosize="{ minRows: 2, maxRows: 6 }">
				</el-input>
				<div class="input-button">
					<el-button style="margin-left: 10px;" size="default" :icon="Plus" :disabled="loading || !previewUrl"
						circle @click="selectVisible = true">
					</el-button>
					<el-button circle type="primary" @click="sendMessage" :disabled="!prompt.trim() || loading"
						:icon="Top">
					</el-button>
				</div>
			</div>
		</div>
		<el-dialog v-model="selectVisible" title="新增功能" width="800px" class="ai-dialog select-dialog">
			<div class="select-item">
				<el-row :gutter="15">
					<el-col :span="6" v-for="(item,index) in functionList" :key="index">
						<el-button style="width: 100%;" @click="selectFunction(item)">
							{{item}}
						</el-button>
					</el-col>
				</el-row>
			</div>
		</el-dialog>
	</div>
</template>


<style lang="scss">
	.message-image {
		width: 30px;
	}

	.hljs-box {
		border-radius: 5px;
		overflow: hidden;

		.hljs-title {
			background: #f2f3f5;
			padding: 5px 10px;
			color: #354052;
			font-weight: bold;
			border-bottom: 1px solid #d0d3d9;
		}

		.language-html,
		.language-markdown {
			background: #f1f2f5;
		}

		.hljs-pre {
			margin: 0;
		}
	}

	.version-href {
		border: 1px solid var(--el-border-color);
		padding: 5px 15px;
		border-radius: 6px;
		cursor: pointer;
		display: inline-block;
		margin-top: 5px;
	}

	.wk-query {
		padding: 12px 0;
		font-size: 15px;
		font-weight: 500;

		&:last-child {
			padding-bottom: 0;
		}
	}

	.wk-step {
		padding-top: 15px;
		padding-left: 20px;
		position: relative;

		.line {
			position: absolute;
			width: 1px;
			border-left: 1px dashed var(--el-border-color);
			left: 7px;
			z-index: 4;
		}

		.line-top {
			top: 0;
			height: 17px;
		}

		.line-bottom {
			top: 20px;
			bottom: 0;
		}

		.step-icon {
			position: absolute;
			left: 0;
			background: var(--el-color-warning);
			color: #fff;
			width: 14px;
			height: 14px;
			display: flex;
			align-items: center;
			justify-content: center;
			font-size: 12px;
			border-radius: 16px;
			top: 18px;
			z-index: 9;

			&.success {
				background: var(--el-color-success);
			}
		}

		.timeline-warning {
			.step-icon {
				animation: rotating 2s linear infinite;
			}
		}
	}

	.wk-url {
		padding-top: 15px;

		.label {
			font-size: 15px;
			font-weight: 500;
			margin-bottom: 10px;
		}
	}

	.wk-timeline {
		.el-timeline-item__icon {
			font-size: 10px;
		}

		.el-timeline-item {
			padding-bottom: 10px;
		}
	}

	.wk-content {
		.title {
			color: #222;
		}

		.content {
			background: rgb(246, 247, 249);
			border: 1px solid rgb(234, 234, 234);
			height: 30px;
			line-height: 28px;
			border-radius: 30px;
			padding: 0 15px;
			font-size: 13px;
			box-sizing: border-box;
			color: rgb(120, 121, 121);
			margin-top: 10px;
			display: flex;
			align-items: center;
		}

		.content-label {
			margin: 0 10px 0 5px;
		}

		.content-describe {
			font-size: 12px;
		}
	}
</style>
<style scoped lang="scss">
	.ai-chat-container {
		width: 100%;
		height: 100%;
		background: white;
		border-radius: 16px;
		box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
		overflow: hidden;
		display: flex;
		flex-direction: column;
	}

	/* 聊天内容区域 */
	.chat-body {
		flex: 1;
		padding: 20px;
		overflow-y: auto;
		background: #f8fafc;
		display: flex;
		flex-direction: column;
		gap: 15px;
		overflow-x: hidden;
	}

	.message {
		padding: 12px 16px;
		border-radius: 18px;
		position: relative;
		animation: fadeIn 0.3s ease;
		line-height: 1.5;
		display: inline-block;
		max-width: 100%;
	}

	.user-message {
		display: flex;
		justify-content: end;

		.user-message-box {
			background: #7a72cf;
			color: white;
			border-bottom-right-radius: 4px;
		}
	}

	.ai-message {
		background: #ffffff;
		border: 1px solid #e9ecef;
		margin-right: auto;
		border-bottom-left-radius: 4px;
		width: 100%;
	}

	.message-header {
		display: flex;
		align-items: center;
		font-weight: 500;
	}

	.message-header-label {
		flex: 1;
		width: 0;
		overflow: hidden;
		margin-left: 5px;
		font-weight: bold;
	}

	.message-time {
		font-size: 0.7rem;
		opacity: 0.7;
		margin-top: 5px;
		text-align: right;
	}

	/* 加载指示器 */
	.typing-indicator {
		display: flex;
		align-items: center;
		padding: 12px 16px;
		background: white;
		border: 1px solid #e9ecef;
		border-radius: 18px;
		width: fit-content;
		margin-bottom: 15px;
		border-bottom-left-radius: 4px;
	}

	.typing-dot {
		width: 8px;
		height: 8px;
		background: #6c757d;
		border-radius: 50%;
		margin: 0 3px;
		animation: typing 1.4s infinite;
	}

	.typing-dot:nth-child(1) {
		animation-delay: 0s;
	}

	.typing-dot:nth-child(2) {
		animation-delay: 0.2s;
	}

	.typing-dot:nth-child(3) {
		animation-delay: 0.4s;
	}

	/* 输入区域 */
	.input-container {
		padding: 10px;
		box-sizing: border-box;
		background: #f8fafc;

		.input-box {
			background: #ffffff;
			padding: 5px 0;
			border: 1px solid var(--el-border-color);
			border-radius: 10px;
		}

		:deep(.el-textarea__inner) {
			border: none;
			background: transparent;
			box-shadow: none;

			&:hover {
				box-shadow: none;
			}
		}
	}

	.input-button {
		margin-top: 10px;
		text-align: right;
		padding: 5px 10px;
	}

	/* 动画 */
	@keyframes fadeIn {
		from {
			opacity: 0;
			transform: translateY(10px);
		}

		to {
			opacity: 1;
			transform: translateY(0);
		}
	}

	@keyframes typing {

		0%,
		60%,
		100% {
			transform: translateY(0);
		}

		30% {
			transform: translateY(-5px);
		}
	}
</style>