/**
 * 路由守卫模块
 * 提供基于权限的路由拦截和未登录自动跳转登录页功能
 */

import { Auth } from '../core/auth';
import { UserInfo } from '../types';

/**
 * 路由守卫选项
 */
export interface RouterGuardOptions {
  /**
   * 是否需要登录
   * @default true
   */
  requiresAuth?: boolean;
  /**
   * 需要的权限列表
   */
  requiredPermissions?: string[];
  /**
   * 需要的角色列表
   */
  requiredRoles?: string[];
  /**
   * 登录后重定向的URL
   */
  redirectUri?: string;
  /**
   * 权限不足时重定向的URL
   */
  unauthorizedRedirectUri?: string;
  /**
   * 是否需要所有权限（true）还是任一权限（false）
   * @default true
   */
  requireAllPermissions?: boolean;
  /**
   * 是否需要所有角色（true）还是任一角色（false）
   * @default true
   */
  requireAllRoles?: boolean;
}

/**
 * 路由守卫检查结果
 */
export interface GuardCheckResult {
  /** 是否允许访问 */
  allowed: boolean;
  /** 拒绝原因 */
  reason?: 'NOT_AUTHENTICATED' | 'INSUFFICIENT_PERMISSIONS' | 'INSUFFICIENT_ROLES';
  /** 详细信息 */
  details?: string;
}

/**
 * Vue路由守卫函数类型
 */
type VueRouteGuard = (to: any, from: any, next: any) => Promise<void>;

/**
 * 路由守卫类
 */
export class RouterGuard {
  private readonly auth: Auth;

  /**
   * 构造函数
   * @param auth 认证实例
   */
  constructor(auth: Auth) {
    if (!auth) {
      throw new Error('Auth instance is required');
    }
    this.auth = auth;
  }

  /**
   * 检查路由权限
   * @param options 路由守卫选项
   * @returns Promise<GuardCheckResult> 权限检查结果
   */
  async check(options: RouterGuardOptions): Promise<GuardCheckResult> {
    const {
      requiresAuth = true,
      requiredPermissions = [],
      requiredRoles = [],
      requireAllPermissions = true,
      requireAllRoles = true
    } = options;

    // 如果不需要认证，直接允许
    if (!requiresAuth) {
      return { allowed: true };
    }

    // 检查是否已认证
    if (!this.auth.isAuthenticated()) {
      // 未认证，触发登录流程
      try {
        await this.auth.login(options.redirectUri);
      } catch (error) {
        console.error('Failed to initiate login:', error);
      }
      return { 
        allowed: false, 
        reason: 'NOT_AUTHENTICATED',
        details: 'User is not authenticated'
      };
    }

    // 检查权限
    if (requiredPermissions.length > 0) {
      const hasPermission = await this.checkPermissions(
        requiredPermissions, 
        requireAllPermissions
      );
      
      if (!hasPermission) {
        this.handleUnauthorizedAccess(options.unauthorizedRedirectUri);
        return { 
          allowed: false, 
          reason: 'INSUFFICIENT_PERMISSIONS',
          details: `Missing required permissions: ${requiredPermissions.join(', ')}`
        };
      }
    }

    // 检查角色
    if (requiredRoles.length > 0) {
      const hasRole = await this.checkRoles(requiredRoles, requireAllRoles);
      
      if (!hasRole) {
        this.handleUnauthorizedAccess(options.unauthorizedRedirectUri);
        return { 
          allowed: false, 
          reason: 'INSUFFICIENT_ROLES',
          details: `Missing required roles: ${requiredRoles.join(', ')}`
        };
      }
    }

    return { allowed: true };
  }

  /**
   * 创建Vue路由守卫
   * @returns Vue路由守卫函数
   */
  createVueGuard(): VueRouteGuard {
    return async (to: any, from: any, next: any) => {
      try {
        // 从路由元信息中获取守卫选项
        const options: RouterGuardOptions = to.meta?.auth || {};
        
        const result = await this.check(options);
        
        if (result.allowed) {
          next();
        } else {
          // 根据拒绝原因决定如何处理
          switch (result.reason) {
            case 'NOT_AUTHENTICATED':
              // 登录已经在check方法中处理
              next(false);
              break;
            case 'INSUFFICIENT_PERMISSIONS':
            case 'INSUFFICIENT_ROLES':
              // 权限不足已经在check方法中处理
              next(false);
              break;
            default:
              next(false);
          }
        }
      } catch (error) {
        console.error('Route guard error:', error);
        next(false);
      }
    };
  }

  /**
   * 检查当前用户是否有权限访问资源
   * @param permissions 需要的权限列表
   * @param requireAll 是否需要所有权限
   * @returns Promise<boolean> 是否拥有权限
   */
  async hasPermission(permissions: string | string[], requireAll: boolean = true): Promise<boolean> {
    if (!permissions) {
      return true;
    }

    const requiredPermissions = Array.isArray(permissions) ? permissions : [permissions];
    
    if (requiredPermissions.length === 0) {
      return true;
    }
    
    // 检查是否已认证
    if (!this.auth.isAuthenticated()) {
      return false;
    }

    // 使用Auth类的内置权限检查方法
    try {
      if (requireAll) {
        return await this.auth.hasAllPermissions(requiredPermissions);
      } else {
        return await this.auth.hasPermission(requiredPermissions);
      }
    } catch (error) {
      console.error('Permission check failed:', error);
      return false;
    }
  }

  /**
   * 检查当前用户是否有指定角色
   * @param roles 需要的角色列表
   * @param requireAll 是否需要所有角色
   * @returns Promise<boolean> 是否拥有角色
   */
  async hasRole(roles: string | string[], requireAll: boolean = true): Promise<boolean> {
    if (!roles) {
      return true;
    }

    const requiredRoles = Array.isArray(roles) ? roles : [roles];
    
    if (requiredRoles.length === 0) {
      return true;
    }
    
    // 检查是否已认证
    if (!this.auth.isAuthenticated()) {
      return false;
    }

    // 使用Auth类的内置角色检查方法
    try {
      if (requireAll) {
        return await this.auth.hasAllRoles(requiredRoles);
      } else {
        return await this.auth.hasRole(requiredRoles);
      }
    } catch (error) {
      console.error('Role check failed:', error);
      return false;
    }
  }

  /**
   * 获取当前用户信息
   * @returns UserInfo | null 用户信息
   */
  async getCurrentUser(): Promise<UserInfo | null> {
    try {
      return await this.auth.getUserInfo();
    } catch (error) {
      console.error('Failed to get user info:', error);
      return null;
    }
  }

  /**
   * 检查权限
   * @private
   */
  private async checkPermissions(permissions: string[], requireAll: boolean): Promise<boolean> {
    try {
      return requireAll 
        ? await this.auth.hasAllPermissions(permissions)
        : await this.auth.hasPermission(permissions);
    } catch (error) {
      console.error('Permission validation failed:', error);
      return false;
    }
  }

  /**
   * 检查角色
   * @private
   */
  private async checkRoles(roles: string[], requireAll: boolean): Promise<boolean> {
    try {
      return requireAll
        ? await this.auth.hasAllRoles(roles)
        : await this.auth.hasRole(roles);
    } catch (error) {
      console.error('Role validation failed:', error);
      return false;
    }
  }

  /**
   * 处理未授权访问
   * @private
   */
  private handleUnauthorizedAccess(redirectUri?: string): void {
    if (redirectUri) {
      try {
        window.location.href = redirectUri;
      } catch (error) {
        console.error('Failed to redirect to unauthorized page:', error);
      }
    }
  }
}
