<script lang="ts">
import { reactive } from 'vue'

/** 模块级状态——组件销毁重建时不会重置 */
const menuLabels = ['统计', '签到', '管理', '系统'] as const
const collapsedGroups = reactive(new Set<string>(menuLabels))
</script>

<script setup lang="ts">
import { computed, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
import { useToast } from '@/composables/useToast'

const { toasts } = useToast()

const router = useRouter()
const route = useRoute()
const authStore = useAuthStore()

const menuItems = [
  {
    label: '统计',
    items: [
      { path: '/dashboard', icon: 'fas fa-chart-simple', text: '仪表盘', perm: 'business:dataCount' },
      { path: '/data-report', icon: 'fas fa-file-excel', text: '数据报表', perm: 'business:dataCount' },
      { path: '/operation-log', icon: 'fas fa-history', text: '操作日志', perm: 'system:log' },
    ],
  },
  {
    label: '签到',
    items: [
      { path: '/member-signin', icon: 'fas fa-clipboard-check', text: '签到明细', perm: 'business:checkIn' },
    ],
  },
  {
    label: '管理',
    items: [
      { path: '/member-manage', icon: 'fas fa-users', text: '会员管理', perm: 'business:member' },
      { path: '/member-card-manage', icon: 'fas fa-id-card', text: '会员卡管理', perm: 'business:memberCard' },
      { path: '/coach-manage', icon: 'fas fa-user-tie', text: '教练管理', perm: 'business:groupCourse' },
      { path: '/group-course', icon: 'fas fa-dumbbell', text: '团课管理', perm: 'business:groupCourse' },
      { path: '/group-course-types', icon: 'fas fa-tags', text: '类型管理', perm: 'business:groupCourseType' },
      { path: '/group-course-recommend', icon: 'fas fa-star', text: '推荐团课管理', perm: 'business:groupCourseRecommend' },
    ],
  },
  {
    label: '系统',
    items: [
      { path: '/employee-manage', icon: 'fas fa-user-cog', text: '账号管理', perm: 'business:employee' },
      { path: '/role-manage', icon: 'fas fa-shield-alt', text: '角色权限', perm: 'system:role' },
      { path: '/notice-manage', icon: 'fas fa-bullhorn', text: '系统公告', perm: 'system:notice' },
      { path: '/dict-manage', icon: 'fas fa-book', text: '字典管理', perm: 'system:dict' },
    ],
  },
]

function toggleGroup(label: string) {
  if (collapsedGroups.has(label)) {
    collapsedGroups.delete(label)
  } else {
    collapsedGroups.add(label)
  }
}

function expandAll() {
  collapsedGroups.clear()
}

const allExpanded = computed(() => collapsedGroups.size === 0)

/** 按用户权限过滤菜单 */
const filteredMenuItems = computed(() => {
  return menuItems
    .map((group) => ({
      ...group,
      items: group.items.filter((item) => !item.perm || authStore.hasPermission(item.perm)),
    }))
    .filter((group) => group.items.length > 0)
})

const isActive = (path: string) => {
  return route.path === path
}

const navigate = (path: string) => {
  router.push(path)
}

const handleLogout = () => {
  authStore.logout()
  router.push('/login')
}

const initials = computed(() => {
  return authStore.nickname.slice(0, 2).toUpperCase() || 'AD'
})

/** 页面刷新后重新拉取权限以保持同步 */
onMounted(() => {
  if (authStore.isLoggedIn) {
    authStore.fetchPermissions()
  }
})
</script>

<template>
  <div class="app-layout">
    <aside class="sidebar">
      <div class="brand">
        <div class="brand-icon">G</div>
        <div class="brand-text">Gym<span>Manage</span></div>
      </div>
      <nav class="nav">
        <button
          class="expand-all-btn"
          :disabled="allExpanded"
          @click="expandAll"
        >
          <i class="fas fa-expand-alt"></i> 展开所有
        </button>
        <template v-for="group in filteredMenuItems" :key="group.label">
          <div class="nav-group" :class="{ expanded: !collapsedGroups.has(group.label) }">
            <div
              class="nav-label"
              @click="toggleGroup(group.label)"
            >
              <i
                class="fas nav-caret"
                :class="collapsedGroups.has(group.label) ? 'fa-chevron-right' : 'fa-chevron-down'"
              ></i>
              <span>{{ group.label }}</span>
            </div>
            <TransitionGroup name="nav-item">
              <a
                v-for="item in group.items"
                v-show="!collapsedGroups.has(group.label)"
                :key="item.path"
                class="nav-item"
                :class="{ active: isActive(item.path) }"
                @click="navigate(item.path)"
              >
                <i :class="item.icon"></i>
                <span>{{ item.text }}</span>
              </a>
            </TransitionGroup>
          </div>
        </template>
      </nav>
      <div class="user-card">
        <div class="user-avatar">{{ initials }}</div>
        <div class="user-info">
          <div class="name">{{ authStore.nickname }}</div>
          <div class="role">{{ authStore.roleDisplay }}</div>
        </div>
        <i
          class="fas fa-sign-out-alt"
          style="color: #8b9ab0; cursor: pointer"
          title="退出登录"
          @click="handleLogout"
        ></i>
      </div>
    </aside>

    <main class="main">
      <header class="header">
        <div class="header-title">
          <h1>{{ route.meta.title || '仪表盘' }}</h1>
        </div>
        <div class="header-actions">
          <button class="btn btn-outline" @click="handleLogout">
            <i class="fas fa-sign-out-alt"></i><span>退出</span>
          </button>
        </div>
      </header>

      <slot />
    </main>

    <!-- toast notifications -->
    <Teleport to="body">
      <div class="toast-container">
        <transition-group name="toast">
          <div
            v-for="t in toasts"
            :key="t.id"
            class="toast-item"
            :class="t.type"
          >
            <i v-if="t.type === 'success'" class="fas fa-check-circle"></i>
            <i v-else-if="t.type === 'error'" class="fas fa-times-circle"></i>
            <i v-else class="fas fa-info-circle"></i>
            <span>{{ t.message }}</span>
          </div>
        </transition-group>
      </div>
    </Teleport>
  </div>
</template>

<style scoped>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.app-layout {
  display: flex;
  min-height: 100vh;
  background: #f6f8fc;
}

.sidebar {
  width: 260px;
  background: #ffffff;
  border-right: 1px solid #e9edf4;
  display: flex;
  flex-direction: column;
  padding: 24px 16px;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 100;
  transition: all 0.2s;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.02);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 8px 28px 8px;
  border-bottom: 1px solid #f0f3f8;
  margin-bottom: 20px;
}

.brand-icon {
  width: 36px;
  height: 36px;
  background: linear-gradient(145deg, #4f7cff, #3b5fd9);
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 20px;
  font-weight: 600;
  box-shadow: 0 6px 12px rgba(79, 124, 255, 0.25);
}

.brand-text {
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.3px;
  color: #0b1a33;
}

.brand-text span {
  color: #4f7cff;
}

.nav {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.nav-group {
  position: relative;
  margin-bottom: 8px;
  border-radius: 10px;
  transition: background 0.2s;
}

.nav-group.expanded {
  background: #f4f7fd;
  padding-bottom: 8px;
  border: 1px solid #e8edf6;
}

.nav-group.expanded::before {
  content: '';
  position: absolute;
  left: 18px;
  top: 38px;
  bottom: 10px;
  width: 1px;
  background: #dce3f0;
  border-radius: 1px;
  pointer-events: none;
}

.nav-label {
  font-size: 12px;
  font-weight: 600;
  color: #4a5568;
  padding: 10px 12px 6px 12px;
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  user-select: none;
  transition: color 0.15s, background 0.15s;
  border-radius: 8px;
}

.nav-label:hover {
  color: #4f7cff;
  background: #eef3ff;
}

.expand-all-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  margin-bottom: 8px;
  border: 1px solid #dde2eb;
  border-radius: 8px;
  background: #fff;
  color: #4a5568;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s;
}

.expand-all-btn:hover:not(:disabled) {
  border-color: #4f7cff;
  color: #4f7cff;
  background: #f4f7fd;
}

.expand-all-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.nav-caret {
  font-size: 10px;
  width: 12px;
  color: #9ca3af;
  transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1), color 0.2s;
}

.nav-label:hover .nav-caret {
  color: #4f7cff;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px 10px 32px;
  margin-left: 4px;
  border-radius: 8px;
  color: #5a6d80;
  font-weight: 500;
  font-size: 13.5px;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  text-decoration: none;
  position: relative;
  transform-origin: left center;
}

.nav-item::before {
  content: '';
  position: absolute;
  left: 14px;
  top: 50%;
  width: 8px;
  height: 1px;
  background: #d0d8e8;
  pointer-events: none;
  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

.nav-item i {
  width: 18px;
  font-size: 15px;
  color: #8b9ab0;
  text-align: center;
  transition: color 0.2s, transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.nav-item:hover {
  background: #e8effb;
  color: #1e293b;
  transform: translateX(3px);
}

.nav-item:hover i {
  color: #4f7cff;
  transform: scale(1.15);
}

.nav-item.active {
  background: #dbe6fb;
  color: #1e293b;
  font-weight: 600;
  transform: translateX(3px);
}

.nav-item.active::before {
  background: #4f7cff;
  width: 12px;
  height: 2px;
  left: 12px;
}

.nav-item.active i {
  color: #4f7cff;
  transform: scale(1.1);
}

/* 子菜单滑入动画 */
.nav-item-enter-active {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.nav-item-leave-active {
  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

.nav-item-enter-from {
  opacity: 0;
  transform: translateY(-8px);
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  margin-bottom: 0;
}

.nav-item-leave-to {
  opacity: 0;
  transform: translateY(-8px);
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  margin-bottom: 0;
  overflow: hidden;
}

.user-card {
  margin-top: 20px;
  padding: 16px 14px;
  background: #fafcff;
  border-radius: 16px;
  border: 1px solid #eef2f8;
  display: flex;
  align-items: center;
  gap: 14px;
}

.user-avatar {
  width: 44px;
  height: 44px;
  background: linear-gradient(135deg, #d9e2f0, #c8d3e6);
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 18px;
  color: #1e2f44;
}

.user-info {
  flex: 1;
}

.user-info .name {
  font-weight: 600;
  font-size: 14px;
}

.user-info .role {
  font-size: 12px;
  color: #7a8b9f;
}

.main {
  margin-left: 260px;
  flex: 1;
  padding: 28px 36px 36px 36px;
  min-height: 100vh;
  background: #f6f8fc;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 32px;
  flex-wrap: wrap;
  gap: 16px;
}

.header-title h1 {
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.4px;
  color: #0b1a33;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

.btn {
  padding: 9px 20px;
  border-radius: 40px;
  border: 1px solid #e2e8f0;
  background: white;
  font-weight: 500;
  font-size: 13px;
  color: #1e293b;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  transition: 0.15s;
}

.btn-primary {
  background: #4f7cff;
  border: 1px solid #4f7cff;
  color: white;
  box-shadow: 0 4px 10px rgba(79, 124, 255, 0.25);
}

.btn-primary:hover {
  background: #3f6ae0;
  border-color: #3f6ae0;
}

.btn-outline {
  background: transparent;
  border: 1px solid #e2e8f0;
}

.btn-outline:hover {
  background: #f0f5ff;
}

@media (max-width: 768px) {
  .sidebar {
    width: 72px;
    padding: 16px 8px;
  }
  .brand-text,
  .nav-label,
  .nav-item span,
  .user-info {
    display: none;
  }
  .nav-item {
    justify-content: center;
    padding: 12px;
  }
  .nav-item i {
    font-size: 20px;
    margin: 0;
  }
  .user-card {
    justify-content: center;
    padding: 8px;
  }
  .user-avatar {
    width: 36px;
    height: 36px;
    font-size: 14px;
  }
  .main {
    margin-left: 72px;
    padding: 20px 16px;
  }
}

/* ---- toast ---- */
.toast-container {
  position: fixed;
  top: 24px;
  right: 24px;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: 10px;
  pointer-events: none;
}

.toast-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 20px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 500;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
  pointer-events: auto;
  min-width: 220px;
}

.toast-item.success {
  background: #ecfdf5;
  color: #0b8b5e;
  border: 1px solid #a7f3d0;
}

.toast-item.error {
  background: #fef2f2;
  color: #dc2626;
  border: 1px solid #fecaca;
}

.toast-item.info {
  background: #eff6ff;
  color: #4f7cff;
  border: 1px solid #bfdbfe;
}

.toast-item i {
  font-size: 18px;
  flex-shrink: 0;
}

.toast-enter-active {
  transition: all 0.3s ease;
}

.toast-leave-active {
  transition: all 0.25s ease;
}

.toast-enter-from {
  opacity: 0;
  transform: translateX(40px);
}

.toast-leave-to {
  opacity: 0;
  transform: translateX(40px);
}
</style>