/**
 * Custom Authentication Error class
 * Used for authentication and authorization related errors
 */
export class AuthError extends Error {
  originalError?: any;
  code: string;
  statusCode: number;

  /**
   * Create a new Auth error
   * @param message Error message
   * @param originalError Original error object
   * @param code Error code
   * @param statusCode HTTP status code
   */
  constructor(
    message: string,
    originalError?: any,
    code: string = 'AUTHENTICATION_ERROR',
    statusCode: number = 401
  ) {
    super(message);
    this.name = this.constructor.name;
    this.originalError = originalError;
    this.code = code;
    this.statusCode = statusCode;
    Error.captureStackTrace(this, this.constructor);
  }

  /**
   * Create an Invalid Credentials error
   * @param message Error message
   * @param originalError Original error object
   */
  static invalidCredentials(message: string = 'Invalid credentials', originalError?: any): AuthError {
    return new AuthError(message, originalError, 'INVALID_CREDENTIALS', 401);
  }

  /**
   * Create an Access Denied error
   * @param message Error message
   * @param originalError Original error object
   */
  static accessDenied(message: string = 'Access denied', originalError?: any): AuthError {
    return new AuthError(message, originalError, 'ACCESS_DENIED', 403);
  }

  /**
   * Create an Invalid Token error
   * @param message Error message
   * @param originalError Original error object
   */
  static invalidToken(message: string = 'Invalid token', originalError?: any): AuthError {
    return new AuthError(message, originalError, 'INVALID_TOKEN', 401);
  }

  /**
   * Create an Expired Token error
   * @param message Error message
   * @param originalError Original error object
   */
  static expiredToken(message: string = 'Token expired', originalError?: any): AuthError {
    return new AuthError(message, originalError, 'TOKEN_EXPIRED', 401);
  }

  /**
   * Create a Token Not Found error
   * @param message Error message
   * @param originalError Original error object
   */
  static tokenNotFound(message: string = 'Token not found', originalError?: any): AuthError {
    return new AuthError(message, originalError, 'TOKEN_NOT_FOUND', 401);
  }

  /**
   * Create an Invalid Scope error
   * @param message Error message
   * @param originalError Original error object
   */
  static invalidScope(message: string = 'Invalid token scope', originalError?: any): AuthError {
    return new AuthError(message, originalError, 'INVALID_SCOPE', 403);
  }

  /**
   * Create an OAuth Error
   * @param message Error message
   * @param originalError Original error object
   * @param code Specific OAuth error code
   */
  static oauthError(message: string, originalError?: any, code: string = 'OAUTH_ERROR'): AuthError {
    return new AuthError(message, originalError, code, 401);
  }

  /**
   * Create a Missing Permission error
   * @param message Error message
   * @param originalError Original error object
   */
  static missingPermission(message: string = 'Missing required permission', originalError?: any): AuthError {
    return new AuthError(message, originalError, 'MISSING_PERMISSION', 403);
  }

  /**
   * Get a public-safe version of the error
   * @returns Public error object
   */
  toPublicError(): { message: string; code: string; statusCode: number } {
    return {
      message: this.message,
      code: this.code,
      statusCode: this.statusCode
    };
  }
}
