class AppException implements Exception {
  final String message;
  final String prefix;
  final int? statusCode;
  final dynamic originalError;

  AppException([
    this.message = 'An unknown error occurred.',
    this.prefix = '',
    this.statusCode,
    this.originalError,
  ]);

  @override
  String toString() {
    return '$prefix$message';
  }
}

class FetchDataException extends AppException {
  FetchDataException([String? message, int? statusCode, originalError])
    : super(
        message ?? 'Error During Communication: ',
        'Network Error : ',
        statusCode,
        originalError,
      );
}

class AuthenticationException extends AppException {
  AuthenticationException([String? message, int? statusCode, originalError])
    : super(
        message ?? 'Authentication Failed.',
        'Auth Error : ',
        statusCode,
        originalError,
      );
}

class NetworkConnectionException extends AppException {
  NetworkConnectionException([String? message, originalError])
    : super(
        message ?? 'No internet connection available.',
        'Connection Error : ',
        null,
        originalError,
      );
}

class TimeoutException extends AppException {
  TimeoutException([String? message, originalError])
    : super(
        message ?? 'Request timed out.',
        'Timeout Error : ',
        null,
        originalError,
      );
}

class ServerException extends AppException {
  ServerException([String? message, int? statusCode, originalError])
    : super(
        message ?? 'Server error occurred.',
        'Server Error : ',
        statusCode,
        originalError,
      );
}

class BadRequestException extends AppException {
  BadRequestException([String? message, int? statusCode, originalError])
    : super(
        message ?? 'Bad request.',
        'Bad Request Error : ',
        statusCode,
        originalError,
      );
}

class NotFoundException extends AppException {
  NotFoundException([String? message, int? statusCode, originalError])
    : super(
        message ?? 'Resource not found.',
        'Not Found Error : ',
        statusCode,
        originalError,
      );
}

class ForbiddenException extends AppException {
  ForbiddenException([String? message, int? statusCode, originalError])
    : super(
        message ?? 'Access forbidden.',
        'Forbidden Error : ',
        statusCode,
        originalError,
      );
}

class RateLimitException extends AppException {
  RateLimitException([String? message, int? statusCode, originalError])
    : super(
        message ?? 'Rate limit exceeded.',
        'Rate Limit Error : ',
        statusCode,
        originalError,
      );
}
