import { defineStore } from 'pinia';
import { cloneDeep, omit } from 'lodash';
import { getMenus, logout, login } from '@/api/user';
import router from '@/router/index';
import asyncRoutes, {
  whiteMenuList,
  devPushMenuList,
} from '@/router/asyncRoutes';
import { getTreeList, local, session, clear } from '@/utils/tool';
import { routesNotMenu } from '@/router/asyncRoutes';

// 路由扁平化
const flatAsyncRoutes = (routes, breadcrumb = []) => {
  const res = [];
  routes.forEach((route) => {
    const tmp = { ...route };
    if (tmp.children) {
      const childrenBreadcrumb = [...breadcrumb];
      childrenBreadcrumb.push(route);
      const tmpRoute = { ...route };
      tmpRoute.meta.breadcrumb = childrenBreadcrumb;
      delete tmpRoute.children;
      res.push(tmpRoute);
      const childrenRoutes = flatAsyncRoutes(tmp.children, childrenBreadcrumb);
      childrenRoutes.map((item) => {
        res.push(item);
      });
    } else {
      const tmpBreadcrumb = [...breadcrumb];
      tmpBreadcrumb.push(tmp);
      tmp.meta.breadcrumb = tmpBreadcrumb;
      res.push(tmp);
    }
  });
  return res;
};

const views = import.meta.glob('../../views/**/**.vue');
const empty = import.meta.glob('../../layout/empty.vue');
const findRoutersItemByName = (name, arr = asyncRoutes, finds = []) => {
  // arr = cloneDeep(arr);
  for (let i = 0; i < arr.length; i++) {
    const item = arr[i];
    //asyncRoutes里，当有非菜单的路由时，其meta里会有bind字段定义，也要考虑进来
    // if (item.name === name || item.meta?.bind === name) {
    if (item.meta.alias === name || item.meta?.bind === name) {
      finds.push(item);
    }
    if (item.children) {
      findRoutersItemByName(name, item.children, finds);
    }
  }
  return finds;
};
// 菜单转换路由
const filterAsyncRouter = (routerMap) => {
  const accessedRouters = [];
  routerMap.forEach((item) => {
    const targets = findRoutersItemByName(item.url);
    if (targets.length) {
      targets.forEach((target) => {
        const route = {
          path: target.path,
          name: target.name,
          // hidden: item.hidden == 1,
          meta: target.meta,
          children: item.children ? filterAsyncRouter(item.children) : null,
          // component: views[`../../views${target.path}/index.vue`],
          component: target.component,
          // redirect: target.redirect || null,
        };
        accessedRouters.push(route);
      });
    }
  });
  return accessedRouters;
};

const useUserStore = defineStore('user', {
  // persist: true,
  persist: {
    storage: sessionStorage,
    paths: ['user'],
  },
  state: () => ({
    routers: undefined,
    user: undefined,
    menus: [],
    curPage: '',
    curPageModule: '',
    headerMenus: [],
    moduleMenus: [],
    finePermissionIds: [],
  }),

  actions: {
    setState(data) {
      this.$patch(data);
    },
    setInfo(data) {
      this.user = data;
    },
    resetUserInfo() {
      this.$reset();
    },
    setCurPage(name) {
      this.curPage = name;
    },
    setCurPageModule(name) {
      this.curPageModule = name;
      let item = this.menus.find((item) => item.name === name);
      // this.moduleMenus = item?.children || [];
      const data = item?.children || [];
      let moduleMenus = [];
      data.forEach((item) => {
        // moduleMenus.push({ ...omit(item, ['children']), disabled: true });
        moduleMenus.push({
          ...omit(item, ['children']),
          disabled: !!item.children,
        });
        if (item.children && item.children.length) {
          item.children.forEach((elem) => {
            moduleMenus.push({ ...elem, disabled: false });
          });
        }
      });
      this.moduleMenus = moduleMenus;
    },
    setHeaderMenus(menus) {
      let newMenus = cloneDeep(menus);
      this.headerMenus = newMenus.map((item) => {
        delete item.children;
        return item;
      });
    },
    setMenu(data) {
      const menus = filterAsyncRouter(getTreeList(data));
      this.menus = menus;
      const routers = flatAsyncRoutes(cloneDeep(menus));
      this.routers = routers;
      routers.map((item) => router.addRoute('Layout', item));
      routesNotMenu.forEach((item) => router.addRoute(item.meta.mount, item));
      if (menus.length) {
        this.setHeaderMenus(menus);
        this.setCurPageModule(menus[0].name);
      }
    },
    setFinePermissionIds(data) {
      let ids = [];
      for (let i = 0; i < data.length; i++) {
        let item = data[i];
        let arr = [
          ...(item.conditions || []),
          ...(item.buttons || []),
          ...(item.lists || []),
          ...(item.links || []),
        ];
        arr.map((v) => {
          ids.push(`${item.url}_${v.type}_${v.url}`);
        });
      }
      this.finePermissionIds = ids.map((item) => String(item));
    },
    requestUserMenu() {
      return new Promise((resolve, reject) => {
        getMenus()
          .then((response) => {
            if (!response) {
              router.push({ name: 'Login' });
              return;
            }
            let allMenus = [
              ...whiteMenuList,
              ...(response.privileges || []),
              ...devPushMenuList,
            ];
            this.setMenu(allMenus);
            this.setFinePermissionIds(allMenus);
            resolve(allMenus);
          })
          .catch((error) => {
            reject(error);
            clear();
            this.resetUserInfo();
            router.push({ name: 'Login' });
          });
      });
    },

    login(form) {
      return new Promise((resolve, reject) => {
        login(form)
          .then((userInfo) => {
            this.setInfo(userInfo);
            resolve();
          })
          .catch((e) => {
            console.log('login error', e);
            reject(e);
          });
      });
    },

    async logout() {
      await logout();
      clear();
      this.resetUserInfo();
      router.push({ name: 'Login' });
    },
  },
});

export default useUserStore;
