import { computed, nextTick, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { useContext } from '@sa/hooks';
import type { RouteKey } from '@elegant-router/types';
import { getObjectContextDomainConfigByPath } from '@/constants/object-context';
import { useRouteStore } from '@/store/modules/route';
import { useObjectContextStore } from '@/store/modules/object-context';
import { useRouterPush } from '@/hooks/common/router';

export const { setupStore: setupMixMenuContext, useStore: useMixMenuContext } = useContext('mix-menu', useMixMenu);

function isMenuMatchedByPath(path: string, menuPath: string) {
  if (!menuPath) {
    return false;
  }

  return path === menuPath || path.startsWith(`${menuPath}/`);
}

function useMixMenu() {
  const route = useRoute();
  const routeStore = useRouteStore();
  const objectContextStore = useObjectContextStore();
  const { selectedKey } = useMenu();

  const activeFirstLevelMenuKey = ref('');

  const allMenus = computed<App.Global.Menu[]>(() => routeStore.menus);

  function setActiveFirstLevelMenuKey(key: string) {
    activeFirstLevelMenuKey.value = key;
  }

  function getActiveFirstLevelMenuKey() {
    const [firstLevelMenuKey = ''] = routeStore.getSelectedMenuKeyPath(selectedKey.value);

    if (firstLevelMenuKey) {
      setActiveFirstLevelMenuKey(firstLevelMenuKey);
      return;
    }

    const fallbackFirstLevelMenuKey =
      allMenus.value.find(menu => isMenuMatchedByPath(route.path, menu.routePath))?.key || '';

    setActiveFirstLevelMenuKey(fallbackFirstLevelMenuKey);
  }

  const firstLevelMenus = computed<App.Global.Menu[]>(() =>
    routeStore.menus.map(menu => {
      const { children: _, ...rest } = menu;

      return rest;
    })
  );

  const childLevelMenus = computed<App.Global.Menu[]>(
    () => routeStore.menus.find(menu => menu.key === activeFirstLevelMenuKey.value)?.children || []
  );

  const currentObjectContextDomain = computed(() => getObjectContextDomainConfigByPath(route.path) || null);

  const headerMenuMode = computed<'global' | 'object-context'>(() =>
    currentObjectContextDomain.value && objectContextStore.hasContext ? 'object-context' : 'global'
  );

  const headerMenus = computed<(App.Global.Menu | App.ObjectContext.Menu)[]>(() => {
    if (headerMenuMode.value === 'object-context') {
      return objectContextStore.contextScopedMenus;
    }

    // 对象型业务域处于入口态时，头部只保留业务域锚点，不继续投影全局子菜单。
    if (currentObjectContextDomain.value) {
      return [];
    }

    return childLevelMenus.value;
  });

  const isActiveFirstLevelMenuHasChildren = computed(() => {
    if (!activeFirstLevelMenuKey.value) {
      return false;
    }

    const findItem = allMenus.value.find(item => item.key === activeFirstLevelMenuKey.value);

    return Boolean(findItem?.children?.length);
  });

  watch(
    [selectedKey, allMenus, () => route.path],
    () => {
      getActiveFirstLevelMenuKey();
    },
    { immediate: true }
  );

  return {
    allMenus,
    firstLevelMenus,
    childLevelMenus,
    headerMenuMode,
    headerMenus,
    currentObjectContextDomain,
    isActiveFirstLevelMenuHasChildren,
    activeFirstLevelMenuKey,
    setActiveFirstLevelMenuKey,
    getActiveFirstLevelMenuKey
  };
}

export function useMenu() {
  const route = useRoute();
  const { routerPushByKeyWithMetaQuery } = useRouterPush();

  const selectedKey = computed(() => {
    const { hideInMenu, activeMenu } = route.meta;
    const name = route.name as string;

    const routeName = (hideInMenu ? activeMenu : name) || name;

    return routeName;
  });

  const selectedKeyDummy = ref(selectedKey.value);

  watch(
    () => selectedKey.value,
    val => {
      selectedKeyDummy.value = val;
    }
  );

  function handleSelect(key: RouteKey) {
    selectedKeyDummy.value = key;

    routerPushByKeyWithMetaQuery(key);

    if (key.endsWith('-link')) {
      nextTick(() => {
        selectedKeyDummy.value = selectedKey.value;
      });
    }
  }

  return {
    selectedKey,
    selectedKeyDummy,
    handleSelect
  };
}
