<template>
	<view class="records-page">
		<scroll-view class="records-scroll" scroll-y :scroll-with-animation="true"
			:style="{ paddingBottom: scrollPaddingBottom + 'px' }">
			<view class="hero-panel">
				<view class="hero-main">
					<view class="hero-copy">
						<text class="hero-kicker">健康档案</text>
						<text class="hero-title">{{ heroTitle }}</text>
						<text class="hero-desc">{{ heroDesc }}</text>
					</view>
					<view class="hero-action" @click="handleAddRecord">
						<TnIcon name="add-lack" :size="34" color="#FFFFFF" />
					</view>
				</view>

				<view class="summary-row">
					<view class="summary-item">
						<text class="summary-value">{{ records.length }}</text>
						<text class="summary-label">当前记录</text>
					</view>
					<view class="summary-divider" />
					<view class="summary-item">
						<text class="summary-value">{{ monthCount }}</text>
						<text class="summary-label">覆盖月份</text>
					</view>
					<view class="summary-divider" />
					<view class="summary-item">
						<text class="summary-value">{{ totalCostText }}</text>
						<text class="summary-label">累计花费</text>
					</view>
				</view>
			</view>

			<view class="category-strip">
				<TnTabs v-model="currentFilterIndex" height="78rpx" bar-width="36rpx" bar-color="#F97316"
					active-color="#F97316" color="#64748B" bg-color="#FFFFFF" font-size="25rpx" active-font-size="27rpx"
					:bottom-shadow="false" @change="onFilterChange">
					<TnTabsItem v-for="tab in filterTabs" :key="tab" :title="tab" />
				</TnTabs>
			</view>

			<view class="records-stage">
				<view v-if="loading" class="loading-state">
					<TnLoading :show="true" mode="circle" color="#F97316" :size="54" />
					<text class="loading-text">正在整理健康记录...</text>
					<view class="loading-card" v-for="i in 3" :key="i">
						<view class="skeleton-icon" />
						<view class="skeleton-content">
							<view class="skeleton-line skeleton-line-title" />
							<view class="skeleton-line skeleton-line-meta" />
						</view>
					</view>
				</view>

				<view v-else-if="groupedRecords.length === 0" class="empty-state">
					<TnEmpty mode="data" color="#F97316" size="xl" />
					<text class="empty-title">{{ emptyTitle }}</text>
					<text class="empty-desc">{{ emptyDesc }}</text>
					<TnButton text-color="#FFFFFF" shape="round" :bold="true" :shadow="true"
						:custom-style="primaryButtonStyle" width="320" height="88" @click="handleAddRecord">
						<view class="button-inner">
							<TnIcon name="add-lack" :size="28" />
							<text>添加记录</text>
						</view>
					</TnButton>
				</view>

				<view v-else class="records-content">
					<view class="section-head">
						<view>
							<text class="section-title">记录时间线</text>
							<text class="section-subtitle">{{ activeFilterLabel }} · {{ records.length }} 条</text>
						</view>
						<TnTag bg-color="#FFF7ED" text-color="#F97316" shape="round" size="sm">
							{{ latestDateText }}
						</TnTag>
					</view>

					<view class="month-group" v-for="(group, groupIndex) in groupedRecords" :key="group.monthKey">
						<view class="month-head">
							<view class="month-dot" :class="{ 'month-dot-active': groupIndex === 0 }" />
							<text class="month-label">{{ group.monthLabel }}</text>
							<TnTag bg-color="#F1F5F9" text-color="#475569" shape="round" size="sm">
								{{ group.records.length }} 条
							</TnTag>
						</view>

						<view v-for="record in group.records" :key="record._id" class="record-card"
							hover-class="record-card-active" @click="handleRecordTap(record)">
							<view class="record-accent" :style="{ background: getTypeStyle(record.type).accent }" />
							<view class="record-icon" :style="{ backgroundColor: getTypeStyle(record.type).bg }">
								<TnIcon :name="getTypeStyle(record.type).icon" :size="38"
									:color="getTypeStyle(record.type).color" />
							</view>

							<view class="record-main">
								<view class="record-title-row">
									<text class="record-title">{{ getRecordTitle(record) }}</text>
									<TnTag :bg-color="getTypeStyle(record.type).soft"
										:text-color="getTypeStyle(record.type).color" shape="round" size="sm">
										{{ getTypeLabel(record.type) }}
									</TnTag>
								</view>
								<text class="record-desc">{{ getRecordDesc(record) }}</text>
								<view class="record-meta">
									<view class="meta-pill">
										<TnIcon name="calendar" :size="22" color="#64748B" />
										<text>{{ formatRecordDate(record.date) }}</text>
									</view>
									<view v-if="record.petName" class="meta-pill">
										<TnIcon name="floral" :size="22" color="#64748B" />
										<text>{{ record.petName }}</text>
									</view>
									<view v-if="record.hospital" class="meta-pill meta-pill-wide">
										<TnIcon name="location" :size="22" color="#64748B" />
										<text>{{ record.hospital }}</text>
									</view>
									<view v-if="record.cost" class="meta-pill cost-pill">
										<text>¥{{ formatCost(record.cost) }}</text>
									</view>
								</view>
							</view>

							<TnIcon name="right" :size="28" color="#CBD5E1" />
						</view>
					</view>

					<view class="bottom-tip">
						<TnIcon name="success-circle-fill" :size="24" color="#14B8A6" />
						<text>已展示当前分类的全部记录</text>
					</view>
				</view>
			</view>
		</scroll-view>

		<view v-if="!loading && groupedRecords.length > 0" class="fab-wrap" :style="{ bottom: fabBottom + 'px' }">
			<TnButton text-color="#FFFFFF" shape="round" :bold="true" :shadow="true"
				:custom-style="primaryButtonStyle" width="280" height="88" :font-size="28" @click="handleAddRecord">
				<view class="button-inner">
					<TnIcon name="add-lack" :size="28" />
					<text>添加记录</text>
				</view>
			</TnButton>
		</view>
	</view>
</template>

<script setup lang="ts">
	import { computed, onMounted, ref } from 'vue'
	import { onShow } from '@dcloudio/uni-app'
	import TnButton from '@/uni_modules/tuniaoui-vue3/components/button/src/button.vue'
	import TnEmpty from '@/uni_modules/tuniaoui-vue3/components/empty/src/empty.vue'
	import TnIcon from '@/uni_modules/tuniaoui-vue3/components/icon/src/icon.vue'
	import TnLoading from '@/uni_modules/tuniaoui-vue3/components/loading/src/loading.vue'
	import TnTabs from '@/uni_modules/tuniaoui-vue3/components/tabs/src/tabs.vue'
	import TnTabsItem from '@/uni_modules/tuniaoui-vue3/components/tabs/src/tabs-item.vue'
	import TnTag from '@/uni_modules/tuniaoui-vue3/components/tag/src/tag.vue'

	interface HealthRecord {
		_id : string
		pet_id : string
		user_id : string
		type : string
		title : string
		date : number | string
		nextDate ?: number | string
		hospital ?: string
		doctor ?: string
		description ?: string
		vaccineName ?: string
		batchNumber ?: string
		dewormType ?: string
		brand ?: string
		diagnosis ?: string
		medications ?: Array<{ name : string; dosage : string; frequency : string }>
		images ?: string[]
		cost ?: number
		tags ?: string[]
		createdAt : number
		updatedAt : number
		petName ?: string
	}

	interface RecordGroup {
		monthKey : string
		monthLabel : string
		records : HealthRecord[]
	}

	interface TypeStyle {
		icon : string
		color : string
		bg : string
		soft : string
		accent : string
	}

	const loading = ref(true)
	const hasLoaded = ref(false)
	const records = ref<HealthRecord[]>([])
	const groupedRecords = ref<RecordGroup[]>([])
	const scrollPaddingBottom = ref(190)
	const fabBottom = ref(78)
	const currentFilterIndex = ref(0)
	let recordsRequestId = 0
	const primaryButtonStyle = {
		background: 'linear-gradient(135deg, #F97316, #FB923C)',
	}

	const filterTabs = ['全部', '疫苗', '驱虫', '病历', '体检', '其他']
	const filterValues = ['all', 'vaccine', 'deworm', 'medical', 'checkup', 'other']

	const typeStyleMap : Record<string, TypeStyle> = {
		vaccine: {
			icon: 'safe-fill',
			color: '#2563EB',
			bg: '#EFF6FF',
			soft: '#DBEAFE',
			accent: 'linear-gradient(180deg, #2563EB, #60A5FA)',
		},
		deworm: {
			icon: 'notice-fill',
			color: '#7C3AED',
			bg: '#F5F3FF',
			soft: '#EDE9FE',
			accent: 'linear-gradient(180deg, #7C3AED, #A78BFA)',
		},
		medical: {
			icon: 'write-feather',
			color: '#F97316',
			bg: '#FFF7ED',
			soft: '#FFEDD5',
			accent: 'linear-gradient(180deg, #F97316, #FDBA74)',
		},
		checkup: {
			icon: 'data-fill',
			color: '#0D9488',
			bg: '#F0FDFA',
			soft: '#CCFBF1',
			accent: 'linear-gradient(180deg, #0D9488, #5EEAD4)',
		},
		other: {
			icon: 'inventory-fill',
			color: '#475569',
			bg: '#F8FAFC',
			soft: '#E2E8F0',
			accent: 'linear-gradient(180deg, #64748B, #CBD5E1)',
		},
	}

	const typeLabelMap : Record<string, string> = {
		vaccine: '疫苗',
		deworm: '驱虫',
		medical: '病历',
		checkup: '体检',
		other: '其他',
	}

	const activeFilterLabel = computed(() => filterTabs[currentFilterIndex.value] || '全部')

	const monthCount = computed(() => groupedRecords.value.length)

	const latestDateText = computed(() => {
		const latest = records.value[0]
		return latest ? formatRecordDate(latest.date) : '暂无'
	})

	const totalCostText = computed(() => {
		const total = records.value.reduce((sum, item) => sum + (Number(item.cost) || 0), 0)
		if (total >= 10000) return `${(total / 10000).toFixed(1)}w`
		if (total > 0) return `¥${Math.round(total)}`
		return '¥0'
	})

	const heroTitle = computed(() => {
		if (loading.value) return '正在同步记录'
		if (!records.value.length) return currentFilterIndex.value === 0 ? '从第一条记录开始' : `${activeFilterLabel.value}暂无记录`
		return currentFilterIndex.value === 0 ? '毛球健康一眼掌握' : `${activeFilterLabel.value}记录`
	})

	const heroDesc = computed(() => {
		if (loading.value) return '正在读取疫苗、驱虫、病历和体检信息'
		if (!records.value.length) return '添加记录后，这里会自动生成按月整理的健康时间线'
		return `最近更新 ${latestDateText.value}，共整理 ${records.value.length} 条健康事件`
	})

	const emptyTitle = computed(() => (currentFilterIndex.value === 0 ? '还没有健康记录' : `暂无${activeFilterLabel.value}记录`))

	const emptyDesc = computed(() => (
		currentFilterIndex.value === 0
			? '记录疫苗、驱虫、体检和就诊情况，让每一次照护都有迹可循。'
			: '切换其他分类看看，或为毛球补上一条新的健康记录。'
	))

	onMounted(() => {
		calcLayout()
		loadRecords()
	})

	onShow(() => {
		loadRecords(!hasLoaded.value)
	})

	function calcLayout() {
		const systemInfo = uni.getSystemInfoSync()
		const bottom = systemInfo.safeAreaInsets?.bottom || 0
		fabBottom.value = bottom + 58
		scrollPaddingBottom.value = bottom + 190
	}

	async function loadRecords(showLoading = !hasLoaded.value) {
		const requestId = ++recordsRequestId
		if (showLoading) loading.value = true
		try {
			const uid = uni.getStorageSync('uid')
			if (!uid) {
				if (requestId !== recordsRequestId) return
				records.value = []
				groupedRecords.value = []
				return
			}

			const res = await uniCloud.callFunction({
				name: 'recordManager',
				data: {
					action: 'list',
					uid,
					type: currentFilterIndex.value === 0 ? undefined : filterValues[currentFilterIndex.value],
				},
			})

			if (requestId !== recordsRequestId) return

			if (res.result?.code === 0 && res.result.data) {
				const list = (res.result.data.list || []) as HealthRecord[]
				records.value = sortRecords(list)
				groupedRecords.value = groupByMonth(records.value)
			} else {
				records.value = []
				groupedRecords.value = []
			}
		} catch (e) {
			if (requestId !== recordsRequestId) return
			console.warn('加载健康记录失败', e)
			records.value = []
			groupedRecords.value = []
		} finally {
			if (requestId === recordsRequestId) {
				loading.value = false
				hasLoaded.value = true
			}
		}
	}

	function onFilterChange(index : number | string) {
		currentFilterIndex.value = Number(index)
		loadRecords(false)
	}

	function sortRecords(list : HealthRecord[]) {
		return [...list].sort((a, b) => getTimeValue(b.date) - getTimeValue(a.date))
	}

	function groupByMonth(list : HealthRecord[]) {
		const map = new Map<string, HealthRecord[]>()
		list.forEach((record) => {
			const date = getDate(record.date)
			if (!date) return
			const month = date.getMonth() + 1
			const key = `${date.getFullYear()}-${String(month).padStart(2, '0')}`
			if (!map.has(key)) map.set(key, [])
			map.get(key)!.push(record)
		})

		return Array.from(map.entries()).map(([monthKey, groupRecords]) => ({
			monthKey,
			monthLabel: getMonthLabel(groupRecords[0].date),
			records: groupRecords,
		}))
	}

	function getTypeStyle(type : string) {
		return typeStyleMap[type] || typeStyleMap.other
	}

	function getTypeLabel(type : string) {
		return typeLabelMap[type] || '其他'
	}

	function getRecordTitle(record : HealthRecord) {
		if (record.title) return record.title
		if (record.vaccineName) return record.vaccineName
		if (record.diagnosis) return record.diagnosis
		return getTypeLabel(record.type)
	}

	function getRecordDesc(record : HealthRecord) {
		if (record.description) return record.description
		if (record.hospital && record.doctor) return `${record.hospital} · ${record.doctor}`
		if (record.hospital) return record.hospital
		if (record.brand) return `品牌：${record.brand}`
		if (record.batchNumber) return `批号：${record.batchNumber}`
		return '点击查看记录详情'
	}

	function formatRecordDate(value : number | string | undefined) {
		const date = getDate(value)
		if (!date) return ''
		const month = String(date.getMonth() + 1).padStart(2, '0')
		const day = String(date.getDate()).padStart(2, '0')
		return `${month}月${day}日`
	}

	function getMonthLabel(value : number | string | undefined) {
		const date = getDate(value)
		if (!date) return '未知月份'
		const year = date.getFullYear()
		const month = date.getMonth() + 1
		const now = new Date()
		if (year === now.getFullYear() && month === now.getMonth() + 1) return `${month}月`
		return `${year}年${month}月`
	}

	function getDate(value : number | string | undefined) {
		if (!value) return null
		const date = new Date(value)
		return Number.isNaN(date.getTime()) ? null : date
	}

	function getTimeValue(value : number | string | undefined) {
		return getDate(value)?.getTime() || 0
	}

	function formatCost(value : number) {
		const num = Number(value) || 0
		return Number.isInteger(num) ? String(num) : num.toFixed(2)
	}

	function handleAddRecord() {
		uni.navigateTo({ url: '/pages/record/type-select' })
	}

	function handleRecordTap(record : HealthRecord) {
		uni.navigateTo({ url: `/pages/record/detail?id=${record._id}` })
	}
</script>

<style lang="scss" scoped>
	$primary: #F97316;
	$primary-light: #FB923C;
	$primary-bg: #FFF7ED;
	$text-dark: #0F172A;
	$text-body: #475569;
	$text-muted: #64748B;
	$border: #E2E8F0;
	$card-bg: #FFFFFF;
	$shadow: 0 8rpx 24rpx rgba(15, 23, 42, 0.06);
	$shadow-active: 0 12rpx 34rpx rgba(15, 23, 42, 0.1);

	.records-page {
		position: relative;
		height: 100%;
		background: #F8FAFC;
	}

	.records-scroll {
		height: 100vh;
		box-sizing: border-box;
	}

	.hero-panel {
		margin: 24rpx 24rpx 0;
		padding: 30rpx 28rpx 26rpx;
		border-radius: 28rpx;
		background: linear-gradient(135deg, #F97316 0%, #FB923C 54%, #2DD4BF 145%);
		box-shadow: 0 14rpx 36rpx rgba(249, 115, 22, 0.22);
		overflow: hidden;
	}

	.hero-main {
		display: flex;
		align-items: flex-start;
		justify-content: space-between;
		gap: 24rpx;
	}

	.hero-copy {
		flex: 1;
		min-width: 0;
		display: flex;
		flex-direction: column;
	}

	.hero-kicker {
		font-size: 23rpx;
		font-weight: 700;
		color: rgba(255, 255, 255, 0.78);
	}

	.hero-title {
		margin-top: 8rpx;
		font-size: 40rpx;
		font-weight: 900;
		color: #FFFFFF;
		line-height: 1.25;
	}

	.hero-desc {
		margin-top: 12rpx;
		font-size: 25rpx;
		color: rgba(255, 255, 255, 0.82);
		line-height: 1.5;
	}

	.hero-action {
		width: 76rpx;
		height: 76rpx;
		border-radius: 24rpx;
		background: rgba(255, 255, 255, 0.2);
		border: 1rpx solid rgba(255, 255, 255, 0.28);
		display: flex;
		align-items: center;
		justify-content: center;
		flex-shrink: 0;
		transition: opacity 0.2s ease;

		&:active {
			opacity: 0.78;
		}
	}

	.summary-row {
		margin-top: 28rpx;
		display: flex;
		align-items: center;
		padding: 18rpx 0;
		border-radius: 18rpx;
		background: rgba(255, 255, 255, 0.16);
	}

	.summary-item {
		flex: 1;
		display: flex;
		flex-direction: column;
		align-items: center;
		gap: 4rpx;
		min-width: 0;
	}

	.summary-value {
		font-size: 32rpx;
		font-weight: 900;
		color: #FFFFFF;
		max-width: 180rpx;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.summary-label {
		font-size: 21rpx;
		color: rgba(255, 255, 255, 0.78);
	}

	.summary-divider {
		width: 1rpx;
		height: 42rpx;
		background: rgba(255, 255, 255, 0.28);
	}

	.category-strip {
		display: grid;
		place-items: center;
		height: 80rpx;
		position: sticky;
		top: 0;
		z-index: 20;
		margin: 20rpx 24rpx 0;
		padding: 4rpx;
		border-radius: 22rpx;
		background: $card-bg;
		box-shadow: $shadow;
		overflow: hidden;
	}

	.category-strip :deep(.tn-tabs) {
		width: 100%;
		align-self: center;
	}

	.category-strip :deep(.tn-tabs__container) {
		align-items: center;
	}

	.category-strip :deep(.tn-tabs__bar-container) {
		bottom: 4rpx;
	}

	.records-stage {
		min-height: 720rpx;
	}

	.loading-state {
		padding: 48rpx 24rpx 0;
		display: flex;
		flex-direction: column;
		align-items: center;
		gap: 18rpx;
	}

	.loading-text {
		font-size: 26rpx;
		color: $text-muted;
		margin-bottom: 10rpx;
	}

	.loading-card {
		width: 100%;
		box-sizing: border-box;
		display: flex;
		align-items: center;
		gap: 20rpx;
		padding: 24rpx;
		border-radius: 24rpx;
		background: $card-bg;
		box-shadow: $shadow;
	}

	.skeleton-icon {
		width: 78rpx;
		height: 78rpx;
		border-radius: 22rpx;
		background: #E2E8F0;
		flex-shrink: 0;
	}

	.skeleton-content {
		flex: 1;
		display: flex;
		flex-direction: column;
		gap: 14rpx;
	}

	.skeleton-line {
		height: 24rpx;
		border-radius: 12rpx;
		background: #E2E8F0;
	}

	.skeleton-line-title {
		width: 64%;
	}

	.skeleton-line-meta {
		width: 42%;
	}

	.empty-state {
		display: flex;
		flex-direction: column;
		align-items: center;
		gap: 18rpx;
		padding: 98rpx 48rpx 0;
	}

	.empty-title {
		font-size: 32rpx;
		font-weight: 800;
		color: $text-dark;
	}

	.empty-desc {
		max-width: 520rpx;
		font-size: 26rpx;
		line-height: 1.6;
		text-align: center;
		color: $text-muted;
		margin-bottom: 10rpx;
	}

	.records-content {
		padding: 26rpx 24rpx 0;
	}

	.section-head {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 20rpx;
		margin-bottom: 18rpx;
	}

	.section-title {
		display: block;
		font-size: 31rpx;
		font-weight: 900;
		color: $text-dark;
	}

	.section-subtitle {
		display: block;
		margin-top: 6rpx;
		font-size: 23rpx;
		color: $text-muted;
	}

	.month-group {
		margin-top: 20rpx;
	}

	.month-head {
		display: flex;
		align-items: center;
		gap: 12rpx;
		margin-bottom: 14rpx;
		padding: 0 4rpx;
	}

	.month-dot {
		width: 18rpx;
		height: 18rpx;
		border-radius: 50%;
		background: #CBD5E1;
		box-shadow: 0 0 0 8rpx #F1F5F9;
		flex-shrink: 0;

		&.month-dot-active {
			background: $primary;
			box-shadow: 0 0 0 8rpx #FFEDD5;
		}
	}

	.month-label {
		flex: 1;
		font-size: 27rpx;
		font-weight: 800;
		color: $text-dark;
	}

	.record-card {
		position: relative;
		display: flex;
		align-items: center;
		gap: 18rpx;
		min-height: 150rpx;
		margin-bottom: 16rpx;
		padding: 22rpx 20rpx 22rpx 24rpx;
		border-radius: 24rpx;
		background: $card-bg;
		box-shadow: $shadow;
		overflow: hidden;
		transition: transform 0.18s ease, box-shadow 0.18s ease;

		&.record-card-active {
			transform: scale(0.985);
			box-shadow: $shadow-active;
		}
	}

	.record-accent {
		position: absolute;
		left: 0;
		top: 0;
		bottom: 0;
		width: 7rpx;
	}

	.record-icon {
		width: 82rpx;
		height: 82rpx;
		border-radius: 22rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		flex-shrink: 0;
	}

	.record-main {
		flex: 1;
		min-width: 0;
		display: flex;
		flex-direction: column;
		gap: 8rpx;
	}

	.record-title-row {
		display: flex;
		align-items: center;
		gap: 12rpx;
		min-width: 0;
	}

	.record-title {
		flex: 1;
		min-width: 0;
		font-size: 29rpx;
		font-weight: 800;
		color: $text-dark;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.record-desc {
		font-size: 24rpx;
		color: $text-muted;
		line-height: 1.45;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.record-meta {
		display: flex;
		align-items: center;
		flex-wrap: wrap;
		gap: 10rpx;
		margin-top: 2rpx;
	}

	.meta-pill {
		max-width: 220rpx;
		height: 42rpx;
		box-sizing: border-box;
		display: flex;
		align-items: center;
		gap: 5rpx;
		padding: 0 12rpx;
		border-radius: 999rpx;
		background: #F8FAFC;
		border: 1rpx solid $border;
		font-size: 21rpx;
		color: $text-body;

		text {
			overflow: hidden;
			text-overflow: ellipsis;
			white-space: nowrap;
		}
	}

	.meta-pill-wide {
		max-width: 280rpx;
	}

	.cost-pill {
		background: #FEF2F2;
		border-color: #FEE2E2;
		color: #DC2626;
		font-weight: 800;
	}

	.bottom-tip {
		height: 86rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		gap: 8rpx;
		font-size: 23rpx;
		color: $text-muted;
	}

	.button-inner {
		display: flex;
		align-items: center;
		justify-content: center;
		gap: 10rpx;
	}

	.fab-wrap {
		position: fixed;
		left: 50%;
		transform: translateX(-50%);
		z-index: 60;
	}
</style>
