<template>
  <a-layout class="layout-shell">
    <!-- 左侧固定侧边栏 -->
    <a-layout-sider
      v-model:collapsed="collapsed"
      :collapsed-width="64"
      :trigger="null"
      :width="220"
      breakpoint="lg"
      class="sider"
      collapsible
      theme="dark"
    >
      <!-- Logo 区域 -->
      <div class="sider-logo" @click="navigateTo('/admin')">
        <img alt="logo" class="logo-img" src="/logo.png" />
        <transition name="logo-text">
          <span v-if="!collapsed" class="logo-name">决策咨询网</span>
        </transition>
      </div>

      <!-- 菜单 -->
      <a-menu
        :inline-collapsed="collapsed"
        :open-keys="collapsed ? [] : openKeys"
        :selected-keys="selectedKeys"
        mode="inline"
        theme="dark"
        @click="onMenuClick"
        @open-change="onOpenChange"
      >
        <template v-for="entry in menu" :key="isGroup(entry) ? entry.key : entry.to">
          <!-- 分组：有子菜单 -->
          <a-sub-menu v-if="isGroup(entry)" :key="entry.key">
            <template v-if="entry.icon" #icon>
              <component :is="entry.icon" />
            </template>
            <template #title>{{ entry.label }}</template>
            <a-menu-item v-for="item in entry.children" :key="item.to">
              <template v-if="item.icon" #icon>
                <component :is="item.icon" />
              </template>
              {{ item.label }}
            </a-menu-item>
          </a-sub-menu>
          <!-- 单条链接 -->
          <a-menu-item v-else :key="entry.to">
            <template v-if="entry.icon" #icon>
              <component :is="entry.icon" />
            </template>
            {{ entry.label }}
            <a-tag
              v-if="!collapsed && (entry as AdminNavLink).badge"
              :color="(entry as AdminNavLink).badge === 'NEW' ? 'green' : 'orange'"
              class="nav-badge"
            >{{ (entry as AdminNavLink).badge }}</a-tag>
          </a-menu-item>
        </template>
      </a-menu>

      <!-- 折叠按钮 -->
      <div
        :aria-label="collapsed ? '展开菜单' : '收起菜单'"
        class="sider-collapse-trigger"
        role="button"
        tabindex="0"
        @click="toggleCollapsed"
        @keydown.enter.prevent="toggleCollapsed"
        @keydown.space.prevent="toggleCollapsed"
      >
        <RightOutlined v-if="collapsed" style="font-size: 10px" />
        <LeftOutlined v-else style="font-size: 10px" />
      </div>
    </a-layout-sider>

    <!-- 右侧主区域 -->
    <a-layout :class="{ 'main-layout--collapsed': collapsed }" class="main-layout">
      <!-- 顶部 Header -->
      <a-layout-header class="main-header">
        <div class="header-inner">
          <div class="header-left">
            <a-tag class="admin-badge" color="red">决策咨询网</a-tag>
            <span class="page-title">{{ currentPageTitle }}</span>
          </div>

          <div class="header-right">
            <a-tooltip title="查看网站首页">
              <a-button size="small" type="text" @click="navigateTo('/')">
                <template #icon><DesktopOutlined /></template>
                网站首页
              </a-button>
            </a-tooltip>
            <a-dropdown :trigger="['click']" placement="bottomRight">
              <div class="user-trigger">
                <a-avatar :size="28" :src="user?.avatar || user?.avatarUrl">
                  <template #icon>
                    <UserOutlined />
                  </template>
                </a-avatar>
                <span class="user-name">{{ userDisplayName }}</span>
                <DownOutlined style="font-size: 10px; opacity: 0.6; margin-left: 2px" />
              </div>
              <template #overlay>
                <a-menu class="user-dropdown-menu" @click="onUserMenuClick">
                  <a-menu-item key="account-info">
                    <UserOutlined style="margin-right: 8px" />
                    账户信息
                  </a-menu-item>
                  <a-menu-item key="profile">
                    <IdcardOutlined style="margin-right: 8px" />
                    个人信息
                  </a-menu-item>
                  <a-menu-divider />
                  <a-menu-item key="view-site">
                    <DesktopOutlined style="margin-right: 8px" />
                    查看网站
                  </a-menu-item>
                  <a-menu-divider />
                  <a-menu-item key="logout" class="logout-item">
                    <LogoutOutlined style="margin-right: 8px" />
                    退出登录
                  </a-menu-item>
                </a-menu>
              </template>
            </a-dropdown>
          </div>
        </div>
      </a-layout-header>

      <!-- 内容区 -->
      <a-layout-content class="main-content">
        <a-spin v-if="!ready" class="spin" size="large" tip="加载中..." />
        <template v-else>
          <slot />
        </template>
      </a-layout-content>
    </a-layout>
  </a-layout>
</template>

<script lang="ts" setup>
import { message } from 'ant-design-vue'
import {
  DesktopOutlined,
  DownOutlined,
  IdcardOutlined,
  LeftOutlined,
  LogoutOutlined,
  RightOutlined,
  UserOutlined,
} from '@ant-design/icons-vue'
import { adminNav, type AdminNavEntry, type AdminNavGroup, type AdminNavLink } from '@/config/admin-nav'
import { getUserInfo } from '@/api/layout'
import { getToken, removeToken } from '@/utils/token-util'
import { clearAuthz, setAuthzFromUser } from '@/utils/permission'
import type { User } from '@/api/system/user/model'

const route = useRoute()
const collapsed = ref(false)
const menu = computed(() => adminNav)
const user = ref<User | null>(null)

const userDisplayName = computed(() => {
  const u = user.value
  return u?.nickname?.trim() || u?.username?.trim() || u?.phone?.trim() || u?.mobile?.trim() || '管理员'
})

function isGroup(entry: AdminNavEntry): entry is AdminNavGroup {
  return 'children' in entry
}

// 当前页面标题
const currentPageTitle = computed(() => {
  const path = route.path
  for (const entry of menu.value) {
    if (isGroup(entry)) {
      const hit = entry.children.find((c) => path === c.to || path.startsWith(c.to + '/'))
      if (hit) return hit.label
    } else {
      if (path === entry.to || path.startsWith(entry.to + '/')) return (entry as AdminNavLink).label
    }
  }
  return '管理后台'
})

// 选中 key
const selectedKeys = computed(() => {
  const path = route.path
  for (const entry of menu.value) {
    if (isGroup(entry)) {
      const hit = entry.children.find((c) => path === c.to || path.startsWith(c.to + '/'))
      if (hit) return [hit.to]
    } else {
      if (path === (entry as AdminNavLink).to) return [(entry as AdminNavLink).to]
    }
  }
  return []
})

// 展开 key
const openKeys = ref<string[]>([])

function syncOpenKeys() {
  const path = route.path
  const hit = menu.value.find(
    (entry) => isGroup(entry) && entry.children.some((c) => path === c.to || path.startsWith(c.to + '/'))
  )
  openKeys.value = hit ? [hit.key] : []
}

function onOpenChange(keys: string[]) {
  openKeys.value = Array.isArray(keys) ? keys.slice(-1) : []
}

function onMenuClick(info: { key: string }) {
  navigateTo(String(info.key))
}

function toggleCollapsed() {
  collapsed.value = !collapsed.value
}

function logout() {
  removeToken()
  try {
    localStorage.removeItem('TenantId')
    localStorage.removeItem('UserId')
  } catch { /* ignore */ }
  clearAuthz()
  navigateTo('/login')
}

function onUserMenuClick(info: { key: string }) {
  const key = String(info.key)
  if (key === 'account-info') navigateTo('/admin/users')
  if (key === 'profile') navigateTo('/profile')
  if (key === 'view-site') window.open('/', '_blank')
  if (key === 'logout') logout()
}

watch(() => route.path, syncOpenKeys, { immediate: true })

const ready = ref(false)

onMounted(async () => {
  const token = getToken()
  if (!token) {
    clearAuthz()
    message.error('请先登录')
    await navigateTo('/login')
    ready.value = true
    return
  }
  try {
    const me = await getUserInfo()
    user.value = me
    setAuthzFromUser(me)
    // 权限校验：isAdmin=true 方可访问管理后台
    if (!(me as any).isAdmin) {
      message.error('您无权访问管理后台，该区域仅限管理员使用')
      clearAuthz()
      await navigateTo('/login')
      ready.value = true
      return
    }
  } catch {
    user.value = null
    clearAuthz()
    await navigateTo('/login')
    ready.value = true
    return
  }
  syncOpenKeys()
  ready.value = true
})
</script>

<style scoped>
/* ===== 整体 shell ===== */
.layout-shell {
  min-height: 100vh;
  background: #f5f7fa;
}

/* ===== 左侧边栏（深红黑调，区别于 console 的深蓝黑）===== */
.sider {
  position: fixed !important;
  top: 0;
  left: 0;
  height: 100vh;
  z-index: 100;
  overflow: hidden;
  background: #1a0f0f !important;
  box-shadow: 2px 0 8px rgba(0, 0, 0, 0.2);
}

:deep(.ant-layout-sider-children) {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
}

:deep(.ant-menu-dark) {
  background: transparent;
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
}

:deep(.ant-menu-dark .ant-menu-item-selected) {
  background-color: rgba(239, 68, 68, 0.25) !important;
}

:deep(.ant-menu-dark .ant-menu-item:hover),
:deep(.ant-menu-dark .ant-menu-submenu-title:hover) {
  background-color: rgba(255, 255, 255, 0.06) !important;
}

/* Logo 区域 */
.sider-logo {
  height: 56px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 20px;
  cursor: pointer;
  flex-shrink: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  overflow: hidden;
  white-space: nowrap;
}

.logo-img {
  height: 16px;
  width: auto;
  flex-shrink: 0;
  display: block;
}

.logo-name {
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.04em;
  background: linear-gradient(135deg, #ffffff 0%, #fca5a5 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.logo-text-enter-active,
.logo-text-leave-active {
  transition: opacity 0.2s, width 0.2s;
}

.logo-text-enter-from,
.logo-text-leave-to {
  opacity: 0;
  width: 0;
}

/* 菜单中的 badge */
.nav-badge {
  margin-left: auto;
  font-size: 10px;
  padding: 0 4px;
  line-height: 16px;
  height: 16px;
}

/* 折叠按钮 */
.sider-collapse-trigger {
  position: absolute;
  right: -14px;
  top: 50%;
  transform: translateY(-50%);
  width: 14px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #2d1515;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-left: 0;
  border-radius: 0 9999px 9999px 0;
  box-shadow: 2px 0 6px rgba(0, 0, 0, 0.2);
  color: rgba(255, 255, 255, 0.6);
  cursor: pointer;
  z-index: 101;
}

.sider-collapse-trigger:hover {
  color: #fff;
  background: #3d1f1f;
}

/* ===== 右侧主区域 ===== */
.main-layout {
  margin-left: 220px;
  transition: margin-left 0.2s ease;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: #f5f7fa;
}

.main-layout--collapsed {
  margin-left: 64px;
}

/* 顶部 Header */
.main-header {
  position: sticky;
  top: 0;
  z-index: 99;
  height: 56px;
  line-height: 56px;
  padding: 0;
  background: #fff !important;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
  flex-shrink: 0;
}

.header-inner {
  height: 100%;
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.header-left {
  display: flex;
  align-items: center;
  gap: 10px;
}

.admin-badge {
  font-size: 11px;
  font-weight: 600;
  flex-shrink: 0;
}

.page-title {
  font-size: 15px;
  font-weight: 600;
  color: #1f2937;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.user-trigger {
  height: 36px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 10px;
  border-radius: 9999px;
  cursor: pointer;
  color: #374151;
  transition: background 0.2s;
}

.user-trigger:hover {
  background: rgba(0, 0, 0, 0.04);
}

.user-name {
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 14px;
  color: #374151;
}

.user-dropdown-menu {
  min-width: 180px;
}

.logout-item {
  color: #ff4d4f;
}

.logout-item:hover {
  background-color: #fff1f0;
}

/* 内容区 */
.main-content {
  flex: 1;
  padding: 20px 24px;
  min-height: calc(100vh - 56px);
}

.spin {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 400px;
}
</style>
