<template>
	<view class="dialog-generation">
		<view class="subject-matter-ofText" :style="{ paddingBottom: keyboardHeight + 'px' }">
			<!-- 顶部导航栏 -->
			<div class="navbar">
				<view class="navbar-left">
					<image @click="goBack()" class="back" src="../../static/vip/hy_icon_jiantou.png"></image>
					<view class="elf-name">精灵·小萌</view>
					<image class="deepseek" src="../../static/makedetail/deepseek-logo.png"></image>
				</view>
				<view class="navbar-right">
					<image @click="switchToNormal()" class="primary" src="../../static/makedetail/primary.png"></image>
					<image @click="newChar()" class="createChat" src="../../static/makedetail/createChat.png"></image>
				</view>
			</div>

			<!-- <view class="navbar-reserveASeat"> </view>  -->
			<!-- 聊天内容区 -->
			<scroll-view class="chat-content" :scroll-into-view="toView" scroll-y
				:style="{ height: `calc(100% - ${370 + textareaHeight}rpx)` }" @scroll="onChatScroll">
				<template v-if="messages && messages.length > 0">
					<!-- <scroll-view class="chat-content" scroll-y> -->
					<view v-for="(msg, idx) in messages" :key="idx" :class="['chat-bubble', msg.role]">
						<template v-if="msg.role === 'user'">
							{{ msg.content }}
						</template>
						<template v-else-if="msg.role === 'ai'">
							<view class="ai-bubble-row">
								<view class="ai-avatar">
									<image src="../../static/makedetail/characterProfilePicture.png" mode="aspectFill">
									</image>
								</view>
								<view class="ai-bubble-content" v-if="!msg.isStartGenerating">
									<template v-if="idx === lastAiIndex && isLoading">
										<text>{{ displayText }}</text>
										<text v-if="isLoading" class="loading-dot">...</text>
									</template>
									<template v-else>
										<text>{{ msg.content }}</text>
									</template>
								</view>
								<view v-else class="ai-bubble-content">
									<text>OK!~小萌正在根据你的描述生成形象中</text><br>
									<div v-if="msg.isStartGenerating && msg.startGeneratingId == 0" class="btn-box">
										点击查看
										({{ countdown }}) s</div>
									<div v-else
										@click="goPage(`/pages/makedetail/makeImgDetail?id=${msg.startGeneratingId}`)"
										class="btn-box"> 点击查看
									</div>
								</view>
							</view>
						</template>
					</view>
					<view id="bottom-anchor"></view>
					<view v-if="error" class="chat-bubble ai error">{{ error }}</view>

					<image v-if="showToBottomBtn && keyboardHeight === 0" class="to-bottom-btn" @click="scrollToBottom"
						src="../../static/makedetail/toBottomBtn.png"></image>
				</template>
				<template v-else>
					<view class="chat-content-empty">
						<image src="../../static/makedetail/characterProfilePicture.png" mode="aspectFill"></image>
						<view class="chat-content-empty-title">嗨！我是创梦精灵</view>
						<view class="chat-content-empty-desc">与我聊聊你想要生成的角色吧！</view>
					</view>
				</template>
			</scroll-view>
			<!-- <view class="bom-reserveASeat"></view> -->

			<view class="bom-box" :style="{ bottom: 0 + 'px', height: `${190 + textareaHeight}rpx` }">
				<view class="bom-box-bg">
					<c-lottie ref="cLottieRef" :src='"/static/lottie/xiaomeng.json"' class="icon-img" height="108rpx"
						width="112rpx" :loop="true" :autoPlay="false"></c-lottie>
						
				</view>
				<!-- 底部输入区 -->
				<view class="input-bar">
					<!-- <image class="icon-img" src="../../static/makedetail/characterProfilePicture.png" mode="aspectFill">
					</image> -->


					<textarea :autoHeight="true" class="input-box" :adjust-position="false" v-model="question"
						:disabled="isLoading" placeholder="给我发送消息吧..." maxlength="400" @input="onTextareaInput"
						confirm-type="search" @confirm="onSend" rows="1"
						style="overflow-y:auto;max-height:176rpx;min-height:44rpx;" />
					<!-- <button class="send-btn" :disabled="isLoading || !question.trim()" @click="onSend">{{ isLoading ?
						'生成中...' :
						'发送' }}</button> -->
					<image v-if="isLoading" class="stop" src="../../static/makedetail/stop.png" mode=""
						@click="stopStreamAnswer" />
					<image v-else-if="!isLoading && !question.trim() && keyboardHeight === 0" class="keyboard"
						src="../../static/makedetail/keyboard.png" mode="" />

					<image v-else-if="!isLoading && question.trim() && keyboardHeight !== 0" class="send"
						src="../../static/makedetail/send.png" mode="" @click="onSend" />
				</view>
				<!-- 底部提示 -->
				<view class="footer-tip">内容由AI生成，禁用相关功能请联系管理员。</view>
			</view>
		</view>

		<DialogBox ref="DialogBox"></DialogBox>
	</view>
</template>
<script>
import websocket from '@/common/websocket.js';

export default {
	data() {
		return {
			question: '',
			answer: '',
			displayText: '',
			isComplete: false,
			isLoading: false,
			error: null,
			retryCount: 0,
			maxRetries: 3,
			timer: null,
			lastResponseTime: 0,
			timeout: 30000,
			typingSpeed: 50,
			messages: [],
			lastAiIndex: -1,
			keyboardHeight: 0,
			statusBarHeight: 0,
			windowBottom: 0,
			toView: '',
			showToBottomBtn: false,
			textareaHeight: 0,
			isConnected: false,
			isStartGenerating: false,
			countdown: 0,
		};
	},
	methods: {
		scrollToBottom() {
			this.toView = '';
			this.$nextTick(() => {
				this.toView = 'bottom-anchor';
			});
		},
		async initWebSocket() {
			if (this.isConnected) return;

			try {
				await websocket.connect('wss://e.zhichao.art/Gapi/Work/streamAnswer', {
					uuid: getApp().globalData.uuid
				});

				this.isConnected = true;

				// 设置消息处理回调
				websocket.onMessage((data) => {
					console.log("data:", data);
					if (this.isLoading) {
						if (data.includes('[DONE]')) {
							this.completeAnswer();
						} else if (data == 'PING' || data == 'PONG') {
							// 心跳消息   忽略
						} else if (data.includes('ID:')) {
							// 提取ID
							const aiMsg = this.messages[this.lastAiIndex];
							if (aiMsg) {
								aiMsg.startGeneratingId = data.split(':')[1];
							}
						} else if (data.includes('OKOKOK')) {
							const aiMsg = this.messages[this.lastAiIndex];
							if (aiMsg) {
								aiMsg.isStartGenerating = true;
							}
							this.isStartGenerating = true;
							this.countdownFun(20);
						} else {
							const aiMsg = this.messages[this.lastAiIndex];
							if (aiMsg) {
								aiMsg.isStartGenerating = false;
								this.displayText += data;
								this.answer += data;
								aiMsg.content += data;
								this.retryCount = 0;
								this.lastResponseTime = Date.now();
								this.scrollToBottom();
							}
						}
					}
				});

				// 设置错误处理回调
				websocket.onError((error) => {
					console.error('WebSocket错误:', error);
					this.isConnected = false;
					this.handleError(error);
				});

				// 设置关闭处理回调
				websocket.onClose(() => {
					console.log('WebSocket已关闭');
					this.isConnected = false;
					this.isLoading = false;
				});

			} catch (error) {
				console.error('WebSocket初始化失败:', error);
				this.isConnected = false;
				this.handleError(error);
			}
		},
		async startStreamAnswer(content) {
			if (!content.trim()) {
				uni.showToast({
					title: '请输入问题',
					icon: 'none'
				});
				return;
			}

			// 检查连接状态，如果断开则重连
			if (!this.isConnected) {
				try {
					await this.initWebSocket();
				} catch (error) {
					console.error('重连失败:', error);
					uni.showToast({
						title: '连接已断开，请重试',
						icon: 'none'
					});
					return;
				}
			}

			this.resetState();
			this.messages.push({ role: 'user', content });

			try {
				this.isLoading = true;
				let aiMsg = {
					role: 'ai',
					content: '',
					isStartGenerating: false,
					startGeneratingId: 0
				};
				this.messages.push(aiMsg);
				this.lastAiIndex = this.messages.length - 1;

				// 发送消息
				websocket.send(content);

			} catch (error) {
				console.error('发送消息失败:', error);
				this.handleError(error);
			}
		},
		onSend() {
			if (!this.question.trim() || this.isLoading) return;
			this.startStreamAnswer(this.question);
			this.question = '';
		},
		resetState() {
			this.answer = '';
			this.displayText = '';
			this.isComplete = false;
			this.error = null;
			this.retryCount = 0;
			this.lastResponseTime = Date.now();
		},
		handleError(error) {
			if (this.retryCount < this.maxRetries) {
				this.retryCount++;
				this.retryRequest();
			} else {
				this.error = '请求失败，请稍后重试';
				this.isLoading = false;
				uni.showToast({
					title: this.error,
					icon: 'none'
				});
			}
		},
		retryRequest() {
			uni.showToast({
				title: `正在重试 (${this.retryCount}/${this.maxRetries})`,
				icon: 'none'
			});
			setTimeout(() => {
				this.startStreamAnswer(this.question);
			}, 1000 * this.retryCount);
		},
		completeAnswer() {
			this.isComplete = true;
			this.isLoading = false;
		},
		stopStreamAnswer() {
			if (this.timer) {
				clearTimeout(this.timer);
				this.timer = null;
			}
			this.isLoading = false;
		},
		checkTimeout() {
			if (Date.now() - this.lastResponseTime > this.timeout) {
				this.handleError(new Error('请求超时'));
			}
		},

		goBack() {
			uni.navigateBack({
				delta: 1
			});
		},
		onChatScroll(e) {
			const threshold = 600; // 离底部100px以内不显示按钮
			const {
				scrollHeight,
				scrollTop
			} = e.detail;
			const clientHeight = e.detail.clientHeight || e.detail.height || 0;
			if (scrollHeight - scrollTop - clientHeight > threshold) {
				this.showToBottomBtn = true;
			} else {
				this.showToBottomBtn = false;
			}
		},
		onTextareaInput(e) {
			console.log(e.detail);

			// 获取textarea的实际高度
			const query = uni.createSelectorQuery().in(this);
			query.select('.input-box').boundingClientRect(data => {
				if (data) {
					// 将px转换为rpx (假设设计稿是750rpx宽度)
					const height = (data.height * 750) / uni.getSystemInfoSync().windowWidth;
					// 减去基础高度90rpx，得到额外增加的高度
					this.textareaHeight = Math.max(0, height - 90);
					// 滚动到底部
					this.scrollToBottom();
				}
			}).exec();
		},
		retrieveHistoricalRecords() {
			uni.request({
				url: this.$apiHost + '/Work/streamAnswerLast',
				method: 'GET',
				header: {
					'content-type': 'application/json',
					'sign': getApp().globalData.headerSign
				},
				data: {
					uuid: getApp().globalData.uuid,
					task_type: 2
				},
				success: (res) => {
					console.log("获取历史记录：", res.data.list);
					if (res.data.success === "yes" && res.data.list) {
						this.messages = res.data.list
						if (res && res.data && res.data.list && res.data.list.length > 0) {
							this.showToBottomBtn = true
						}
					} else {
						this.messages = []
					}
				},
				fail: (err) => {
					console.log('获取历史记录失败', err);
					uni.showToast({
						title: '获取历史记录失败',
						icon: 'none'
					});
				}
			})
		},
		// 重新计算元素高度
		recalculateHeights() {
			// 重新计算textarea高度
			const query = uni.createSelectorQuery().in(this);
			query.select('.input-box').boundingClientRect(data => {
				if (data) {
					const height = (data.height * 750) / uni.getSystemInfoSync().windowWidth;
					this.textareaHeight = Math.max(0, height - 90);
				}
			}).exec();
		},
		countdownFun(n) {
			if (this.timer) {
				clearInterval(this.timer);
			}
			this.countdown = n;
			// 倒计时
			this.timer = setInterval(() => {
				this.countdown--;
				if (this.countdown <= 0) {
					clearInterval(this.timer);
				}
			}, 1000);
		},
		goPage(page) {
			uni.navigateTo({
				url: page,
			});
		},
		newChar() {
			this.$refs["DialogBox"]
				.confirm({
					title: "是否创建新对话",
					content: "立即结束当前对话内容，开启新的对话?",
					DialogType: "inquiry",
					btn1: "取消",
					btn2: "确定",
					animation: 0,
				})
				.then(() => {
					websocket.send('clear');
					this.retrieveHistoricalRecords()
				});

		},
		switchToNormal() {
			this.$refs["DialogBox"]
				.confirm({
					title: "是否切回常规模式",
					content: "切换至普通常规模式进行创作?",
					DialogType: "inquiry",
					btn1: "取消",
					btn2: "确定",
					animation: 0,
				})
				.then(() => {
					this.goPage('/pages/makedetail/makeImgDetail')
				});

		}
	},
	async created() {
		await this.initWebSocket();
		this.retrieveHistoricalRecords();
		this.timer = setInterval(() => {
			if (this.isLoading) {
				this.checkTimeout();
			}
		}, 1000);

		uni.onKeyboardHeightChange(res => {
			this.keyboardHeight = res.height;
			if (res.height === 0) {
				this.$refs.cLottieRef.call('stop')
			} else {
				this.$refs.cLottieRef.call('play')

			}
			this.$nextTick(() => {
				this.recalculateHeights();
			});
		});

		const systemInfo = uni.getSystemInfoSync();
		this.statusBarHeight = systemInfo.statusBarHeight;
		this.windowBottom = systemInfo.safeAreaInsets ? systemInfo.safeAreaInsets.bottom : 0;
	},

	beforeDestroy() {
		websocket.close();
		this.stopStreamAnswer();
	}
}
</script>

<style lang="scss">
@import './intelligentLifeChart.scss';

.to-bottom-btn {
	position: fixed;
	right: 50%;
	transform: translateX(50%);
	bottom: 20rpx;
	width: 60rpx;
	height: 60rpx;
	bottom: 220rpx;
	z-index: 999;
	opacity: .75;
	transition: opacity 0.2s;
}

.ai-bubble-row {
	display: flex;
	align-items: flex-start;
}

.ai-avatar {
	width: 60rpx;
	height: 60rpx;
	border-radius: 50%;
	margin-right: 20rpx;
	border: solid 2rpx rgb(238, 238, 238, .3);
	display: flex;
	align-items: flex-end;
	justify-content: center;

	image {
		width: 52rpx;
		height: 52rpx;
	}
}

.ai-bubble-content {
	flex: 1;
}
</style>tyle>