import type { AppRouteRecordRaw, Menu } from '@/mainApp/router/types';

import { useI18n } from '@/global/hooks/web/useI18n';
import { transformRouteToMenu } from '@/mainApp/router/helper/menuHelper';
import { flatMultiLevelRoutes } from '@/mainApp/router/helper/routeHelper';
import { store } from '@/global/store';
import { defineStore } from 'pinia';
import { useUserStore } from './user';

import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '@/mainApp/router/routes/basic';

import { ikTree } from 'iking-utils';

import { getMenuList } from '../../../mainApp/api/sys-default/menu';

import { MenuBtnEnum, MenuStorageEnum } from '@/global/enums/menuEnum';
import { PageEnum } from '@/global/enums/pageEnum';
import { useMessage } from '@/global/hooks/web/useMessage';
import localforage from 'localforage';
interface PermissionState {
  // Permission code list
  permCodeList: string[] | number[];
  // Whether the route has been dynamically added
  isDynamicAddedRoute: boolean;
  // To trigger a menu update
  lastBuildMenuTime: number;
  systemMenuList: Menu[];
  systemMenuTree: Menu[];
  notSuperMenuList: Menu[] | null;
}
export const usePermissionStore = defineStore({
  id: 'app-permission',
  state: (): PermissionState => ({
    permCodeList: [],
    // Whether the route has been dynamically added
    isDynamicAddedRoute: false,
    // To trigger a menu update
    lastBuildMenuTime: 0,
    systemMenuList: [],
    systemMenuTree: [],
    notSuperMenuList: null,
  }),
  getters: {
    getPermCodeList(): string[] | number[] {
      return this.permCodeList;
    },
    getsystemMenuList(): Menu[] {
      return this.systemMenuList;
    },
    getsystemMenuTree(): Menu[] {
      return this.systemMenuTree;
    },
    getLastBuildMenuTime(): number {
      return this.lastBuildMenuTime;
    },
    getIsDynamicAddedRoute(): boolean {
      return this.isDynamicAddedRoute;
    },
    getNotSuperMenuList(): Menu[] {
      return this.notSuperMenuList || [];
    },
  },
  actions: {
    setPermCodeList(codeList: string[]) {
      this.permCodeList = codeList;
    },

    setNotSuperMenuList(list: Menu[]) {
      this.notSuperMenuList = list;
    },

    setsystemMenuList(list: Menu[]) {
      this.systemMenuList = list;
      // list?.length > 0 && this.setLastBuildMenuTime();
    },

    setsystemMenuTree(list: Menu[]) {
      this.systemMenuTree = list;
      list?.length > 0 && this.setLastBuildMenuTime();
    },

    setLastBuildMenuTime() {
      this.lastBuildMenuTime = new Date().getTime();
    },

    setDynamicAddedRoute(added: boolean) {
      this.isDynamicAddedRoute = added;
    },
    resetState(): void {
      this.isDynamicAddedRoute = false;
      this.permCodeList = [];
      this.systemMenuList = [];
      this.lastBuildMenuTime = 0;
    },
    async buildRoutesAction(): Promise<AppRouteRecordRaw[]> {
      const { t } = useI18n();
      const userStore = useUserStore();
      let routes: AppRouteRecordRaw[] = [];

      const routeRemoveIgnoreFilter = (route: AppRouteRecordRaw) => {
        const { meta } = route;
        const { ignoreRoute } = meta || {};
        return !ignoreRoute;
      };

      /**
       * @description 根据设置的首页path，修正routes中的affix标记（固定首页）
       * */
      const patchHomeAffix = (routes: AppRouteRecordRaw[]) => {
        if (!routes || routes.length === 0) return;
        let homePath: string = userStore.getUserInfo.homePath || PageEnum.BASE_HOME;
        function patcher(routes: AppRouteRecordRaw[], parentPath = '') {
          if (parentPath) parentPath = parentPath + '/';
          routes.forEach((route: AppRouteRecordRaw) => {
            const { path, children, redirect } = route;
            const currentPath = path.startsWith('/') ? path : parentPath + path;
            if (currentPath === homePath) {
              if (redirect) {
                homePath = route.redirect! as string;
              } else {
                route.meta = Object.assign({}, route.meta, { affix: true });
                throw new Error('end');
              }
            }
            children && children.length > 0 && patcher(children, currentPath);
          });
        }
        try {
          patcher(routes);
        } catch (e) {
          // 已处理完毕跳出循环
        }
        return;
      };
      const { createMessage } = useMessage();
      createMessage.loading({
        content: t('sys.app.menuLoading'),
        duration: 1,
      });

      // !Simulate to obtain permission codes from the background,
      // this function may only need to be executed once, and the actual project can be put at the right time by itself
      let routeList: AppRouteRecordRaw[] = [];
      try {
        const res = await getMenuList();
        if (res.data) {
          res.data.forEach((item: any) => {
            item.path = item.link;
          });
          localforage.setItem(MenuStorageEnum.ALL, res.data);
          routeList = res.data.filter((item: any) => {
            item.meta ??= {
              title: item.name,
              affix: item.affix || false,
            };
            return item.menuType === MenuBtnEnum.MENU;
          });
          localforage.setItem(MenuStorageEnum.MENU, routeList);
          localforage.setItem(
            MenuStorageEnum.BUTTON,
            res.data.filter((item: any) => item.menuType === MenuBtnEnum.PAGE_BUTTON),
          );
        }
      } catch (error) {
        console.error(error);
      }

      const systemMenuList = transformRouteToMenu(routeList);
      this.setsystemMenuTree(ikTree.listToTree(routeList, { needSort: true }) as Menu[]);
      this.setsystemMenuList(
        ikTree.treeToList(ikTree.listToTree(systemMenuList, { needSort: true }) as Menu[]),
      );

      // remove meta.ignoreRoute item
      routeList = ikTree.filter(routeList, routeRemoveIgnoreFilter);
      routeList = routeList.filter(routeRemoveIgnoreFilter);

      routeList = flatMultiLevelRoutes(routeList);
      routes = [PAGE_NOT_FOUND_ROUTE, ...routeList];
      // break;
      // }
      routes.push(ERROR_LOG_ROUTE);
      patchHomeAffix(routes);
      return routes;
    },
  },
});

// Need to be used outside the setup
export function usePermissionStoreWithOut() {
  return usePermissionStore(store);
}
