<template>
	<view class="matching-page">
		<view class="matching-shell">
			<view class="top-visual">
				<view class="network">
					<view class="ring ring-large"></view>
					<view class="ring ring-middle"></view>
					<view class="ring ring-small"></view>
					<view class="node node-top"></view>
					<view class="node node-left"></view>
					<view class="node node-right"></view>
					<view
						v-for="particle in particles"
						:key="particle.id"
						class="particle"
						:style="particle.style"
					></view>
				</view>
			</view>

			<view class="middle-visual">
				<view class="match-bubble">
					<text>{{ profile.message }}</text>
					<text class="typing-dots"></text>
					<view class="bubble-tail"></view>
				</view>

				<view class="director-card">
					<image class="director-image" src="/static/config-doctor.png" mode="aspectFit"></image>
				</view>

				<view class="intelligence-area">
					<view class="scan-circle">
						<view class="pulse-ring ring-one"></view>
						<view class="pulse-ring ring-two"></view>
						<view class="brain-core">
							<view class="scan-bar"></view>
							<view class="brain-icon"></view>
						</view>
					</view>

					<view
						v-for="(tag, index) in profile.tags"
						:key="tag.label"
						class="float-tag"
						:class="[`tag-${tag.tone}`, `tag-pos-${index}`]"
					>
						<text>{{ tag.label }}</text>
					</view>
				</view>
			</view>

			<view class="bottom-progress">
				<view class="progress-track">
					<view class="progress-fill" :style="{ width: `${progress}%` }"></view>
				</view>
				<text class="progress-subtitle">{{ profile.subtitle }}</text>
				<view class="security-icon"></view>
			</view>
		</view>
	</view>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref } from 'vue'
import { fetchMatchingProfile, type MatchingProfile } from '../../api/matching'

type Particle = {
	id: number
	style: Record<string, string>
}

const profile = reactive<MatchingProfile>({
	message: '王主任正在为您智能匹配病例',
	subtitle: '正在通过大模型计算最适合您的临床案例库...',
	progressTarget: 92,
	tags: []
})

const particles = ref<Particle[]>([])
const progress = ref(0)

let particleId = 0
let particleTimer: ReturnType<typeof setInterval> | null = null
let progressTimer: ReturnType<typeof setInterval> | null = null
const MATCHING_DURATION_MS = 10000
const PROGRESS_INTERVAL_MS = 100

function loadMatchingProfile() {
	fetchMatchingProfile().then(result => {
		Object.assign(profile, result)
		startProgress()
	})
}

function createParticle() {
	const id = particleId++
	const startX = Math.random() * 256
	const startY = Math.random() * 256
	const destX = (Math.random() - 0.5) * 150
	const destY = (Math.random() - 0.5) * 150
	const duration = 2 + Math.random() * 3

	particles.value.push({
		id,
		style: {
			left: `${startX}px`,
			top: `${startY}px`,
			'--particle-x': `${destX}px`,
			'--particle-y': `${destY}px`,
			animationDuration: `${duration}s`
		}
	})

	setTimeout(() => {
		particles.value = particles.value.filter(item => item.id !== id)
	}, duration * 1000)
}

function startParticles() {
	for (let index = 0; index < 12; index += 1) {
		createParticle()
	}
	particleTimer = setInterval(createParticle, 300)
}

function startProgress() {
	if (progressTimer) clearInterval(progressTimer)
	progress.value = 0
	const startedAt = Date.now()
	progressTimer = setInterval(() => {
		const elapsed = Date.now() - startedAt
		const ratio = Math.min(1, elapsed / MATCHING_DURATION_MS)
		progress.value = Math.round(profile.progressTarget * ratio)

		if (ratio >= 1) {
			if (progressTimer) clearInterval(progressTimer)
			progressTimer = null
			uni.redirectTo({
				url: '/pages/cases/cases'
			})
			return
		}
	}, PROGRESS_INTERVAL_MS)
}

onMounted(() => {
	loadMatchingProfile()
	startParticles()
})

onUnmounted(() => {
	if (particleTimer) clearInterval(particleTimer)
	if (progressTimer) clearInterval(progressTimer)
})
</script>

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

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

.matching-shell {
	position: relative;
	min-height: 100vh;
	overflow: hidden;
	background: #ffffff;
	display: flex;
	flex-direction: column;
}

.matching-shell::before {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	top: 0;
	bottom: 0;
	background-size: 40px 40px;
	background-image: radial-gradient(circle, rgba(0, 71, 141, 0.08) 1px, transparent 1px);
	pointer-events: none;
}

.top-visual {
	position: relative;
	z-index: 1;
	height: 33.333vh;
	min-height: 250px;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
}

.network {
	position: relative;
	width: 256px;
	height: 256px;
}

.ring {
	position: absolute;
	left: 50%;
	top: 50%;
	border-radius: 50%;
	transform: translate(-50%, -50%);
	box-sizing: border-box;
}

.ring-large {
	width: 224px;
	height: 224px;
	border: 1px solid rgba(194, 198, 212, 0.28);
	animation: spin-reverse 15s linear infinite;
}

.ring-middle {
	width: 192px;
	height: 192px;
	border: 2px solid rgba(0, 71, 141, 0.2);
	animation: pulse-soft 2s ease-in-out infinite;
}

.ring-small {
	width: 128px;
	height: 128px;
	border: 1px solid rgba(0, 105, 112, 0.3);
	animation: spin 10s linear infinite;
}

.node {
	position: absolute;
	border-radius: 50%;
}

.node-top {
	left: 50%;
	top: 16px;
	width: 16px;
	height: 16px;
	background: #00478d;
	box-shadow: 0 0 15px rgba(0, 71, 141, 0.5);
	transform: translateX(-50%);
}

.node-left {
	left: 40px;
	bottom: 40px;
	width: 12px;
	height: 12px;
	background: #006970;
	box-shadow: 0 0 10px rgba(0, 105, 112, 0.4);
}

.node-right {
	right: 32px;
	top: 80px;
	width: 20px;
	height: 20px;
	background: #005eb8;
	box-shadow: 0 0 12px rgba(0, 94, 184, 0.4);
}

.particle {
	position: absolute;
	width: 4px;
	height: 4px;
	border-radius: 50%;
	background: #00478d;
	box-shadow: 0 0 8px #00478d;
	pointer-events: none;
	animation-name: particle-move;
	animation-timing-function: linear;
	animation-fill-mode: forwards;
}

.middle-visual {
	position: relative;
	z-index: 1;
	flex: 1;
	padding: 40px 20px 0;
	display: flex;
	flex-direction: column;
	align-items: center;
}

.match-bubble {
	position: relative;
	max-width: 280px;
	margin-bottom: 24px;
	padding: 12px 16px;
	border: 1px solid #c2c6d4;
	border-radius: 8px;
	background: #e1e2ea;
	box-shadow: 0 4px 12px rgba(25, 28, 33, 0.06);
	color: #424752;
	font-size: 14px;
	line-height: 20px;
	font-weight: 600;
}

.bubble-tail {
	position: absolute;
	left: 50%;
	bottom: -8px;
	width: 16px;
	height: 16px;
	border-right: 1px solid #c2c6d4;
	border-bottom: 1px solid #c2c6d4;
	background: #e1e2ea;
	transform: translateX(-50%) rotate(45deg);
}

.typing-dots::after {
	content: '';
	animation: typing 1.5s steps(4) infinite;
}

.director-card {
	width: 192px;
	height: 192px;
	margin-bottom: 32px;
	padding: 8px;
	border-radius: 8px;
	background: #ffffff;
	box-shadow: 0 8px 22px rgba(25, 28, 33, 0.12);
	box-sizing: border-box;
	display: flex;
	align-items: center;
	justify-content: center;
	animation: float-soft 6s ease-in-out infinite;
}

.director-image {
	width: 100%;
	height: 100%;
	border-radius: 8px;
}

.intelligence-area {
	position: relative;
	width: 100%;
	display: flex;
	flex-direction: column;
	align-items: center;
}

.scan-circle {
	position: relative;
	width: 96px;
	height: 96px;
	display: flex;
	align-items: center;
	justify-content: center;
}

.pulse-ring {
	position: absolute;
	border-radius: 50%;
	animation: pulse-ring 2s cubic-bezier(0.455, 0.03, 0.515, 0.955) infinite;
}

.ring-one {
	width: 96px;
	height: 96px;
	background: rgba(0, 71, 141, 0.1);
}

.ring-two {
	width: 76px;
	height: 76px;
	background: rgba(0, 71, 141, 0.2);
	animation-delay: 0.5s;
}

.brain-core {
	position: relative;
	z-index: 2;
	width: 64px;
	height: 64px;
	border: 1px solid rgba(0, 71, 141, 0.2);
	border-radius: 50%;
	background: #f9f9ff;
	box-shadow: 0 6px 16px rgba(25, 28, 33, 0.08);
	overflow: hidden;
	display: flex;
	align-items: center;
	justify-content: center;
}

.scan-bar {
	position: absolute;
	left: -100%;
	top: 0;
	width: 200%;
	height: 100%;
	background: linear-gradient(to right, transparent, rgba(0, 71, 141, 0.4), transparent);
	animation: scan-h 2s ease-in-out infinite;
}

.brain-icon {
	position: relative;
	z-index: 1;
	width: 32px;
	height: 32px;
	background: #00478d;
	-webkit-mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M9%202a4%204%200%200%200-4%204v.1A5%205%200%200%200%203%2010a5%205%200%200%200%202%204v.1A4%204%200%200%200%209%2022h1V2H9zm6%200h-1v20h1a4%204%200%200%200%204-4v-.1a5%205%200%200%200%202-4A5%205%200%200%200%2019%206.1V6a4%204%200%200%200-4-4z'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M9%202a4%204%200%200%200-4%204v.1A5%205%200%200%200%203%2010a5%205%200%200%200%202%204v.1A4%204%200%200%200%209%2022h1V2H9zm6%200h-1v20h1a4%204%200%200%200%204-4v-.1a5%205%200%200%200%202-4A5%205%200%200%200%2019%206.1V6a4%204%200%200%200-4-4z'/%3E%3C/svg%3E") center / contain no-repeat;
	animation: pulse-soft 1.8s ease-in-out infinite;
}

.float-tag {
	position: absolute;
	padding: 4px 12px;
	border-radius: 999px;
	border: 1px solid transparent;
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	font-size: 10px;
	line-height: 16px;
	font-weight: 500;
	opacity: 0;
	animation: fade-float 1s forwards ease-out, float 4s ease-in-out infinite;
}

.tag-pos-0 {
	left: 0;
	top: -16px;
	animation-delay: 0.2s, 1.2s;
}

.tag-pos-1 {
	right: -8px;
	top: 48px;
	animation-delay: 0.6s, 1.6s;
}

.tag-pos-2 {
	left: 24px;
	top: 118px;
	animation-delay: 1s, 2s;
}

.tag-pos-3 {
	right: 0;
	top: 92px;
	animation-delay: 1.4s, 2.4s;
}

.tag-secondary {
	border-color: rgba(0, 105, 112, 0.2);
	background: rgba(122, 241, 252, 0.8);
	color: #006e75;
}

.tag-primary {
	border-color: rgba(0, 71, 141, 0.2);
	background: rgba(214, 227, 255, 0.8);
	color: #001b3d;
}

.tag-tertiary {
	border-color: rgba(121, 49, 0, 0.2);
	background: rgba(255, 219, 203, 0.8);
	color: #341100;
}

.tag-neutral {
	border-color: rgba(194, 198, 212, 0.3);
	background: rgba(231, 232, 240, 0.9);
	color: #424752;
}

.bottom-progress {
	position: relative;
	z-index: 1;
	padding: 20px 20px 48px;
	display: flex;
	flex-direction: column;
	align-items: center;
}

.progress-track {
	width: 100%;
	height: 8px;
	margin-bottom: 16px;
	border-radius: 999px;
	background: #f3f4f6;
	overflow: hidden;
}

.progress-fill {
	height: 100%;
	border-radius: inherit;
	background: #00478d;
	transition: width 1s ease-out;
}

.progress-subtitle {
	max-width: 280px;
	text-align: center;
	color: #727783;
	font-size: 12px;
	line-height: 16px;
	font-weight: 500;
}

.security-icon {
	width: 16px;
	height: 16px;
	margin-top: 32px;
	background: #00478d;
	opacity: 0.6;
	-webkit-mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M12%201a5%205%200%200%200-5%205v3H6a2%202%200%200%200-2%202v9a2%202%200%200%200%202%202h12a2%202%200%200%200%202-2v-9a2%202%200%200%200-2-2h-1V6a5%205%200%200%200-5-5zm-3%208V6a3%203%200%200%201%206%200v3H9z'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M12%201a5%205%200%200%200-5%205v3H6a2%202%200%200%200-2%202v9a2%202%200%200%200%202%202h12a2%202%200%200%200%202-2v-9a2%202%200%200%200-2-2h-1V6a5%205%200%200%200-5-5zm-3%208V6a3%203%200%200%201%206%200v3H9z'/%3E%3C/svg%3E") center / contain no-repeat;
}

@keyframes typing {
	0%,
	25% {
		content: '';
	}
	50% {
		content: '.';
	}
	75% {
		content: '..';
	}
	100% {
		content: '...';
	}
}

@keyframes particle-move {
	0% {
		transform: translate(0, 0);
		opacity: 0;
	}
	20%,
	80% {
		opacity: 1;
	}
	100% {
		transform: translate(var(--particle-x), var(--particle-y));
		opacity: 0;
	}
}

@keyframes pulse-ring {
	0% {
		transform: scale(0.33);
		opacity: 0.8;
	}
	80%,
	100% {
		transform: scale(1.5);
		opacity: 0;
	}
}

@keyframes float {
	0%,
	100% {
		transform: translateY(0);
	}
	50% {
		transform: translateY(-10px);
	}
}

@keyframes float-soft {
	0%,
	100% {
		transform: translateY(0) scale(1);
	}
	50% {
		transform: translateY(-5px) scale(1.02);
	}
}

@keyframes fade-float {
	from {
		opacity: 0;
		transform: translateY(10px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

@keyframes scan-h {
	0% {
		left: -100%;
	}
	100% {
		left: 100%;
	}
}

@keyframes spin {
	from {
		transform: translate(-50%, -50%) rotate(0deg);
	}
	to {
		transform: translate(-50%, -50%) rotate(360deg);
	}
}

@keyframes spin-reverse {
	from {
		transform: translate(-50%, -50%) rotate(360deg);
	}
	to {
		transform: translate(-50%, -50%) rotate(0deg);
	}
}

@keyframes pulse-soft {
	0%,
	100% {
		opacity: 0.75;
	}
	50% {
		opacity: 1;
	}
}
</style>
