import { Injectable, UnauthorizedException, Logger } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { ConfigService } from '@nestjs/config';
import { UsersService } from '../users/users.service';
import { JwtPayload } from './interfaces/jwt-payload.interface';

@Injectable()
export class AuthService {
  private readonly logger = new Logger(AuthService.name);

  constructor(
    private readonly jwtService: JwtService,
    private readonly configService: ConfigService,
    private readonly usersService: UsersService,
  ) {}

  /**
   * Validate a Keycloak token and return the user
   * Always verifies the token signature for security
   */
  async validateKeycloakToken(token: string): Promise<JwtPayload> {
    try {
      const jwtSecret = this.configService.get<string>('JWT_SECRET');

      if (!jwtSecret) {
        this.logger.error('JWT_SECRET is not configured');
        throw new UnauthorizedException('Server configuration error');
      }

      // Always verify the token signature - never just decode
      // This prevents token forgery attacks
      const decoded = this.jwtService.verify(token, {
        secret: jwtSecret,
      });

      if (!decoded || !decoded.sub || !decoded.email) {
        throw new UnauthorizedException('Invalid token payload');
      }

      return decoded;
    } catch (error) {
      if (error instanceof UnauthorizedException) {
        throw error;
      }
      this.logger.error('Token validation failed', error);
      throw new UnauthorizedException('Invalid or expired token');
    }
  }

  /**
   * Create an internal JWT token for a user
   */
  async createToken(userId: string): Promise<string> {
    const user = await this.usersService.findOne(userId);

    const payload: JwtPayload = {
      sub: user.id,
      email: user.email,
      roles: user.roles.map((ur) => ur.role.name),
    };

    return this.jwtService.sign(payload);
  }

  /**
   * Verify an internal JWT token
   */
  async verifyToken(token: string): Promise<JwtPayload> {
    try {
      return this.jwtService.verify(token);
    } catch {
      throw new UnauthorizedException('Invalid or expired token');
    }
  }

  /**
   * Get user from JWT payload
   */
  async getUserFromPayload(payload: JwtPayload) {
    const user = await this.usersService.findOne(payload.sub);
    return user;
  }
}
