<template>
	<view class="patient-group-page">
	
		<!-- 头部 -->
		<view class="navbox">
			<view class="status_bar"></view>
			<uni-nav-bar
			left-icon="left" 
			title="患者分组" 
			@clickLeft="goBack" 
			
			color="#8B2316" 
			
			:border="false" 
			backgroundColor="#eeeeee"
		>
			<template #right>
				<view class="save-text" @click="addGroup">新建</view>
			</template>
		</uni-nav-bar>
		</view>
		<!-- 筛选排序栏 -->
		<view class="filter-sort-bar">
			<view class="sort-section" @click="toggleGroupSort">
				<text class="sort-label" :class="{ 'is-selected': groupSortSelected }">{{ groupSortTitle }}</text>
				<view class="imgbox">
					<up-image  :src="groupSortIcon" width="26rpx" height="26rpx" ></up-image>
				</view>
			</view>
			<view class="divider"></view>
			<view class="current-sort" @click="toggleInnerSort">
				<text class="sort-text" :class="{ 'is-selected': innerSortSelected }">{{ innerSortTitle }}</text>
				<view class="imgbox">
					<up-image  :src="innerSortIcon" width="26rpx" height="26rpx" ></up-image>
				</view>
			</view>
		</view>

		<!-- 分组排序弹窗 -->
		<view v-if="showGroupSort" class="popup-panel">
			<view class="popup-item" :class="{ active: group_sort==0 }" @click.stop="chooseGroupSort('letter')">
				<text class="item-text">按首字母</text>
				<uni-icons v-if="selectedGroupSort==='letter'" type="checkmarkempty" color="#8B2316" size="22"></uni-icons>
			</view>
			<view class="popup-divider"></view>
			<view class="popup-item" :class="{ active:group_sort==1}" @click.stop="chooseGroupSort('count')">
				<text class="item-text">分组人数</text>
				<uni-icons v-if="selectedGroupSort==='count'" type="checkmarkempty" color="#8B2316" size="22"></uni-icons>
			</view>
		</view>
		<view v-if="showGroupSort" class="popup-mask" @click="closeGroupSort"></view>

		<!-- 组内排序弹窗 -->
		<view v-if="showInnerSort" class="popup-panel">
			<view class="popup-item" :class="{ active:list_sort==0 }" @click.stop="chooseInnerSort('letter')">
				<text class="item-text">按首字母</text>
				<uni-icons v-if="selectedInnerSort==='letter'" type="checkmarkempty" color="#8B2316" size="22"></uni-icons>
			</view>
			<view class="popup-divider"></view>
			<view class="popup-item" :class="{ active:list_sort==1 }" @click.stop="chooseInnerSort('count')">
				<text class="item-text">随访时间</text>
				<uni-icons v-if="selectedInnerSort==='count'" type="checkmarkempty" color="#8B2316" size="22"></uni-icons>
			</view>
		</view>
		<view v-if="showInnerSort" class="popup-mask" @click="closeInnerSort"></view>

		<!-- 患者列表 -->
		<scroll-view class="patient-list-section" scroll-y="true" >
			<!-- 分组循环渲染 -->
			<view class="groupcell" v-for="(group, gi) in groups" :key="group.uuid || gi" style="flex-direction: row;">
				<view class="section-title" @click="toggleGroup(gi)">
					<view class="left">
						<view class="imgbox" :class="{ 'active':openGroups[gi] }">
							<up-image v-if="!openGroups[gi]" :src="groupRightImg" width="19rpx" height="32rpx" ></up-image>
							<up-image v-else :src="groupDownImg" width="32rpx" height="19rpx" ></up-image>
						</view>
						<view class="title">{{ group.name || '未命名分组' }} | {{ group.patientNum || (group.patientList ? group.patientList.length : 0) }}</view>
					</view>
					<view class="right-edit" @click.stop="editGroup(group)">
						
						<text class="edit-text">编辑</text>
					</view>
				</view>
				<view class="patient-list" v-if="openGroups[gi]">
					<view class="patient-item" v-for="(patient, index) in getVisiblePatients(group, gi)" :key="patient.uuid || index" @click="goPatientDetail(patient.uuid)">
						<view class="patient-avatar">
							<up-image :src="patient._avatarLoadError ? defaultImg : patient._photoUrl" width="80rpx" height="80rpx" mode="aspectFill" @error="handlePatientAvatarError(patient)"></up-image>
						</view>
						<view class="patient-info">
							<view class="patient-name">{{ patient._displayName }}</view>
							<view class="follow-up-time">随访于{{ patient._formattedJoinDate }}</view>
						</view>
					</view>
					<view v-if="isGroupRendering(group, gi)" class="rendering-tip">加载中...</view>
				</view>
			</view>
			<empty v-if="groups.length == 0" :emptyDesc="'暂无分组'" />
		</scroll-view>
	</view>
</template>

<script setup>
import { ref, computed, onMounted,nextTick } from 'vue';
import { onShow,onBackPress,onLoad } from "@dcloudio/uni-app";
import upImg from "@/static/triangle_green_theme.png"
import downImg from "@/static/triangle_normal.png"
import groupRightImg from "@/static/groupright_big.png"
import groupDownImg from "@/static/groupup_big.png"
import normalImg from "@/static/triangle_normal.png"
import api from '@/api/api.js';
import docUrl from '@/utils/docUrl'
import empty from "@/components/empty/empty.vue"
import dayjs from 'dayjs'
import navTo from '@/utils/navTo.js'
import defaultImg from "@/static/default.png"
const list_sort = ref(0);
const group_sort = ref(0);
const groupSortSelected = ref(false);
const innerSortSelected = ref(false);
const from = ref('');
onLoad((options) => {
	if(options.from){
		from.value = options.from;
	}
});
onShow(() => {
	uni.showLoading({
		title: '加载中...',
		mask: true
	});
	fetchGroupList();
});
const goPatientDetail = (uuid) => {
		navTo({
			url: `/pages_app/patientDetail/patientDetail?uuid=${uuid}`
		})
	}
onBackPress(() => {
	if(!from.value){
		uni.navigateBack();
		return true;
	}
});
// 分组数据与展开状态
const groups = ref([]);
const openGroups = ref({});
const groupRenderCount = ref({});
const INITIAL_RENDER_COUNT = 20;
const BATCH_RENDER_COUNT = 20;

const formatYMD = (val) => {
	if (!val) return '';
	const d = dayjs(val);
	return d.isValid() ? d.format('YYYY-MM-DD') : '';
};

// 排序栏标题/图标（初始化为默认文案+灰色图标，选择后展示具体文案+主题图标）
const groupSortTitle = computed(() => {
	if (!groupSortSelected.value) return '分组排序';
	return group_sort.value === 0 ? '按首字母' : '分组人数';
});
const innerSortTitle = computed(() => {
	if (!innerSortSelected.value) return '组内排序';
	return list_sort.value === 0 ? '按首字母' : '随访时间';
});
const groupSortIcon = computed(() => groupSortSelected.value ? upImg : normalImg);
const innerSortIcon = computed(() => innerSortSelected.value ? upImg : normalImg);


const fetchGroupList = async () => {
	const res = await api.groupList({
		list_sort:list_sort.value,
		page:1,
		pageSize:10,
		group_sort:group_sort.value
	});
	if(res.code === 200){
		groups.value = Array.isArray(res.data) ? preprocessGroups(res.data) : [];
		// 初始化展开状态：默认收起
		openGroups.value = {};
		groupRenderCount.value = {};
		groups.value.forEach((_, idx) => openGroups.value[idx] = false);
		nextTick(() => {
			uni.hideLoading();
		});
	}
};

const toggleGroup = (idx) => {
	openGroups.value[idx] = !openGroups.value[idx];
	if (openGroups.value[idx]) {
		startProgressiveRender(idx);
	}
};

const preprocessGroups = (rawGroups) => {
	return rawGroups.map((group) => {
		const list = Array.isArray(group.patientList) ? group.patientList : [];
		list.forEach((patient) => {
			patient._formattedJoinDate = formatYMD(patient.join_date);
			patient._displayName =  patient.nickname || patient.realName ;
			patient._photoUrl = patient.photo ? `${docUrl}${patient.photo}` : defaultImg;
		});
		return {
			...group,
			patientList: list
		};
	});
};

const handlePatientAvatarError = (patient) => {
	if (!patient) return;
	patient._avatarLoadError = true;
};

const startProgressiveRender = (idx) => {
	const group = groups.value[idx];
	if (!group) return;
	const total = (group.patientList || []).length;
	if (!total) {
		groupRenderCount.value[idx] = 0;
		return;
	}

	groupRenderCount.value[idx] = Math.min(INITIAL_RENDER_COUNT, total);
	if (total <= INITIAL_RENDER_COUNT) return;

	const loadNextBatch = () => {
		if (!openGroups.value[idx]) return;
		const current = groupRenderCount.value[idx] || 0;
		if (current >= total) return;
		groupRenderCount.value[idx] = Math.min(current + BATCH_RENDER_COUNT, total);
		if (groupRenderCount.value[idx] < total) {
			setTimeout(loadNextBatch, 16);
		}
	};

	setTimeout(loadNextBatch, 16);
};

const getVisiblePatients = (group, idx) => {
	const list = group?.patientList || [];
	const renderCount = groupRenderCount.value[idx] || 0;
	if (renderCount >= list.length) return list;
	return list.slice(0, renderCount);
};

const isGroupRendering = (group, idx) => {
	const total = (group?.patientList || []).length;
	const rendered = groupRenderCount.value[idx] || 0;
	return total > 0 && rendered < total;
};

const editGroup = (group) => {
	navTo({
		url: `/pages_app/groupEdit/groupEdit?uuid=${group.uuid}`
	})
};

// 分组排序弹窗状态
const showGroupSort = ref(false);
const selectedGroupSort = ref('letter'); // letter | count

// 组内排序弹窗状态
const showInnerSort = ref(false);
const selectedInnerSort = ref('letter');

// 待分组展开/收起
const showPending = ref(false);

const toggleGroupSort = () => {
  showGroupSort.value = !showGroupSort.value;
  if (showGroupSort.value) showInnerSort.value = false;
};
const closeGroupSort = () => {
  showGroupSort.value = false;
};

const chooseGroupSort = (type) => {
	selectedGroupSort.value = type;
	// 修改接口字段：按首字母=0，分组人数=1
	group_sort.value = type === 'letter' ? 0 : 1;
	groupSortSelected.value = true;
	closeGroupSort();
	fetchGroupList();
};
const addGroup = () => {
	navTo({
		url: `/pages_app/groupEdit/groupEdit`
	})
}
const toggleInnerSort = () => {
  showInnerSort.value = !showInnerSort.value;
  if (showInnerSort.value) showGroupSort.value = false;
};

const closeInnerSort = () => {
  showInnerSort.value = false;
};

const chooseInnerSort = (type) => {
	selectedInnerSort.value = type;
	// 组内排序：按首字母=0，随访时间=1
	list_sort.value = type === 'letter' ? 0 : 1;
	innerSortSelected.value = true;
	closeInnerSort();
	fetchGroupList();
};

// 方法
const goBack = () => {
	if(!from.value){
		plus.runtime.quit();
	}else{
		uni.navigateBack();
	}
};

const createNew = () => {
	uni.showToast({
		title: '跳转到新建分组页面',
		icon: 'none'
	});
	// 这里可以跳转到新建分组页面
};

</script>

<style lang="scss" scoped>
.patient-group-page {
	min-height: 100vh;
	background-color: #f5f5f5;
	.groupcell{
	    flex-direction: row!important;
   }	
}

/* 弹窗样式 */
.popup-mask {
	position: fixed;
	top: 220rpx; /* 位于筛选栏下方 */
	left: 0;
	right: 0;
	bottom: 0;
	background: rgba(0,0,0,0.3);
	z-index: 8;
}

.popup-panel {
	position: fixed;
	top: calc(var(--status-bar-height) + 44px + 82rpx); /* 紧贴筛选栏 */
	left: 0;
	right: 0;
	background: #fff;
	z-index: 10;
	box-shadow: 0 6rpx 20rpx rgba(0,0,0,0.08);
}

.popup-item {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 28rpx 30rpx;
	font-size: 30rpx;
	color: #333;
}

.popup-divider {
	height: 2rpx;
	background: #eaeaea;
}

.popup-item.active .item-text {
	color: #8B2316;
}
.save-text{ 
	color:#8B2316; 
	font-size: 30rpx;
	display: flex;
	align-items: center;
	justify-content: center;
	
 }
.status-bar {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 10rpx 30rpx;
	background-color: #ffffff;
	font-size: 24rpx;
	color: #333;
	
	.status-left {
		display: flex;
		align-items: center;
		gap: 20rpx;
		
		.time {
			font-weight: 500;
		}
		
		.app-icons {
			display: flex;
			gap: 10rpx;
			
			.app-icon {
				width: 24rpx;
				height: 24rpx;
				border-radius: 4rpx;
				
				&.weibo {
					background-color: #ff8200;
				}
				
				&.taobao {
					background-color: #ff6a00;
				}
				
				&.xiaohongshu {
					background-color: #ff2442;
				}
			}
		}
	}
	
	.status-right {
		display: flex;
		align-items: center;
		gap: 15rpx;
		
		.network {
			color: #666;
		}
		
		.signal-icon {
			width: 32rpx;
			height: 20rpx;
			background-color: #333;
			border-radius: 2rpx;
		}
		
		.battery-text {
			font-size: 20rpx;
			color: #333;
		}
		
		.battery {
			width: 40rpx;
			height: 20rpx;
			border: 2rpx solid #333;
			border-radius: 4rpx;
			background-color: #4caf50;
			position: relative;
			
			&::after {
				content: '';
				position: absolute;
				right: -6rpx;
				top: 6rpx;
				width: 4rpx;
				height: 8rpx;
				background-color: #333;
				border-radius: 0 2rpx 2rpx 0;
			}
		}
	}
}

.header {
	display: flex;
	align-items: center;
	padding: 20rpx 30rpx;
	background-color: #ffffff;
	border-bottom: 1rpx solid #f0f0f0;
	
	.back-btn {
		padding: 10rpx;
	}
	
	.title {
		flex: 1;
		text-align: center;
		font-size: 36rpx;
		font-weight: normal;
		color: #ff0000;
		margin-right: 60rpx; // 为了保持标题居中
	}
	
	.new-btn {
		padding: 10rpx;
		
		.new-text {
			font-size: 28rpx;
			color: #ff0000;
		}
	}
}

.filter-sort-bar {
	display: flex;
	align-items: center;
	justify-content:center;
	padding: 20rpx 30rpx;
	background-color: #ffff;
	position: fixed;
	top: calc(var(--status-bar-height) + 44px);
	left: 0;
	right: 0;
	z-index: 9;
	border-bottom: 1rpx solid #f0f0f0;
	.imgbox{
		width: 32rpx;
		margin-top: -10rpx;
	}
	.sort-section {
		display: flex;
		align-items: center;
		gap: 10rpx;
		
		.sort-label {
			font-size: 28rpx;
			color: #999;
			&.is-selected {
				color: #8B2316;
			}
		}
		
		.sort-icon.down {
			width: 0;
			height: 0;
			border-left: 8rpx solid transparent;
			border-right: 8rpx solid transparent;
			border-top: 12rpx solid #999;
		}
	}
	
	.divider {
		width: 2rpx;
		height: 40rpx;
		background-color: #e0e0e0;
		margin: 0 80rpx;
	}
	
	.current-sort {
		display: flex;
		align-items: center;
		gap: 10rpx;
		
		.sort-text {
			font-size: 28rpx;
			color: #999;
			&.is-selected {
				color: #8B2316;
			}
		}
		
		.sort-icon.up {
			width: 0;
			height: 0;
			border-left: 8rpx solid transparent;
			border-right: 8rpx solid transparent;
			border-bottom: 12rpx solid #999;
			
			&.active {
				border-bottom-color: #ff0000;
			}
		}
	}
}

.patient-list-section {
	top: calc(var(--status-bar-height) + 44px + 100rpx);
	width:100%;
	bottom:0;
	position: fixed;
	background-color: #ffffff;
	
	.section-title {
		padding: 30rpx 30rpx 20rpx;
		font-size: 32rpx;
		width: 100%;
		box-sizing: border-box;
		font-weight: normal;
		display: flex;
		color: #333;
		border-bottom: 1rpx solid #f0f0f0;
		align-items: center;
		justify-content: space-between;
		.left{
			display:flex;
			align-items:center;
		}
		.imgbox{
			&.active{
				margin-top: -20rpx;
			}
			margin-right: 8rpx;
		}
		.right-edit{
			display:flex;
			align-items:center;
			gap: 8rpx;
			.edit-text{ font-size: 28rpx; color:#8B2316; }
		}
	}
	
	.patient-list {
		// 滚动视图样式
		&::-webkit-scrollbar {
			display: none;
		}
		
		.patient-item {
			display: flex;
			align-items: center;
			gap: 20rpx;
			padding: 30rpx;
			border-bottom: 1rpx solid #f0f0f0;
			
			&:last-child {
				border-bottom: none;
			}
			
			.patient-avatar {
				width: 80rpx;
				height: 80rpx;
				border-radius: 12rpx;
				overflow: hidden;
			}
			
			.patient-info {
				flex: 1;
				
				.patient-name {
					font-size: 32rpx;
					color: #333;
					margin-top: 24rpx;
				}
				
				.follow-up-time {
					font-size: 24rpx;
					color: #999;
					display: flex;
					justify-content: flex-end;
				}
			}
		}
	}

	.rendering-tip {
		padding: 16rpx 30rpx 24rpx;
		font-size: 24rpx;
		color: #999;
		text-align: center;
	}
}
</style>
