<template>
  <n-menu
    ref="menu"
    class="side-menu"
    accordion
    :indent="18"
    :collapsed-icon-size="22"
    :collapsed-width="64"
    :options="menuOptions"
    :value="activeKey"
    @update:value="handleMenuSelect"
  />
</template>

<script setup>
import { usePermissionStore } from '@/store'
import { renderCustomIcon, renderIcon, isExternal } from '@/utils'

const router = useRouter()
const curRoute = useRoute()
const permissionStore = usePermissionStore()

const activeKey = computed(() => curRoute.meta?.activeMenu || curRoute.name)

const menuOptions = computed(() => {
  return permissionStore.menus.map((item) => getMenuItem(item)).sort((a, b) => a.order - b.order)
})

const menu = ref(null)
watch(curRoute, async () => {
  await nextTick()
  menu.value?.showOption()
})

function resolvePath(basePath, path) {
  if (isExternal(path)) return path
  return (
    '/' +
    [basePath, path]
      .filter((path) => !!path && path !== '/')
      .map((path) => path.replace(/(^\/)|(\/$)/g, ''))
      .join('/')
  )
}

function getMenuItem(route, basePath = '') {
  let menuItem = {
    label: (route.meta && route.meta.title) || route.name,
    key: route.name,
    path: resolvePath(basePath, route.path),
    icon: getIcon(route.meta),
    order: route.meta?.order || 0,
  }

  const visibleChildren = route.children
    ? route.children.filter((item) => item.name && !item.isHidden)
    : []

  if (!visibleChildren.length) return menuItem

  if (visibleChildren.length === 1) {
    // 单个子路由处理
    const singleRoute = visibleChildren[0]
    menuItem = {
      ...menuItem,
      label: singleRoute.meta?.title || singleRoute.name,
      key: singleRoute.name,
      path: resolvePath(menuItem.path, singleRoute.path),
      icon: getIcon(singleRoute.meta),
    }
    const visibleItems = singleRoute.children
      ? singleRoute.children.filter((item) => item.name && !item.isHidden)
      : []

    if (visibleItems.length === 1) {
      menuItem = getMenuItem(visibleItems[0], menuItem.path)
    } else if (visibleItems.length > 1) {
      menuItem.children = visibleItems
        .map((item) => getMenuItem(item, menuItem.path))
        .sort((a, b) => a.order - b.order)
    }
  } else {
    menuItem.children = visibleChildren
      .map((item) => getMenuItem(item, menuItem.path))
      .sort((a, b) => a.order - b.order)
  }
  return menuItem
}

function getIcon(meta) {
  if (meta?.customIcon) return renderCustomIcon(meta.customIcon, { size: 18 })
  if (meta?.icon) return renderIcon(meta.icon, { size: 18 })
  return null
}

function handleMenuSelect(key, item) {
  if (isExternal(item.path)) {
    window.open(item.path)
  } else {
    router.push(item.path)
  }
}
</script>

<style scoped lang="scss">
.side-menu {
  flex: 1;
  background: transparent !important;

  :deep(.n-menu-item-content),
  :deep(.n-submenu-children .n-menu-item-content),
  :deep(.n-submenu-header) {
    margin: 3px 0;
    border-radius: 12px;
  }

  :deep(.n-menu-item-content) {
    padding-left: 10px !important;
    padding-right: 10px !important;
  }

  :deep(.n-menu-item-content::before),
  :deep(.n-submenu-children .n-menu-item-content::before),
  :deep(.n-submenu-header::before) {
    left: 0 !important;
    right: 0 !important;
    border-radius: 12px;
  }

  :deep(.n-menu-item-content-header),
  :deep(.n-menu-item-content__icon),
  :deep(.n-menu-item-content__arrow),
  :deep(.n-menu-item-content__icon svg),
  :deep(.n-submenu-header),
  :deep(.n-submenu-header .n-menu-item-content-header),
  :deep(.n-submenu-header .n-menu-item-content__icon),
  :deep(.n-submenu-header .n-menu-item-content__arrow),
  :deep(.n-submenu-header .n-icon) {
    color: #334155 !important;
  }

  :deep(.n-menu-item-content--selected),
  :deep(.n-menu-item-content:hover),
  :deep(.n-submenu-header:hover),
  :deep(.n-submenu.n-submenu--child-active > .n-submenu-header) {
    background: #eef4fb;
  }

  :deep(.n-menu-item-content--selected) {
    box-shadow: inset 0 0 0 1px rgba(59, 130, 246, 0.18);
  }

  :deep(.n-menu-item-content--selected .n-menu-item-content-header),
  :deep(.n-menu-item-content--selected .n-menu-item-content__icon),
  :deep(.n-menu-item-content--selected .n-menu-item-content__icon svg),
  :deep(.n-submenu.n-submenu--child-active > .n-submenu-header),
  :deep(.n-submenu.n-submenu--child-active > .n-submenu-header .n-menu-item-content-header),
  :deep(.n-submenu.n-submenu--child-active > .n-submenu-header .n-menu-item-content__icon),
  :deep(.n-submenu.n-submenu--child-active > .n-submenu-header .n-icon) {
    color: #0f172a !important;
  }
}

.side-menu:not(.n-menu--collapsed) {
  :deep(.n-menu-item-content) {
    &::before {
      left: 0;
      right: 0;
    }
    &.n-menu-item-content--selected,
    &:hover {
      &::before {
        border-left: 3px solid #3b82f6;
      }
    }
  }

  :deep(.n-submenu-header) {
    padding-left: 10px !important;
    padding-right: 10px !important;
  }
}
</style>
