<script setup lang="ts">
/**
 * 侧边栏菜单
 *
 * 渲染规则：
 *   - 父路由有 meta.title 且至少 1 个可见子路由 → 「分组 el-sub-menu」
 *   - 其他叶子 → 「菜单项 el-menu-item」
 *   - meta.hidden 任何层级都隐藏
 *   - meta.order 数字小的排前面；未设置按路由表出现顺序
 *
 * 样式：
 *   - 展开中的分组：浅蓝渐变背景，与未展开的纯透明形成对比
 *   - 激活的菜单项：实色蓝色背景 + 左侧 3px 高亮条
 */
import { computed, markRaw, type Component } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'
import * as ElIcons from '@element-plus/icons-vue'

interface Props {
  collapsed?: boolean
}
defineProps<Props>()

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

/** 把字符串图标名解析为 Element Plus 图标组件（来自 @element-plus/icons-vue） */
function resolveIcon(name?: string): Component | null {
  if (!name) return null
  // 已传组件
  if (typeof name !== 'string') return name as Component
  const map = ElIcons as unknown as Record<string, Component>
  return map[name] ?? null
}

function isGroup(r: RouteRecordRaw): boolean {
  if (r.meta?.hidden) return false
  if (!r.meta?.title) return false
  const children = r.children || []
  return children.some((c) => !c.meta?.hidden && c.path && !c.path.startsWith(':'))
}

function joinPath(parent: string, child: string): string {
  if (child.startsWith('/')) return child
  if (!parent || parent === '/') return '/' + child.replace(/^\/+/, '')
  return parent.replace(/\/+$/, '') + '/' + child.replace(/^\/+/, '')
}

interface MenuLeaf {
  type: 'leaf'
  key: string
  path: string
  title: string
  icon: Component | null
  order: number
}
interface MenuGroup {
  type: 'group'
  key: string
  title: string
  icon: Component | null
  order: number
  children: { path: string; title: string; icon: Component | null }[]
}

const menuItems = computed<(MenuGroup | MenuLeaf)[]>(() => {
  const topRoutes = router.options.routes.filter(
    (r) => !r.meta?.hidden && r.path !== '/:pathMatch(.*)*'
  ) as RouteRecordRaw[]

  const out: (MenuGroup | MenuLeaf)[] = []

  topRoutes.forEach((r, idx) => {
    if (isGroup(r)) {
      const children = (r.children || [])
        .filter((c) => !c.meta?.hidden && c.path && !c.path.startsWith(':'))
        .map((c) => ({
          path: joinPath(r.path, c.path),
          title: c.meta?.title as string,
          icon: resolveIcon(c.meta?.icon as string)
        }))
      if (children.length === 0) return
      out.push({
        type: 'group',
        key: r.path,
        title: r.meta!.title as string,
        icon: resolveIcon(r.meta?.icon as string),
        order: typeof r.meta?.order === 'number' ? (r.meta.order as number) : idx,
        children
      })
    } else {
      const child = (r.children || []).find((c) => !c.meta?.hidden && c.path)
      if (child) {
        out.push({
          type: 'leaf',
          key: r.path,
          path: joinPath(r.path, child.path!),
          title: (child.meta?.title as string) || (r.meta?.title as string),
          icon:
            resolveIcon(child.meta?.icon as string) ||
            resolveIcon(r.meta?.icon as string),
          order: typeof r.meta?.order === 'number' ? (r.meta.order as number) : idx
        })
      }
    }
  })

  return out.sort((a, b) => a.order - b.order).map((m) => ({ ...m, icon: m.icon ? markRaw(m.icon) : null }))
})

const activePath = computed(() => route.path)

const activeGroupKey = computed(() => {
  for (const item of menuItems.value) {
    if (item.type === 'group' && item.children.some((c) => c.path === activePath.value)) {
      return item.key
    }
  }
  return undefined
})
</script>

<template>
  <el-menu
    :default-active="activePath"
    :default-openeds="activeGroupKey ? [activeGroupKey] : []"
    :collapse="collapsed"
    background-color="transparent"
    text-color="rgba(255,255,255,0.85)"
    active-text-color="#fff"
    router
    class="side-menu"
    unique-opened
  >
    <!-- 按 order 排序后统一渲染：分组 / 叶子在同一个循环内 -->
    <template v-for="m in menuItems" :key="m.key">
      <el-sub-menu v-if="m.type === 'group'" :index="m.key">
        <template #title>
          <el-icon v-if="m.icon"><component :is="m.icon" /></el-icon>
          <span>{{ m.title }}</span>
        </template>
        <el-menu-item v-for="c in m.children" :key="c.path" :index="c.path">
          <el-icon v-if="c.icon"><component :is="c.icon" /></el-icon>
          <template #title>{{ c.title }}</template>
        </el-menu-item>
      </el-sub-menu>

      <el-menu-item v-else :index="m.path">
        <el-icon v-if="m.icon"><component :is="m.icon" /></el-icon>
        <template #title>{{ m.title }}</template>
      </el-menu-item>
    </template>
  </el-menu>
</template>

<style lang="scss" scoped>
.side-menu {
  border-right: none;
  height: calc(100vh - #{$header-height});
  background: transparent !important;
  --el-menu-bg-color: transparent;
  --el-menu-text-color: rgba(255, 255, 255, 0.85);
  --el-menu-hover-bg-color: rgba(255, 255, 255, 0.08);
  --el-menu-active-color: #fff;

  // ---- 分组标题 ----
  :deep(.el-sub-menu) {
    > .el-sub-menu__title {
      margin: 6px 12px 2px;
      border-radius: 8px;
      height: 44px;
      line-height: 44px;
      padding: 0 12px !important;
      color: rgba(255, 255, 255, 0.92);
      font-weight: 500;

      &:hover {
        background: rgba(255, 255, 255, 0.08) !important;
      }
    }

    // 展开中：浅蓝渐变，与未展开的纯透明形成对比
    &.is-active > .el-sub-menu__title {
      background: linear-gradient(
        90deg,
        rgba(59, 130, 246, 0.32) 0%,
        rgba(59, 130, 246, 0.12) 100%
      ) !important;
      color: #fff;
      font-weight: 600;
    }
  }

  // ---- 子菜单项 ----
  :deep(.el-menu-item) {
    margin: 2px 12px;
    border-radius: 8px;
    height: 38px;
    line-height: 38px;
    min-width: 0;
    font-size: 13px;
    position: relative;

    &:hover {
      background: rgba(255, 255, 255, 0.1) !important;
    }

    // 激活项：实色蓝色背景 + 左侧 3px 高亮条
    &.is-active {
      background: linear-gradient(
        90deg,
        #3b82f6 0%,
        #1e40af 100%
      ) !important;
      color: #fff !important;
      font-weight: 600;
      box-shadow: 0 2px 8px rgba(59, 130, 246, 0.4);

      &::before {
        content: '';
        position: absolute;
        left: -12px;
        top: 6px;
        bottom: 6px;
        width: 3px;
        background: #fff;
        border-radius: 0 2px 2px 0;
      }
    }
  }

  :deep(.el-sub-menu .el-menu-item) {
    margin-left: 12px;
    margin-right: 12px;
    padding-left: 20px !important;
  }

  // 折叠态：只显示图标，隐藏文字、子菜单展开
  &.el-menu--collapse {
    :deep(.el-sub-menu__title) {
      margin: 6px 8px;
      padding: 0 !important;
      justify-content: center;

      span,
      .el-sub-menu__icon-arrow {
        display: none;
      }
    }

    :deep(.el-menu-item) {
      margin: 4px 8px;
      padding-left: 0 !important;
      text-align: center;

      &.is-active::before {
        left: -8px;
      }
    }
  }
}
</style>
