<template>
	<view class="main_div max_page">
		<nav-bar :is_seat="true"></nav-bar>
		<view class="nav-div">
			<view class="title ellipsis-text">
				{{ paperData.name }}
			</view>
			<view class="back_div" @click="exit_practice">
				<image :src="practiceExitIcon()" class="img"></image>
			</view>
		</view>
		<view class="countdown-and-question-number-div">
			<view class="top">
				<view class="countdown">
					<text class="grey">答题进度</text>
					<text class="bold">{{ questionNumber + 1 }}</text>
					<text class="grey">/{{ storageIdList.length }}</text>
				</view>
				<view class="question"></view>
			</view>
			<view class="progress">
				<uv-line-progress
					:percentage="progress"
					:showText="false"
					activeColor="#FFFFFF"
					inactiveColor="#89B8FF"
					:height="8"
				></uv-line-progress>
			</view>
		</view>
		<view class="scroll_div">
			<swiper
				class="swiper"
				:indicator-dots="false"
				@change="swiperChange"
				:current="questionNumber"
				easing-function="linear"
				@transition="transition"
				@animationfinish="animationfinish"
			>
				<swiper-item v-for="(item, index) in topicList">
					<view class="content">
						<view class="expose_shadow"></view>
						<scroll-view :scroll-y="true" class="scroll-Y" :show-scrollbar="false" :refresher-threshold="0">
							<view class="" v-if="item === '00'">加载中</view>

							<view class="" v-if="item === '01'">加载失败</view>
							<view class="" v-if="item === '02'">加载失败</view>
							<Subject
								v-else
								:item="item"
								:mode="mode"
								:isPreview="item.isPreview"
								:clearResult="item.clearResult"
								@subject_click="subject_click"
								v-model="item.my_answer"
							></Subject>
						</scroll-view>
					</view>
				</swiper-item>
			</swiper>
		</view>
		<view class="fixed-box font_pf" :style="{ marginBottom: popup_input_bottom }">
			<view class="touch-btn-div" :class="{ show: showTouchBtn }">
				<TouchBtn
					ref="touchBtnRef"
					class="talk-btns"
					@submit="touchBtnSubmit"
					disabledText="只能进行一条回答"
					:isDisabled="touchIsDisabled"
				/>
			</view>
		</view>
		<!-- 反馈组件 -->
		<Feedback ref="feedbackRef"></Feedback>
		<!-- 结尾弹出层 -->
		<Dialog ref="dialogRef" @button_click="result_click"></Dialog>
	</view>
</template>

<script setup>
	import { ref, reactive, computed, onMounted, nextTick, onUnmounted } from 'vue';
	import { onLoad, onHide, onShow, onUnload } from '@dcloudio/uni-app';

	import Feedback from '@/pages/examination/components/feedback.vue';
	import Dialog from '@/pages/examination/components/dialog.vue';
	import Subject from '@/components/examination/subject.vue';
	import CharactersSubject from '@/components/examination/characters-subject.vue';
	import TouchBtn from '@/components/examination/touchBtn.vue';
	import common from '@/common/common';
	import { setPageCache, getPageCache, setupKeyboardHeightListener } from '@/common/common';
	import { commonUploadVoiceFile } from '@/api/common.js';
	import { optionErrorIcon, examinationSheetIcon, practiceExitIcon } from '@/common/imgSvg';
	import { practiceAnswer, practiceCommit, queryCrsPracticeAnswerResult } from '@/api/practice.js';

	import { queryMistakesAnswerByMisId, mistakesCorrect } from '@/api/wrongQuestionRecord.js';
	const feedbackRef = ref(null);
	const dialogRef = ref(null);
	const touchBtnRef = ref(null);

	const mode = ref('practice'); // 考试 examination 练习practice
	const paperData = reactive({
		name: '' // 名称
	}); // 试卷信息
	const topicList = reactive([]); // 问题列表
	const storageIdList = ref([]); // 所有题ID列表
	const storageIdDict = ref({}); // 所有题ID为键的字典
	const popup_input_bottom = ref('0px');
	const questionNumber = ref(0); // 题号

	// 根据课程ID获取课程的题目  undefined为没有， 00为加载中， 02为加载失败

	const topic = computed({
		get: () => topicList[questionNumber.value],
		set: (val) => (topicList[questionNumber.value] = val)
	});

	const showTouchBtn = computed(() => {
		return topic.value?.qnsTyp === 'ES';
	});

	// 下面语音组件的禁用状态判断
	const touchIsDisabled = computed(() => topic.value?.es_status !== '' && topic.value?.es_status !== undefined);

	const progress = computed(() => {
		// 计算进度百分比（保留两位小数）
		const total = storageIdList.value.length;
		if (total === 0) return 0;
		const completed = questionNumber.value + 1;
		return Math.min(Math.round((completed / total) * 10000) / 100, 100);
	});

	// 滑动切换
	const swiperChange = (item) => {
		questionNumber.value = item.detail.current;
	};
	const isTriggered = ref(false); // 下面这个得防抖
	// 滑动发生改变
	const finishCurrent = ref(questionNumber.value);
	// 滑动组件结束事件
	const animationfinish = (event) => {
		finishCurrent.value = event.detail.current;
	};
	// 判断是否滑动结束
	const isLastTopic = computed(
		() => topicList.length === finishCurrent.value + 1 && finishCurrent.value === questionNumber.value
	);

	const transition = (event) => {
		if (isTriggered.value) return;
		const dx = event.detail.dx;
		if (dx > 90 && dx < 250 && isLastTopic.value && ['P', 'U'].includes(topic.value.judgeResult)) {
			// 如果是最后一题并且右滑动大于50,并且这题已经答了，就触发练习完成
			isTriggered.value = true;
			hand_in_paper_button_click();
		}
	};
	const subject_click = (type, params) => {
		if (type === 'feedback') {
			// 反馈
			feedbackRef.value.open(params.qnsId);
		} else if (type === 'answer') {
			//多选点击按钮答题
			if (params.qnsTyp === 'MU') {
				submitProblem({
					anserResult: params.answer.join(',')
				});
			}
		} else if (type === 'choose') {
			//单选判断点击选项答题
			if (['JD', 'SN'].includes(params.qnsTyp)) {
				submitProblem({ anserResult: params.answer.join(',') });
			}
		} else if (type === 'complete') {
			// 问答题点击完成
			// ossAddr
			// anserResult 作答结果
			// ossKey 对象存储
			submitProblem(params.answer);
		} else if (type === 'again') {
			// 问答题点击重答
			topic.value.my_answer = {};
			topic.value.isPreview = false;
			topic.value.es_status = ''; // 取消转圈
		}
	};

	// 单题回答
	const submitProblem = (answer) => {
		console.log('答题内容', answer);
		console.log('答单题', topic);
		common.loading('答题中');
		mistakesCorrect({
			misId: topic.value.misId,
			ossKey: '',
			...answer
		})
			.then(async (res) => {
				let traQnsInfoVo;
				// 是问答题
				if (topic.value.qnsTyp === 'ES') {
					try {
						const result = await queryWithRetry(res.body.execLogId);
						traQnsInfoVo = result.body.traQnsInfoVo;
					} catch (e) {
						common.hideLoading();
						topic.value.isPreview = false;
						return;
					}
				} else {
					traQnsInfoVo = res.body;
				}
				topic.value.isPreview = true; // 不能在点击了，打开预览模式
				console.log('给出来的traQnsInfoVo', traQnsInfoVo);
				common.hideLoading();
				topic.value.clearResult = false; // 不清除正确答案
				topic.value.analyContent = traQnsInfoVo.analyContent; // 答案解析
				// 更新选项正确项目
				topic.value.itemVos = traQnsInfoVo.itemVos; // 答案选项（todo应该不这样替换）
				topic.value.anserResult = traQnsInfoVo.anserResult; // 正确答案字符串分割
				topic.value.judgeResult = traQnsInfoVo.judgeResult; // 正确答案字符串分割
				const judgeResultStatus = traQnsInfoVo.judgeResult === 'P'; // P为正确U为错误
				// 加载下一题
				if (!addProblem(questionNumber.value + 1)) {
					// 返回false说明到了最后一题
					console.log('最后一题', topic.value.qnsTyp, !judgeResultStatus);
					if (topic.value.qnsTyp === 'ES' || !judgeResultStatus) {
						// 最后一题是问答题，或者答错了，都不自动弹出
						return;
					} else {
						await hand_in_paper_button_click();
					}
				} else {
					addRequestProblem(questionNumber.value + 1);
					// 自动切换下一题的条件
					if (
						judgeResultStatus && // 条件1.答题正确
						topic.value.qnsTyp !== 'ES' // 问答题答对打答错都不切换
					) {
						nextTick(() => {
							setTimeout(() => {
								questionNumber.value++;
							}, 200);
						});
					} else {
						console.log('为什么不跳转2', judgeResultStatus);
						console.log('为什么不跳转3', topic.value.qnsTyp !== 'ES');
					}
				}
			})
			.catch(() => {
				common.hideLoading();
			});
	};

	// 问答题轮询结果方法
	const queryWithRetry = (execLogId, maxRetries = 10) => {
		// 递归终止条件：达到最大重试次数
		if (maxRetries <= 0) {
			return Promise.reject(new Error('超过最大重试次数，查询失败'));
		}
		return queryCrsPracticeAnswerResult({ execLogId })
			.then((res) => {
				console.log('queryCrsPracticeAnswerResult', maxRetries, res.body);
				const isWait = res.body.isWait;
				if (isWait === 'Y') {
					// 如果是Y，延迟2秒后重试，重试次数减1
					return new Promise((resolve) => {
						setTimeout(() => {
							resolve(queryWithRetry(execLogId, maxRetries - 1));
						}, 2000);
					});
				} else {
					// 不是Y，直接返回结果
					return res;
				}
			})
			.catch((error) => {
				// 对接口调用错误进行重试
				if (maxRetries > 0) {
					return new Promise((resolve) => {
						setTimeout(() => {
							resolve(queryWithRetry(execLogId, maxRetries - 1));
						}, 2000);
					});
				}
				return Promise.reject(error);
			});
	};

	// 录音组件提交
	const touchBtnSubmit = (type, submitObj) => {
		const old_text = touchBtnRef.value?.clearinputText(); // 清除发送框数据

		if (type === 'voice') {
			topic.value.es_status = '00'; // 00转圈
			const voicePath = submitObj;
			commonUploadVoiceFile(voicePath, '/traask/traAskchat/voiceTrans', {})
				.then((res) => {
					let _res = JSON.parse(res.data);
					if (_res.rtnCode === '0000') {
						topic.value.es_status = '02';
						topic.value.my_answer = {
							anserResult: _res.body.transContent,
							ossKey: _res.body.fileId,
							ossAddr: _res.body.ossFileAddr,
							voicePath: voicePath
						};
					}
				})
				.catch((err) => {
					topic.value.es_status = ''; // 取消转圈
					// 失败了再把发送框数据还原回去
					touchBtnRef.value?.clearinputText(old_text); // 清除发送框数据
					common.msg('系统异常，请联系管理员');
				});
		} else if (type === 'text') {
			topic.value.es_status = '01';
			topic.value.my_answer = {
				anserResult: submitObj // 正确答案文字内容
			};
		}
	};

	// 添加下一道题
	const addProblem = async (index) => {
		// index 要加载的题号
		if (index < topicList.length) return true; // 说明此题已经加载
		if (topicList.length >= storageIdList.value.length) return false; // 说明已经加载所有题了

		const id = storageIdList.value[index]; // 找到id
		if (storageIdDict.value[id] === undefined) {
			//尚未加载（几乎不可能）
			return true;
		} else if (storageIdDict.value[id].state === '00') {
			//加载中
		} else if (storageIdDict.value[id].state === '01') {
			// 已经加载
			// console.log('增加已经加载的数据', storageIdDict.value[id].topic);
			topicList.push(storageIdDict.value[id].topic);
			return true;
		} else if (storageIdDict.value[id].state === '02') {
			//加载失败
		}
		topicList.push(storageIdDict.value[id].state);
		return true;
	};

	// 网络加载题，并且放在
	const addRequestProblem = async (index, success = () => {}) => {
		const id = storageIdList.value[index];
		const preload = () => {
			nextTick(() => {
				// 最多只预加载当前题号的后两道题（questionNumber.value是当前题号）
				// 修正索引判断：确保 index + 1 是有效的数组索引（< 数组长度）
				if (index + 1 === storageIdList.value.length) return; // 防止下标越界
				if (index + 1 > questionNumber.value + 2) return; // 防止加载太多
				const last_id = storageIdList.value[index + 1];
				// 判断是否加载
				if (last_id in storageIdDict.value) {
					return;
				}else {
					addRequestProblem(index + 1, success);
				}
			});
		};

		if (storageIdDict.value[id] && storageIdDict.value[id].state === '01') {
			preload();
			return;
		}

		storageIdDict.value[id] = { state: '00' };
		queryMistakesAnswerByMisId({ misId: id })
			.then(({ body }) => {
				const topic_item = {
					...body,
					isPreview: false,
					clearResult: true,
					es_status: '', // 预设一下问答题的状态，'' 空为没有 00 转圈 01 播放，其他暂定
					my_answer: []
				};
				storageIdDict.value[id] = {
					state: '01',
					topic: topic_item
				};
				success(topic_item);
				preload();
			})
			.catch(() => {
				storageIdDict.value[id] = { state: '02' };
			})
			.finally(() => {
				// if (isLoading) common.hideLoading();
			});
	};
	// 初始化时检查
	onLoad(() => {
		const correct = getPageCache('correct');
		if (!correct) {
			return common.navigateBack();
		}
		paperData.name = correct.name;
		storageIdList.value = correct.list;

		setupKeyboardHeightListener((height) => {
			popup_input_bottom.value = `${height}px`;
		});

		setTimeout(() => {
			addRequestProblem(0, () => {
				addProblem(0);
			});
			// addProblem(0, true);
		}, 10);
	});

	const result_click = async ({ key }) => {
		isTriggered.value = false; // 恢复
		if (key === 'return') {
			// 返回
			dialogRef.value.close();
			await nextTick();
			common.navigateBack();
		} else if (key === 'exit') {
			// 中途退出
			dialogRef.value.close();
			common.loading();
			await practiceCommit({ exrId: paperData.exrId, stat: 'U' });
			common.hideLoading();
			await nextTick();
			common.navigateBack();
		} else if (key === 'revert') {
			// 返回
			dialogRef.value.close();
		}
	};
	const style_button_1 = {
		color: '#FFFFFF',
		fontSize: '30rpx',
		backgroundColor: '#0066FF',
		borderRadius: '8rpx'
	};
	const style_button_2 = {
		color: '#0066FF',
		fontSize: '30rpx',
		backgroundColor: '#E2EDFF',
		borderRadius: '8rpx'
	};
	// 弹出框配置
	const dialogConfiguration = reactive({});
	// 交卷按钮点击，打开交卷确认框
	const hand_in_paper_button_click = async () => {
		console.log('交卷按钮');
		const stat = 'P';
		common.redirectTo(`/pages/wrongQuestionRecord/result?stat=${stat}`);
	};

	// 中途退出
	const exit_practice = () => {
		dialogRef.value.open({
			title: '确认现在退出吗？',
			buttonList: [
				{
					key: 'exit',
					name: '退出',
					style: style_button_1
				},
				{
					key: 'revert',
					name: '返回',
					style: style_button_2
				}
			]
		});
	};

	onShow(() => {});
	onHide(() => {});
	onUnload(() => {});
</script>

<style scoped lang="scss">
	$bg-margin-left: 30rpx;

	.popup_title_text {
		color: red;
	}

	.popup {
		//答题卡
		z-index: 1800;
		padding: 0 38rpx;

		.sheet_popup_div {
			width: 100%;
			height: 100%;
			background-color: #ffffff;
			padding: 10rpx 34rpx;
			display: flex;
			flex-direction: column;
			align-items: center;
			border-radius: 16rpx 16rpx 0px 0px;
			position: relative;

			.title_div {
				width: 100%;
				text-align: center;
				padding: 30rpx 0;
				font-family: PingFangSC;
				font-weight: 600;
				font-size: 34rpx;
				color: #000000;
				text-align: center;
				font-style: normal;
				border-bottom: 2rpx solid #efefef;
			}

			.popup_back_div {
				width: 60rpx;
				height: 60rpx;
				position: absolute;
				top: 30rpx;
				right: 30rpx;
				display: flex;
				align-items: center;
				justify-content: center;

				.img {
					width: 30rpx;
					height: 30rpx;
				}
			}

			.sheet_table {
				margin-top: 48rpx;
				margin-bottom: 48rpx;
				display: flex;
				flex-wrap: wrap;
				width: calc(100vw - 108rpx);
				align-content: space-between;

				.sheet_table_item {
					width: calc((100vw - 108rpx) / 5 - 16rpx);
					height: calc((100vw - 108rpx) / 5 - 16rpx);
					margin: 8rpx;
					border: 2rpx solid #e5e5e5;
					border-radius: 50%;
					display: flex;
					align-items: center;
					justify-content: center;
					font-size: 32rpx;
					color: #999999;
				}

				.current {
					background-color: rgba(0, 102, 255, 0.6);
					border-color: #0066ff;
					color: #ffffff;
				}

				.completed {
					// 已完成
					background-color: rgba(0, 102, 255, 0.1);
					border-color: #0066ff;
					color: #0066ff;
				}

				.mark,
				.completed.mark {
					background-color: rgba(232, 181, 49, 0.1);
					color: #e8b531;
					border-color: #e8b531;
				}

				.current.mark {
					// 已完成
					background-color: rgba(0, 102, 255, 0.6);
					color: #ffffff;
					border-color: #e8b531;
				}
			}

			.sheet_button {
				width: 100%;
			}
		}
	}

	.fixed-box {
		position: fixed;
		width: 100%;
		left: 0;
		bottom: 0;
		border-radius: 16rpx 16rpx 0px 0px;
		border: 2rpx solid #e5e5e5;
		background: #ffffff;
	}

	.touch-btn-div {
		height: 0;
		overflow: hidden;
		transition: height 0.2s ease-out;
	}

	.touch-btn-div.show {
		height: 150rpx;
	}

	.fixed-btn-box {
		height: 154rpx;
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 0 20rpx 20rpx 20rpx;

		.sheet_button {
			display: flex;
			flex-direction: column;
			align-items: center;
			margin: 0 70rpx;

			.img {
				width: 38rpx;
				height: 40rpx;
			}

			.sheet_text {
				margin-top: 8rpx;
				font-family: PingFangSC;
				font-weight: 500;
				font-size: 24rpx;
				color: #000000;
			}
		}

		.button_div {
			flex: 1;

			display: flex;
			justify-content: space-between;

			.button {
				flex: 1;
			}
		}
	}

	.scroll-Y {
		max-height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx - 68rpx - 60rpx);
		min-height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx - 68rpx - 60rpx - 380rpx);
	}

	.swiper {
		// 状态栏 var(--status-bar-height)
		// 标题栏 70rpx
		// 进度时间栏 70rpx
		// 进度时间栏上下间距 40rpx = 20rpx + 20rpx
		// 正文上下间距 64rpx
		height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx);
		// background-color: red;
	}

	.content {
		position: relative;
		margin: 32rpx $bg-margin-left;
		border-radius: 16rpx;
		padding: 34rpx 30rpx 34rpx 36rpx;
		background-color: #fff;

		.expose_shadow {
			margin-left: 36rpx;
			position: absolute;
			bottom: -26rpx;
			left: 0%;
			width: calc(100% - 66rpx);
			height: 28rpx;
			background-color: #ffffff;
			border-radius: 0 0 14rpx 14rpx;
			opacity: 0.4;
			z-index: 0;
			// background-color: red;
		}
	}

	.countdown-and-question-number-div {
		margin: 20rpx $bg-margin-left;
		height: 70rpx;
		// background-color: red;
		display: flex;
		flex-direction: column;
		justify-content: space-between;
		z-index: 10;

		.top {
			display: flex;
			align-items: center;
			justify-content: space-between;
			font-family: PingFangSC;
			font-size: 26rpx;
			color: #ffffff;
			text-align: left;
			font-style: normal;
		}

		.question {
			display: flex;
			align-items: center;
			// background-color: red;
			width: 242rpx;

			.grey {
				margin-right: 8rpx;
			}
			color: #ffffff;
			font-weight: 600;
			font-size: 26rpx;
		}

		.grey {
			color: #b6e2ff;
		}

		.bold {
			font-weight: 600;
		}
	}

	.nav-div {
		position: relative;

		.title {
			// padding-top:var(--status-bar-height);
			// padding: 0 30rpx;
			margin: 0 calc($bg-margin-left + 70rpx);
			height: 70rpx;
			font-family: PingFangSC;
			font-weight: 500;
			font-size: 34rpx;
			color: #ffffff;
			text-align: center;
			font-style: normal;
			line-height: 70rpx;
		}

		.back_div {
			position: absolute;
			right: $bg-margin-left;
			top: 0;
			width: 70rpx;
			height: 70rpx;
			display: flex;
			align-items: center;
			justify-content: flex-end;
			.img {
				width: 32rpx;
				height: 32rpx;
			}
			// background-color: red;
		}
	}

	.main_div {
		display: flex;
		flex-direction: column;
		background: linear-gradient(to top, #3480ff, #0066ff);
		/* 确保背景占满整个视口高度 */
		min-height: 100vh;
		margin: 0;
	}
</style>
