<script setup lang="ts">
import type { MenuOption } from 'naive-ui';

import { createGetRoutes } from '@/plugins/router';

const router = useRouter();

// 响应式断点检测
const isMobile = ref(false);
const isTablet = ref(false);

// 检测屏幕尺寸
const updateScreenSize = () => {
  const width = window.innerWidth;
  const wasMobile = isMobile.value;

  isMobile.value = width < 768;
  isTablet.value = width >= 768 && width < 1024;

  // 当从移动端切换到桌面端时，关闭抽屉并重置折叠状态
  if (wasMobile && !isMobile.value) {
    drawerVisible.value = false;
    collapsed.value = false;
  }
  // 当从桌面端切换到移动端时，关闭抽屉
  else if (!wasMobile && isMobile.value) {
    drawerVisible.value = false;
  }
};

// 侧边栏状态管理
const collapsed = ref(false);
const drawerVisible = ref(false);

// 初始化屏幕尺寸检测
onMounted(() => {
  updateScreenSize();
  window.addEventListener('resize', updateScreenSize);

  // 移动端默认收起侧边栏
  if (isMobile.value) {
    collapsed.value = true;
    drawerVisible.value = false;
  }
});

onUnmounted(() => {
  window.removeEventListener('resize', updateScreenSize);
});

// 菜单项类型定义
type MenuItemWithRoute = MenuOption & {
  routeName?: string;
  parentId?: string;
  originalPath?: string;
};

// 生成菜单项
const menuOptions = computed(() => {
  let flatArray: MenuItemWithRoute[] = createGetRoutes(router)()
    .filter((route) => !route.path.includes('/:'))
    .filter((route) => !route.meta.hidden)
    .map((route) => ({
      key: route.path,
      label: route.meta.title || `${(route.name as string) || route.path}`,
      routeName: route.name as string,
    }));

  flatArray = flatArray.map((item) => {
    const originalPath = item.key as string; // 保存原始路径
    let id = item.key as string;
    if (flatArray.some((item) => (item.key as string).startsWith(`${id}/`))) {
      id = `${id}/index`;
    }
    // 去掉最前面的 /
    id = id.replace(/^\//, '');

    let parentId = id.replace(/\/[^/]+$/, '');
    if (parentId === id) {
      parentId = '_ROOT_';
    }
    return {
      ...item,
      key: id,
      parentId,
      originalPath, // 保存原始路径用于后续映射
    };
  });

  const groupItems: MenuItemWithRoute[] = [];
  for (const flatArrayItem of flatArray) {
    if (!groupItems.some((item) => item.key === flatArrayItem.parentId) && flatArrayItem.parentId !== '_ROOT_') {
      let groupItemParentId = flatArrayItem.parentId!.replace(/\/[^/]+$/, '');
      if (groupItemParentId === flatArrayItem.parentId) groupItemParentId = '_ROOT_';
      groupItems.push({
        key: flatArrayItem.parentId!,
        label: `Group ${flatArrayItem.parentId}`,
        parentId: groupItemParentId,
      });
    }
  }

  const tree = arrayToTree([...flatArray, ...groupItems], {
    id: 'key',
    parentId: 'parentId',
    rootId: '_ROOT_',
  });

  // 递归转换树形结构为 naive-ui menu 格式
  function convertToMenuOptions(tree: MenuItemWithRoute[]): MenuOption[] {
    return tree.map((item) => {
      const menuItem: MenuOption = {
        key: item.key,
        label: item.label,
      };

      if (item.children && item.children.length > 0) {
        menuItem.children = convertToMenuOptions(item.children);
      } else if (item.routeName) {
        // 叶子节点，存储路由映射
        menuRouteMap.set(item.key as string, item.routeName);
        // 同时存储路径到 key 的映射（用于高亮显示）
        if (item.originalPath) {
          pathToKeyMap.set(item.originalPath, item.key as string);
        }
        (menuItem as MenuItemWithRoute).routeName = item.routeName;
      }

      return menuItem;
    });
  }

  // 清空之前的映射
  menuRouteMap.clear();
  pathToKeyMap.clear();
  const result = convertToMenuOptions(tree);

  // 菜单生成后，重新设置当前选中的菜单项
  nextTick(() => {
    const currentPath = router.currentRoute.value.path;
    const menuKey = pathToKeyMap.get(currentPath);
    if (menuKey) {
      selectedKey.value = menuKey;
    } else {
      const pathWithoutSlash = currentPath.replace(/^\//, '');
      selectedKey.value = pathWithoutSlash;
    }
  });

  return result;
});

// 当前选中的菜单项
const selectedKey = ref<string>();

// 存储菜单项与路由名称的映射
const menuRouteMap = new Map<string, string>();

// 存储路由路径与菜单 key 的映射（用于高亮显示）
const pathToKeyMap = new Map<string, string>();

// 处理菜单点击
const handleMenuSelect = (key: string, item: MenuOption) => {
  const routeName = menuRouteMap.get(key) || (item as MenuItemWithRoute).routeName;
  if (routeName) {
    router.push({ name: routeName as never });

    // 移动端点击菜单项后自动收起侧边栏
    if (isMobile.value) {
      drawerVisible.value = false;
    }
  }
};

// 监听路由变化，更新选中的菜单项
watch(
  () => router.currentRoute.value.path,
  (newPath) => {
    // 使用路径到 key 的映射来找到对应的菜单项
    const menuKey = pathToKeyMap.get(newPath);
    if (menuKey) {
      selectedKey.value = menuKey;
    } else {
      // 如果没有找到精确匹配，尝试去掉前面的 / 再匹配
      const pathWithoutSlash = newPath.replace(/^\//, '');
      selectedKey.value = pathWithoutSlash;
    }
  },
  { immediate: true },
);

// 切换侧边栏状态
const toggleSidebar = () => {
  if (isMobile.value) {
    // 移动端使用抽屉模式
    drawerVisible.value = !drawerVisible.value;
  } else {
    // 桌面端使用折叠模式
    collapsed.value = !collapsed.value;
  }
};
</script>

<template>
  <n-layout :has-sider="!isMobile">
    <!-- 移动端抽屉 -->
    <n-drawer
      v-if="isMobile"
      v-model:show="drawerVisible"
      :width="280"
      placement="left"
      :trap-focus="false"
      :block-scroll="false"
    >
      <n-drawer-content title="菜单" :native-scrollbar="false">
        <n-menu :options="menuOptions" :value="selectedKey" @update:value="handleMenuSelect" />
      </n-drawer-content>
    </n-drawer>

    <!-- 桌面端侧边栏 -->
    <n-layout-sider
      v-if="!isMobile"
      :collapsed="collapsed"
      :native-scrollbar="false"
      bordered
      collapse-mode="width"
      :collapsed-width="64"
      :width="240"
      show-trigger
      @collapse="collapsed = true"
      @expand="collapsed = false"
    >
      <n-menu
        :collapsed="collapsed"
        :collapsed-width="64"
        :collapsed-icon-size="22"
        :options="menuOptions"
        :value="selectedKey"
        @update:value="handleMenuSelect"
      />
    </n-layout-sider>

    <n-layout>
      <n-layout-header
        bordered
        :style="{
          height: '64px',
          padding: isMobile ? '0 16px' : '0 24px',
          display: 'flex',
          alignItems: 'center',
        }"
      >
        <n-button
          quaternary
          @click="toggleSidebar"
          :style="{
            marginRight: isMobile ? '8px' : '12px',
            padding: isMobile ? '8px' : '6px',
          }"
          :size="isMobile ? 'medium' : 'small'"
        >
          <template #icon>
            <n-icon :size="isMobile ? 20 : 18">
              <svg viewBox="0 0 24 24">
                <path
                  v-if="!isMobile && collapsed"
                  fill="currentColor"
                  d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"
                />
                <path
                  v-else-if="!isMobile && !collapsed"
                  fill="currentColor"
                  d="M3 18h13v-2H3v2zm0-5h10v-2H3v2zm0-7v2h13V6H3zm18 9.59L17.42 12 21 8.41 19.59 7l-5 5 5 5L21 15.59z"
                />
                <!-- 移动端始终显示菜单图标 -->
                <path v-else fill="currentColor" d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" />
              </svg>
            </n-icon>
          </template>
        </n-button>
        <span
          :style="{
            fontSize: isMobile ? '16px' : '18px',
            fontWeight: '500',
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            whiteSpace: 'nowrap',
          }"
        >
          Vue TS Example
        </span>
      </n-layout-header>

      <n-layout-content
        :content-style="{
          padding: isMobile ? '16px' : '24px',
          minHeight: 'calc(100vh - 64px - 72px)', // 减去头部和底部高度
        }"
      >
        <router-view />
      </n-layout-content>

      <n-layout-footer
        bordered
        :style="{
          padding: isMobile ? '16px' : '24px',
          textAlign: 'center',
        }"
      >
        <span
          :style="{
            color: 'var(--n-text-color-disabled)',
            fontSize: isMobile ? '12px' : '14px',
          }"
        >
          © 2025 Vue TS Example. All rights reserved.
        </span>
      </n-layout-footer>
    </n-layout>
  </n-layout>
</template>
