/**
 * 管理员鉴权守卫
 * 
 * 功能描述：
 * - 保护后台管理接口的访问权限
 * - 验证Authorization Bearer Token
 * - 确保只有role=9的管理员可以访问
 * 
 * 职责分离：
 * - HTTP请求权限验证
 * - Token解析和验证
 * - 管理员身份确认
 * 
 * 主要方法：
 * - canActivate() - 权限验证核心逻辑
 * 
 * 使用场景：
 * - 后台管理API的权限保护
 * - 管理员身份验证
 * 
 * 最近修改：
 * - 2026-01-08: 注释规范优化 - 为接口添加注释，完善文档说明 (修改者: moyin)
 * - 2026-01-07: 代码规范优化 - 修正文件命名规范，更新作者信息和修改记录
 * - 2026-01-08: 注释规范优化 - 补充方法注释，添加@param、@returns、@throws和@example (修改者: moyin)
 * 
 * @author moyin
 * @version 1.0.3
 * @since 2025-12-19
 * @lastModified 2026-01-08
 */

import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { Request } from 'express';
import { AdminCoreService, AdminAuthPayload } from '../../core/admin_core/admin_core.service';

/**
 * 管理员请求接口
 * 
 * 功能描述：
 * 扩展Express Request接口，添加管理员认证信息
 * 
 * 使用场景：
 * - AdminGuard验证通过后，将管理员信息附加到请求对象
 * - 控制器方法中获取当前管理员信息
 */
export interface AdminRequest extends Request {
  admin?: AdminAuthPayload;
}

@Injectable()
export class AdminGuard implements CanActivate {
  constructor(private readonly adminCoreService: AdminCoreService) {}

  /**
   * 权限验证核心逻辑
   * 
   * 功能描述：
   * 验证HTTP请求的Authorization头，确保只有管理员可以访问
   * 
   * 业务逻辑：
   * 1. 提取Authorization头
   * 2. 验证Bearer Token格式
   * 3. 调用核心服务验证Token
   * 4. 将管理员信息附加到请求对象
   * 
   * @param context 执行上下文，包含HTTP请求信息
   * @returns 是否允许访问，true表示允许
   * 
   * @throws UnauthorizedException 当缺少Authorization头或格式错误时
   * @throws UnauthorizedException 当Token无效或过期时
   * 
   * @example
   * ```typescript
   * // 在控制器方法上使用
   * @UseGuards(AdminGuard)
   * @Get('users')
   * async getUsers() { ... }
   * ```
   */
  canActivate(context: ExecutionContext): boolean {
    const req = context.switchToHttp().getRequest<AdminRequest>();
    const auth = req.headers['authorization'];

    if (!auth || Array.isArray(auth)) {
      throw new UnauthorizedException('缺少Authorization头');
    }

    const [scheme, token] = auth.split(' ');
    if (scheme !== 'Bearer' || !token) {
      throw new UnauthorizedException('Authorization格式错误');
    }

    const payload = this.adminCoreService.verifyToken(token);
    req.admin = payload;
    return true;
  }
}
