import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as jwt from 'jsonwebtoken';
import { AppLoggerService } from 'src/common/services/logger.service';
import { handleKnownErrors } from 'src/common/utils/handle-error.util';
import { ERROR_CODES } from 'src/common/constants/error-string-constants';
import { ZOOM_ENV_KEYS, ZOOM_DEFAULTS } from 'src/common/constants/zoom.constants';
import { ZoomSdkRole } from '../enums/zoom-role.enum';

/**
 * Mints client-side JWTs for the Zoom Meeting/Webinar SDK so frontends can join
 * a meeting. Ports `generateZoomJoinWebJwtToken` from the serverless repo.
 */
@Injectable()
export class ZoomJwtService {
  constructor(
    private readonly configService: ConfigService,
    private readonly logger: AppLoggerService,
  ) {}

  /**
   * @param meetingNumber Zoom meeting/webinar number
   * @param role 1 = host/panelist, 0 = attendee
   * @returns signed SDK JWT (HS256)
   */
  generateJoinToken(meetingNumber: string, role: ZoomSdkRole = ZoomSdkRole.ATTENDEE): string {
    try {
      const sdkKey = this.configService.get<string>(ZOOM_ENV_KEYS.SDK_KEY) ?? '';
      const sdkSecret = this.configService.get<string>(ZOOM_ENV_KEYS.SDK_SECRET) ?? '';

      const iat = Math.floor(Date.now() / 1000) - 30;
      const exp = iat + ZOOM_DEFAULTS.JOIN_TOKEN_TTL_SECONDS;

      const payload = {
        sdkKey,
        appKey: sdkKey,
        mn: meetingNumber,
        role,
        iat,
        exp,
        tokenExp: exp,
      };

      return jwt.sign(payload, sdkSecret, { algorithm: 'HS256' });
    } catch (error: any) {
      this.logger.error('Failed to generate Zoom join token', error?.stack, {
        error: error?.message,
        meetingNumber,
      });
      handleKnownErrors(ERROR_CODES.ZOOM_TOKEN_GENERATION_FAILED, error);
    }
  }
}
