import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { JwtService } from '@nestjs/jwt';
import { IS_PUBLIC_KEY } from '../decorators/public.decorator';

@Injectable()
export class JwtAuthGuard implements CanActivate {
  constructor(
    private readonly jwtService: JwtService,
    private readonly reflector: Reflector,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);
    if (isPublic) return true;

    const request = context.switchToHttp().getRequest();
    const token = this.extractTokenFromHeader(request);
    if (!token) throw new UnauthorizedException('缺少认证令牌');

    try {
      const payload = await this.jwtService.verifyAsync(token);
      // 兼容旧 token（无 type 字段）和新 token（type: 'access'）
      if (payload.type && payload.type !== 'access') throw new UnauthorizedException('无效的令牌类型');
      request.user = {
        userId: payload.userId ?? payload.sub,
        accountSequence: payload.accountSequence ?? payload.sub,
        deviceId: payload.deviceId,
      };
    } catch {
      throw new UnauthorizedException('令牌无效或已过期');
    }

    return true;
  }

  private extractTokenFromHeader(request: any): string | undefined {
    const [type, token] = request.headers.authorization?.split(' ') ?? [];
    return type === 'Bearer' ? token : undefined;
  }
}
