/**
 * @description 认证相关状态管理
 * @author yslg  
 * @since 2025-10-07
 */

import { Module } from 'vuex';
import { LoginDomain, SysMenu, SysPermission } from '@/types';
import { authApi } from '@/apis/system/auth';
import router from '@/router';
import { getFirstAccessibleMenuUrl, buildMenuTree } from '@/utils/route-generator';

// State接口定义
export interface AuthState {
  // 用户信息
  loginDomain: LoginDomain | null;
  // 用户Token
  token: string | null;
  // 用户菜单
  menus: SysMenu[];
  // 用户权限
  permissions: SysPermission[];
  // 动态路由是否已加载
  routesLoaded: boolean;
}

// 从localStorage恢复状态的辅助函数
function getStoredState(): Partial<AuthState> {
  try {
    const token = localStorage.getItem('token');
    const loginDomainStr = localStorage.getItem('loginDomain');
    const menusStr = localStorage.getItem('menus');
    const permissionsStr = localStorage.getItem('permissions');
    
    return {
      token: token || null,
      loginDomain: loginDomainStr ? JSON.parse(loginDomainStr) : null,
      menus: menusStr ? JSON.parse(menusStr) : [],
      permissions: permissionsStr ? JSON.parse(permissionsStr) : [],
      routesLoaded: false, // 路由始终需要重新加载
    };
  } catch (error) {
    console.error('从localStorage恢复状态失败:', error);
    return {
      token: null,
      loginDomain: null,
      menus: [],
      permissions: [],
      routesLoaded: false,
    };
  }
}

// 认证模块
const authModule: Module<AuthState, any> = {
  namespaced: true,
  
  state: (): AuthState => {
    // 从localStorage恢复状态
    const storedState = getStoredState();
    return {
      loginDomain: storedState.loginDomain || null,
      token: storedState.token || null,
      menus: storedState.menus || [],
      permissions: storedState.permissions || [],
      routesLoaded: false,
    };
  },

  getters: {
    // 是否已登录
    isAuthenticated: (state): boolean => {
      return !!(state.token && state.loginDomain);
    },
    
    // 获取用户信息
    user: (state) => {
      return state.loginDomain?.user || null;
    },
    
    // 获取用户角色
    userRoles: (state) => {
      return state.loginDomain?.roles || [];
    },
    
    // 检查是否有指定权限
    hasPermission: (state) => (permissionCode: string): boolean => {
      if (!state.permissions || state.permissions.length === 0) {
        return false;
      }
      return state.permissions.some(permission => 
        permission.code === permissionCode
      );
    },
    
    // 检查是否有任意一个权限
    hasAnyPermission: (state, getters) => (permissionCodes: string[]): boolean => {
      return permissionCodes.some(code => getters.hasPermission(code));
    },
    
    // 检查是否有所有权限
    hasAllPermissions: (state, getters) => (permissionCodes: string[]): boolean => {
      return permissionCodes.every(code => getters.hasPermission(code));
    },
    
    // 获取菜单树结构
    menuTree: (state): SysMenu[] => {
      return buildMenuTree(state.menus);
    }
  },

  mutations: {
    // 设置登录信息
    SET_LOGIN_DOMAIN(state, loginDomain: LoginDomain) {
      state.loginDomain = loginDomain;
      state.token = loginDomain.token || null;
      state.menus = loginDomain.menus || [];
      state.permissions = loginDomain.permissions || [];
      
      // 持久化到localStorage
      if (state.token) {
        localStorage.setItem('token', state.token);
      }
      if (loginDomain) {
        localStorage.setItem('loginDomain', JSON.stringify(loginDomain));
      }
      if (state.menus.length > 0) {
        localStorage.setItem('menus', JSON.stringify(state.menus));
      }
      if (state.permissions.length > 0) {
        localStorage.setItem('permissions', JSON.stringify(state.permissions));
      }
    },
    
    // 设置Token
    SET_TOKEN(state, token: string | null) {
      state.token = token;
      if (token) {
        localStorage.setItem('token', token);
      } else {
        localStorage.removeItem('token');
      }
    },
    
    // 设置菜单
    SET_MENUS(state, menus: SysMenu[]) {
      state.menus = menus;
      if (menus.length > 0) {
        localStorage.setItem('menus', JSON.stringify(menus));
      }
    },
    
    // 设置权限
    SET_PERMISSIONS(state, permissions: SysPermission[]) {
      state.permissions = permissions;
      if (permissions.length > 0) {
        localStorage.setItem('permissions', JSON.stringify(permissions));
      }
    },
    
    // 设置路由加载状态
    SET_ROUTES_LOADED(state, loaded: boolean) {
      state.routesLoaded = loaded;
    },
    
    // 清除认证信息
    CLEAR_AUTH(state) {
      state.loginDomain = null;
      state.token = null;
      state.menus = [];
      state.permissions = [];
      state.routesLoaded = false;
      
      // 清除localStorage
      localStorage.removeItem('token');
      localStorage.removeItem('loginDomain');
      localStorage.removeItem('menus');
      localStorage.removeItem('permissions');
    }
  },

  actions: {
    // 登录
    async login({ commit, dispatch, state }, loginParam) {
      try {
        const result = await authApi.login(loginParam);
        if(result.code !== 200) {
          return Promise.reject(result.message);
        }
        const loginDomain = result.data;
        // 保存登录信息
        commit('SET_LOGIN_DOMAIN', loginDomain);
        
        // 生成动态路由
        await dispatch('generateRoutes');
        // 获取第一个可访问的菜单URL，用于登录后跳转
        const firstMenuUrl = getFirstAccessibleMenuUrl(state.menus);
        
        return Promise.resolve({
          loginDomain,
          redirectUrl: firstMenuUrl || '/home' // 如果没有菜单，跳转到首页
        });
      } catch (error) {
        return Promise.reject(error);
      }
    },
    
    // 登出
    async logout({ commit }) {
      try {
        await authApi.logout();
      } catch (error) {
        console.error('登出接口调用失败:', error);
      } finally {
        // 清除认证信息
        commit('CLEAR_AUTH');
        
        // 跳转到登录页（必须在重置路由之前）
        await router.push('/login');
        
        // 重置路由
        resetRouter();
      }
    },
    
    // 恢复登录状态（页面刷新时使用）
    async restoreAuth({ state, commit, dispatch }) {
      try {
        // 如果没有token，无法恢复
        if (!state.token) {
          return false;
        }
        
        // 如果已经有完整的登录信息，直接生成路由
        if (state.loginDomain && state.menus.length > 0) {
          await dispatch('generateRoutes');
          return true;
        }
        
        return true;
      } catch (error) {
        console.error('恢复登录状态失败:', error);
        // 恢复失败，清除认证信息
        commit('CLEAR_AUTH');
        return false;
      }
    },
    
    // 生成动态路由
    async generateRoutes({ state, commit }) {
      try {
        // 如果路由已经加载，避免重复生成
        if (state.routesLoaded) {
          return;
        }
        
        if (!state.menus || state.menus.length === 0) {
          commit('SET_ROUTES_LOADED', true); // 标记为已加载，避免重复尝试
          return;
        }
        
        // 根据菜单生成路由
        const { generateRoutes } = await import('@/utils/route-generator');
        const routes = generateRoutes(state.menus);
        
        // 添加路由到router
        routes.forEach((route: any) => {
          router.addRoute(route);
        });
        
        // 添加404路由（必须在所有动态路由之后）
        // 只有登录后才会添加这个路由，未登录会跳转到登录页
        router.addRoute({
          path: "/:pathMatch(.*)*",
          name: 'NotFoundAfterLogin',
          redirect: "/404",
        });
        
        // 标记路由已加载
        commit('SET_ROUTES_LOADED', true);
        
      } catch (error) {
        console.error('生成动态路由失败:', error);
        throw error;
      }
    },
    
    // 刷新Token
    async refreshToken({ commit }) {
      try {
        const newToken = await authApi.refreshToken();
        commit('SET_TOKEN', newToken);
        return Promise.resolve(newToken);
      } catch (error) {
        // 刷新失败，清除认证信息
        commit('CLEAR_AUTH');
        router.push('/login');
        return Promise.reject(error);
      }
    }
  }
};


/**
 * 重置路由
 */
function resetRouter() {
  // 这里需要根据实际路由配置来重置
  // 由于Vue Router 4没有直接的重置方法，我们需要重新创建router实例
  // 或者记录动态添加的路由并逐个移除
  location.reload(); // 临时方案，后续可以优化
}

export default authModule;
