import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from "@nestjs/common";
import { AuthService } from "../auth.service";
import type { AuthenticatedRequest } from "../../common/types/user.types";

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private readonly authService: AuthService) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest<AuthenticatedRequest>();
    const token = this.extractTokenFromHeader(request);

    if (!token) {
      throw new UnauthorizedException("No authentication token provided");
    }

    try {
      const sessionData = await this.authService.verifySession(token);

      if (!sessionData) {
        throw new UnauthorizedException("Invalid or expired session");
      }

      // Attach user to request (with type assertion for session data structure)
      const user = sessionData.user as unknown as AuthenticatedRequest["user"];
      if (!user) {
        throw new UnauthorizedException("Invalid user data in session");
      }
      request.user = user;
      request.session = sessionData.session;

      return true;
    } catch (error) {
      // Re-throw if it's already an UnauthorizedException
      if (error instanceof UnauthorizedException) {
        throw error;
      }
      throw new UnauthorizedException("Authentication failed");
    }
  }

  private extractTokenFromHeader(request: AuthenticatedRequest): string | undefined {
    const authHeader = request.headers.authorization;
    if (typeof authHeader !== "string") {
      return undefined;
    }

    const parts = authHeader.split(" ");
    const [type, token] = parts;

    return type === "Bearer" ? token : undefined;
  }
}
