<template>
  <NMenu
    :options="menus"
    :inverted="inverted"
    :mode="mode"
    :collapsed="getCollapsed"
    :collapsed-width="64"
    :collapsed-icon-size="20"
    :indent="24"
    :expanded-keys="openKeys"
    :value="getSelectedKeys"
    @update:value="clickMenuItem"
    @update:expanded-keys="menuExpanded"
  />
</template>

<script lang="ts" setup>
  import { ref, onMounted, computed, watch, unref } from 'vue';
  import { useRoute, useRouter } from 'vue-router';
  import { useAsyncRouteStore } from '@/store/modules/asyncRoute';
  import { generatorMenu, generatorMenuMix } from '@/utils';
  import { useProjectSettingStore } from '@/store/modules/projectSetting';
  import { useProjectSetting } from '@/hooks/setting/useProjectSetting';

  const props = defineProps({
    mode: {
      // 菜单模式
      type: String as PropType<'vertical' | 'horizontal'>,
      default: 'vertical',
    },
    collapsed: {
      // 侧边栏菜单是否收起
      type: Boolean,
    },
    //位置
    location: {
      type: String,
      default: 'left',
    },
  });

  const emit = defineEmits(['update:collapsed']);

  // 当前路由
  const currentRoute = useRoute();
  const router = useRouter();
  const asyncRouteStore = useAsyncRouteStore();
  const settingStore = useProjectSettingStore();
  const menus = ref<any[]>([]);
  const activeMenu = currentRoute.meta?.activeMenu ?? null;
  const selectedKeys = ref<string>((activeMenu ?? currentRoute.name) as string);
  const headerMenuSelectKey = ref<string>('');

  const { getNavMode } = useProjectSetting();

  const navMode = getNavMode;

  // 获取当前打开的子菜单
  const matched = currentRoute.matched;

  const openKeys = ref<string[]>(
    matched && matched.length ? (matched.map((item) => item.name) as string[]) : [],
  );

  const getCollapsed = computed(() => {
    let location = props.location;
    return location === 'left' ? props.collapsed : false;
  });

  const inverted = computed(() => {
    return ['dark', 'header-dark'].includes(settingStore.navTheme);
  });

  const getSelectedKeys = computed(() => {
    let location = props.location;
    return location === 'left' || (location === 'header' && unref(navMode) === 'horizontal')
      ? unref(selectedKeys)
      : unref(headerMenuSelectKey);
  });

  // 监听分割菜单
  watch(
    () => settingStore.menuSetting.mixMenu,
    () => {
      updateMenu();
      if (props.collapsed) {
        emit('update:collapsed', !props.collapsed);
      }
    },
  );

  // 监听菜单收缩状态
  // watch(
  //   () => props.collapsed,
  //   (newVal) => {
  //   }
  // );

  // 跟随页面路由变化，切换菜单选中状态
  watch(
    () => currentRoute.fullPath,
    () => {
      updateMenu();
      const matched = currentRoute.matched;
      openKeys.value = matched.map((item) => item.name) as string[];
      const activeMenu: string = (currentRoute.meta?.activeMenu as string) || '';
      selectedKeys.value = activeMenu ? (activeMenu as string) : (currentRoute.name as string);
    },
  );

  function updateMenu() {
    if (!settingStore.menuSetting.mixMenu) {
      menus.value = generatorMenu(asyncRouteStore.getMenus);
    } else {
      //混合菜单
      const firstRouteName: string = (currentRoute.matched[0].name as string) || '';
      menus.value = generatorMenuMix(asyncRouteStore.getMenus, firstRouteName, props.location);
      const activeMenu: string = currentRoute?.matched[0].meta?.activeMenu as string;
      headerMenuSelectKey.value = (activeMenu ? activeMenu : firstRouteName) || '';
    }
  }

  // 点击菜单
  function clickMenuItem(key: string) {
    if (/http(s)?:/.test(key)) {
      window.open(key);
    } else {
      router.push({ name: key });
    }
  }

  //展开菜单
  function menuExpanded(keys: string[]) {
    if (!keys) return;
    const latestOpenKey = keys.find((key) => openKeys.value.indexOf(key) === -1);
    const isExistChildren = findChildrenLen(latestOpenKey as string);
    openKeys.value = isExistChildren ? (latestOpenKey ? [latestOpenKey] : []) : keys;
  }

  //查找是否存在子路由
  function findChildrenLen(key: string) {
    if (!key) return false;
    const subRouteChildren: string[] = [];
    for (const { children, key } of unref(menus)) {
      if (children && children.length) {
        subRouteChildren.push(key as string);
      }
    }
    return subRouteChildren.includes(key);
  }

  onMounted(() => {
    updateMenu();
  });
</script>
