import type {
  ComponentRecordType,
  GenerateMenuAndRoutesOptions,
} from '@easyflow/types';

import { generateAccessible } from '@easyflow/access';
import { loadMissingIconCollections } from '@easyflow/icons';
import { preferences } from '@easyflow/preferences';

import { ElMessage } from 'element-plus';

import { getAllMenusApi } from '#/api';
import { BasicLayout, IFrameView } from '#/layouts';
import { $t } from '#/locales';

import { disableUnsafeMenuRouteCaching } from './route-cache-safety';

const forbiddenComponent = () => import('#/views/_core/fallback/forbidden.vue');

function collectMenuIcons(routes: unknown[]): string[] {
  const icons: string[] = [];
  routes.forEach((item) => {
    if (!item || typeof item !== 'object') {
      return;
    }
    const route = item as Record<string, unknown>;
    const meta =
      route.meta && typeof route.meta === 'object'
        ? (route.meta as Record<string, unknown>)
        : undefined;
    [route.icon, route.activeIcon, meta?.icon, meta?.activeIcon].forEach(
      (icon) => {
        if (typeof icon === 'string') {
          icons.push(icon);
        }
      },
    );
    if (Array.isArray(route.children)) {
      icons.push(...collectMenuIcons(route.children));
    }
  });
  return icons;
}

async function loadMenuIcons(iconNames: string[]) {
  await Promise.all([
    loadMissingIconCollections(iconNames),
    iconNames.some((icon) => icon.startsWith('svg:'))
      ? import('@easyflow/icons/svg')
      : Promise.resolve(),
  ]);
}

async function generateAccess(options: GenerateMenuAndRoutesOptions) {
  const pageMap: ComponentRecordType = import.meta.glob('../views/**/*.vue');

  const layoutMap: ComponentRecordType = {
    BasicLayout,
    IFrameView,
  };

  return await generateAccessible(preferences.app.accessMode ?? 'frontend', {
    ...options,
    fetchMenuListAsync: async () => {
      ElMessage({
        duration: 1500,
        message: `${$t('common.loadingMenu')}...`,
      });
      const menuRoutes = await getAllMenusApi();
      await loadMenuIcons(collectMenuIcons(menuRoutes));
      return disableUnsafeMenuRouteCaching(menuRoutes);
    },
    // 可以指定没有权限跳转403页面
    forbiddenComponent,
    // 如果 route.meta.menuVisibleWithForbidden = true
    layoutMap,
    pageMap,
  });
}

export { generateAccess };
