<template>
	<el-dialog
		v-model="visible"
		:title="dialogTitle"
		width="80%"
		:show-close="false"
		:close-on-click-modal="false"
		:close-on-press-escape="false"
		:before-close="handleBeforeClose"
		center
	>
		<el-form>
			<el-form-item class="role-form-item">
				<el-radio-group v-model="radio" class="role-radio-group" @change="handleChangeRole">
					<template v-for="(roles, groupName) in allRoleGroups" :key="groupName">
						<el-card class="role-group-card" shadow="hover">
							<template #header>
								<span class="group-name">{{ groupName }}</span>
							</template>
							<div class="role-group">
								<el-radio-button v-for="item in roles" :key="item.roleCode" :label="item.roleCode" size="small">
									{{ item.roleName }}
								</el-radio-button>
							</div>
						</el-card>
					</template>
				</el-radio-group>
			</el-form-item>
		</el-form>

		<template v-if="!requireSelectToClose" #footer>
			<el-button @click="handleFooterClose">关 闭</el-button>
		</template>
	</el-dialog>
</template>

<script setup lang="ts">
import { ref, computed, toRef } from 'vue';
import { listAllRole } from '/@/api/admin/role';
import { Local, Session } from '/@/utils/storage';
import { useMessage } from '/@/hooks/message';

/** 弹框标题，如「角色切换」「登录角色选择」 */
const props = withDefaults(defineProps<{ title?: string; requireSelectToClose?: boolean }>(), { title: '角色切换', requireSelectToClose: false });
const dialogTitle = computed(() => props.title);

const visible = ref(false);
const radio = ref('');
/** 按分组名分组的角色列表：{ "未分组": [{ roleId, roleName, roleCode, ... }], ... } */
const allRoleGroups = ref<Record<string, any[]>>({});
const requireSelectToClose = toRef(props, 'requireSelectToClose');

const open = () => {
	if (visible.value) return;
	visible.value = true;
	listAllRole().then((res) => {
		allRoleGroups.value =
			res.data && typeof res.data === 'object' && !Array.isArray(res.data) ? res.data : { 未分组: Array.isArray(res.data) ? res.data : [] };
		radio.value = Local.get('roleCode');
	});
};

/** 根据 roleCode 从分组数据中查找角色 */
const findRoleByCode = (code: string) => {
	for (const roles of Object.values(allRoleGroups.value)) {
		if (!Array.isArray(roles)) continue;
		const found = roles.find((r: any) => r.roleCode === code);
		if (found) return found;
	}
	return null;
};

const canClose = () => {
	if (!radio.value) {
		useMessage().warning('请选择一个角色');
		return false;
	}
	return true;
};

const handleBeforeClose = (done: () => void) => {
	if (requireSelectToClose.value) {
		useMessage().warning('请先选择登录角色');
		return;
	}
	if (!canClose()) return;
	done();
};

const handleFooterClose = () => {
	if (!canClose()) return;
	visible.value = false;
};

const handleChangeRole = (label: string) => {
	const obj = findRoleByCode(label);
	if (!obj) return;
	Local.set('roleCode', obj.roleCode);
	Local.set('roleName', obj.roleName);
	Local.set('roleId', obj.roleId);
	useMessage().success('操作成功');
	// 清掉 tags 缓存，重载后只保留首页 tag
	Session.remove('tagsViewList');
	// 清除 pinia 持久化的 tagsView 路由，避免重载后先恢复旧角色菜单再被新路由覆盖前就初始化出“不存在的 tag”
	try {
		window.localStorage.removeItem('tagsViewRoutes');
	} catch (_) {}
	setTimeout(() => {
		window.location.hash = '#/home';
		window.location.reload();
	}, 500);
};

defineExpose({
	open,
});
</script>

<style scoped lang="scss">
.role-form-item {
	:deep(.el-form-item__content) {
		flex-wrap: wrap;
	}
}
.role-radio-group {
	display: flex;
	flex-direction: column;
	gap: 6px;
	width: 100%;

	:deep(.el-radio-button) {
		margin: 0;
	}
	:deep(.el-radio-button__inner) {
		border-radius: 6px !important;
		border: 1px solid var(--el-border-color) !important;
		margin-left: 0 !important;
		line-height: 1.3;
	}
	:deep(.el-radio-button.is-active .el-radio-button__inner) {
		border-color: var(--el-color-primary) !important;
	}
}
.role-group-card {
	width: 100%;
	flex: 0 0 auto;

	:deep(.el-card__header) {
		padding: 6px 12px;
		font-size: 14px;
		font-weight: 600;
		color: var(--el-text-color-primary);
	}
	:deep(.el-card__body) {
		padding: 6px 12px 8px;
	}
}
.role-group {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 4px 8px;
}
.group-name {
	font-size: 14px;
	font-weight: 600;
	color: var(--el-text-color-primary);
}
</style>
