<template>
	<view class="records-page">
		<view class="records-shell">
			<header class="top-bar">
				<button class="icon-button" aria-label="返回" @click="goBack">
					<view class="back-icon"></view>
				</button>
				<text class="page-title">学习记录</text>
			</header>

			<scroll-view class="records-scroll" scroll-y @scrolltolower="loadMoreRecords">
				<main class="records-main">
					<section class="stats-grid">
						<view
							v-for="stat in stats"
							:key="stat.label"
							class="stat-card"
						>
							<text class="stat-label">{{ stat.label }}</text>
							<text class="stat-value" :class="{ secondary: stat.secondary }">{{ stat.value }}</text>
						</view>
					</section>

					<section class="search-section">
						<view class="search-field">
							<view class="search-icon"></view>
							<input
								v-model="keyword"
								class="search-input"
								placeholder="搜索病例标题或科室..."
								placeholder-class="search-placeholder"
								type="text"
							/>
						</view>
					</section>

					<section class="history-section">
						<text class="section-title">最近训练</text>
						<view class="record-list">
							<view
								v-for="record in recordItems"
								:key="record.id"
								class="record-card"
								:class="{ dimmed: record.dimmed }"
								@click="openReport(record.id)"
							>
								<view class="case-icon-wrap" :class="record.tone">
									<text class="case-icon-text">{{ record.abbr }}</text>
								</view>

								<view class="case-copy">
									<text class="case-title">{{ record.title }}</text>
									<view class="case-meta">
										<text>{{ record.department }}</text>
										<text class="dot">•</text>
										<text>{{ record.date }}</text>
									</view>
								</view>

								<view class="score-block">
									<view class="score-row">
										<text class="score-value">{{ record.score }}</text>
										<text class="score-unit">分</text>
									</view>
									<button class="report-button" @click.stop="openReport(record.id)">
										<text>查看报告</text>
										<view class="small-chevron"></view>
									</button>
								</view>
							</view>

							<view v-if="recordItems.length === 0" class="empty-state">
								<text>{{ emptyText }}</text>
							</view>
						</view>
					</section>

					<view class="bottom-hint">
						<text>{{ bottomHint }}</text>
					</view>
				</main>
			</scroll-view>

			<view class="toast" :class="{ visible: toastVisible }">{{ toastMessage }}</view>
		</view>
	</view>
</template>

<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import {
	fetchUserTrainingRecords,
	type TrainingRecord,
	type TrainingRecordSummary
} from '../../api/profile'

const keyword = ref('')
const toastMessage = ref('')
const toastVisible = ref(false)
const records = ref<TrainingRecord[]>([])
const summary = ref<TrainingRecordSummary>({
	total_cases: 0,
	total_hours: 0,
	avg_accuracy: 0
})
const currentPage = ref(1)
const totalCount = ref(0)
const hasMore = ref(false)
const loadingRecords = ref(false)
const recordsLoaded = ref(false)
const recordsFailed = ref(false)

let toastTimer: ReturnType<typeof setTimeout> | null = null
let searchTimer: ReturnType<typeof setTimeout> | null = null
let requestSeq = 0

const stats = computed(() => [
	{ label: '总病例', value: formatNumber(summary.value.total_cases) },
	{ label: '总时长', value: `${formatNumber(summary.value.total_hours)}h` },
	{ label: '平均正确率', value: `${formatNumber(summary.value.avg_accuracy)}%`, secondary: true }
])

const recordItems = computed(() => {
	return records.value.map((record, index) => ({
		id: record.record_id,
		title: record.case_title || '未命名病例',
		department: record.department || '未标注科室',
		date: formatDate(record.trained_at),
		score: formatNumber(record.score),
		abbr: readRecordAbbr(record),
		tone: readTone(index),
		dimmed: index > 2
	}))
})

const emptyText = computed(() => {
	if (loadingRecords.value && !recordsLoaded.value) return '训练记录加载中...'
	if (recordsFailed.value) return '训练记录加载失败，请稍后重试'
	return keyword.value.trim() ? '没有找到匹配的训练记录' : '暂无训练记录'
})

const bottomHint = computed(() => {
	if (loadingRecords.value && recordsLoaded.value) return '加载更多...'
	if (hasMore.value) return '上拉加载更多'
	return records.value.length > 0 ? '已经到底啦' : ''
})

function goBack() {
	if (typeof getCurrentPages === 'function' && getCurrentPages().length > 1) {
		uni.navigateBack()
		return
	}

	uni.reLaunch({
		url: '/pages/profile/profile'
	})
}

function openReport(evaluationId: number) {
	if (!evaluationId) {
		showToast('未找到报告 ID')
		return
	}
	uni.setStorageSync('clinical-thinking-current-evaluation-id', evaluationId)
	uni.navigateTo({
		url: `/pages/assessment/assessment?evaluation_id=${encodeURIComponent(String(evaluationId))}`
	})
}

async function loadRecords(page = 1, append = false) {
	const seq = ++requestSeq
	loadingRecords.value = true
	if (!append) {
		recordsFailed.value = false
		hasMore.value = false
	}

	try {
		const result = await fetchUserTrainingRecords({
			search: keyword.value.trim(),
			page
		})
		if (seq !== requestSeq) return

		records.value = append ? records.value.concat(result.results || []) : result.results || []
		summary.value = result.summary || summary.value
		totalCount.value = result.count || records.value.length
		currentPage.value = page
		hasMore.value = Boolean(result.next) || records.value.length < totalCount.value
		recordsLoaded.value = true
		recordsFailed.value = false
	} catch (error) {
		if (seq !== requestSeq) return
		recordsFailed.value = true
		if (!append) records.value = []
		showToast(error instanceof Error ? error.message : '训练记录加载失败')
	} finally {
		if (seq === requestSeq) loadingRecords.value = false
	}
}

function loadMoreRecords() {
	if (!hasMore.value || loadingRecords.value) return
	void loadRecords(currentPage.value + 1, true)
}

function showToast(message: string) {
	if (toastTimer) clearTimeout(toastTimer)
	toastMessage.value = message
	toastVisible.value = true
	toastTimer = setTimeout(() => {
		toastVisible.value = false
	}, 2200)
}

function formatDate(value: string) {
	if (!value) return '--'
	const date = new Date(value)
	if (Number.isNaN(date.getTime())) return value
	const month = `${date.getMonth() + 1}`.padStart(2, '0')
	const day = `${date.getDate()}`.padStart(2, '0')
	return `${date.getFullYear()}-${month}-${day}`
}

function formatNumber(value: number) {
	if (!Number.isFinite(value)) return '0'
	return Number.isInteger(value) ? String(value) : value.toFixed(1)
}

function readRecordAbbr(record: TrainingRecord) {
	const source = record.department || record.case_title || '训'
	return source.trim().slice(0, 1) || '训'
}

function readTone(index: number) {
	const tones = ['primary', 'secondary', 'tertiary'] as const
	return tones[index % tones.length]
}

watch(keyword, () => {
	if (searchTimer) clearTimeout(searchTimer)
	searchTimer = setTimeout(() => {
		void loadRecords(1)
	}, 350)
})

onMounted(() => {
	void loadRecords(1)
})

onUnmounted(() => {
	if (toastTimer) clearTimeout(toastTimer)
	if (searchTimer) clearTimeout(searchTimer)
})
</script>

<style scoped>
page {
	min-height: 100%;
	background: #f9f9ff;
}

.records-page {
	min-height: 100vh;
	background: #f9f9ff;
	color: #191c21;
	font-family: Inter, -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
	-webkit-tap-highlight-color: transparent;
}

.records-shell {
	position: relative;
	width: 390px;
	max-width: 100vw;
	min-height: 884px;
	margin: 0 auto;
	background: #f9f9ff;
	overflow: hidden;
	display: flex;
	flex-direction: column;
}

.records-page view,
.records-page text,
.records-page button,
.records-page input,
.records-page scroll-view {
	box-sizing: border-box;
}

.records-page ::-webkit-scrollbar {
	width: 0;
	height: 0;
	background: transparent;
}

.top-bar {
	position: sticky;
	top: 0;
	z-index: 50;
	height: 64px;
	padding: 0 20px;
	border-bottom: 1px solid #c2c6d4;
	background: #f9f9ff;
	box-shadow: 0 1px 4px rgba(25, 28, 33, 0.04);
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
}

.page-title {
	position: absolute;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	color: #00478d;
	font-size: 20px;
	line-height: 28px;
	font-weight: 600;
	letter-spacing: 0;
}

.icon-button,
.report-button {
	padding: 0;
	border: 0;
	background: transparent;
}

.icon-button::after,
.report-button::after {
	border: 0;
}

.icon-button {
	position: absolute;
	left: 20px;
	top: 12px;
	width: 40px;
	height: 40px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
}

.icon-button:active,
.record-card:active {
	transform: scale(0.98);
}

.back-icon,
.search-icon,
.small-chevron {
	background: #00478d;
	-webkit-mask-position: center;
	-webkit-mask-repeat: no-repeat;
	-webkit-mask-size: contain;
	mask-position: center;
	mask-repeat: no-repeat;
	mask-size: contain;
}

.back-icon {
	width: 24px;
	height: 24px;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M20%2011H7.83l5.59-5.59L12%204l-8%208%208%208%201.42-1.41L7.83%2013H20v-2z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M20%2011H7.83l5.59-5.59L12%204l-8%208%208%208%201.42-1.41L7.83%2013H20v-2z'/%3E%3C/svg%3E");
}

.records-scroll {
	flex: 1 1 auto;
	min-height: 0;
}

.records-main {
	padding: 20px 20px 32px;
	display: flex;
	flex-direction: column;
	gap: 24px;
}

.stats-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 12px;
}

.stat-card {
	min-height: 96px;
	padding: 16px 8px;
	border: 1px solid #c2c6d4;
	border-radius: 8px;
	background: #ffffff;
	box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	text-align: center;
}

.stat-label {
	margin-bottom: 8px;
	color: #424752;
	font-size: 12px;
	line-height: 16px;
	font-weight: 500;
}

.stat-value {
	color: #00478d;
	font-size: 20px;
	line-height: 28px;
	font-weight: 600;
}

.stat-value.secondary {
	color: #006970;
}

.search-field {
	position: relative;
	min-height: 48px;
	display: flex;
	align-items: center;
}

.search-icon {
	position: absolute;
	left: 16px;
	z-index: 1;
	width: 22px;
	height: 22px;
	background: #727783;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M9.5%203A6.5%206.5%200%200%200%209.5%2016a6.47%206.47%200%200%200%204.03-1.39l4.43%204.43%201.41-1.41-4.43-4.43A6.47%206.47%200%200%200%2016%209.5%206.5%206.5%200%200%200%209.5%203zm0%202A4.5%204.5%200%201%201%209.5%2014%204.5%204.5%200%200%201%209.5%205z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M9.5%203A6.5%206.5%200%200%200%209.5%2016a6.47%206.47%200%200%200%204.03-1.39l4.43%204.43%201.41-1.41-4.43-4.43A6.47%206.47%200%200%200%2016%209.5%206.5%206.5%200%200%200%209.5%203zm0%202A4.5%204.5%200%201%201%209.5%2014%204.5%204.5%200%200%201%209.5%205z'/%3E%3C/svg%3E");
}

.search-input {
	width: 100%;
	height: 48px;
	padding: 0 16px 0 48px;
	border: 1px solid #c2c6d4;
	border-radius: 24px;
	background: #f2f3fb;
	color: #191c21;
	font-size: 16px;
	line-height: 24px;
}

.search-placeholder {
	color: #727783;
}

.history-section {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.section-title {
	padding: 0 4px;
	color: #424752;
	font-size: 14px;
	line-height: 20px;
	font-weight: 600;
	letter-spacing: 0;
}

.record-list {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.record-card {
	min-height: 80px;
	padding: 16px;
	border: 1px solid #c2c6d4;
	border-radius: 8px;
	background: #ffffff;
	box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
	display: flex;
	align-items: center;
	gap: 16px;
	transition: transform 0.15s ease, opacity 0.15s ease;
}

.record-card.dimmed {
	opacity: 0.88;
}

.case-icon-wrap {
	width: 48px;
	height: 48px;
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
}

.case-icon-wrap.primary {
	background: #005eb8;
	color: #c8daff;
}

.case-icon-wrap.secondary {
	background: #7af1fc;
	color: #006e75;
}

.case-icon-wrap.tertiary {
	background: #ffdbcb;
	color: #793100;
}

.case-icon-text {
	font-size: 18px;
	line-height: 24px;
	font-weight: 700;
}

.case-copy {
	min-width: 0;
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.case-title {
	max-width: 132px;
	color: #191c21;
	font-size: 14px;
	line-height: 20px;
	font-weight: 600;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.case-meta {
	display: flex;
	align-items: center;
	gap: 8px;
	min-width: 0;
	color: #424752;
	font-size: 12px;
	line-height: 16px;
	font-weight: 500;
}

.dot {
	font-size: 10px;
	opacity: 0.4;
}

.score-block {
	flex: 0 0 auto;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 4px;
}

.score-row {
	display: flex;
	align-items: baseline;
	gap: 4px;
}

.score-value {
	color: #00478d;
	font-size: 20px;
	line-height: 28px;
	font-weight: 600;
}

.score-unit {
	color: #424752;
	font-size: 12px;
	line-height: 16px;
	font-weight: 500;
}

.report-button {
	color: #00478d;
	display: flex;
	align-items: center;
	font-size: 12px;
	line-height: 16px;
	font-weight: 500;
}

.small-chevron {
	width: 16px;
	height: 16px;
	margin-left: 4px;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M10%206L8.59%207.41%2013.17%2012l-4.58%204.59L10%2018l6-6-6-6z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M10%206L8.59%207.41%2013.17%2012l-4.58%204.59L10%2018l6-6-6-6z'/%3E%3C/svg%3E");
}

.empty-state {
	min-height: 96px;
	border: 1px dashed #c2c6d4;
	border-radius: 8px;
	background: #f2f3fb;
	color: #727783;
	font-size: 14px;
	line-height: 20px;
	display: flex;
	align-items: center;
	justify-content: center;
}

.bottom-hint {
	padding: 16px 0 4px;
	color: #727783;
	font-size: 12px;
	line-height: 16px;
	font-weight: 500;
	text-align: center;
}

.toast {
	position: absolute;
	left: 50%;
	bottom: 24px;
	z-index: 80;
	max-width: 300px;
	padding: 8px 12px;
	border-radius: 12px;
	background: rgba(46, 48, 55, 0.9);
	color: #eff0f8;
	font-size: 12px;
	line-height: 16px;
	opacity: 0;
	pointer-events: none;
	transform: translate(-50%, 8px);
	transition: opacity 0.2s ease, transform 0.2s ease;
}

.toast.visible {
	opacity: 1;
	transform: translate(-50%, 0);
}
</style>
