import 'dart:convert';
import 'package:http/http.dart';

class APIError {
  int errorCode;
  String errorMessage;

  APIError(this.errorCode, this.errorMessage);

  Map<String, dynamic> toJson() => {'errorCode': errorCode, 'errorMessage': errorMessage};

  @override
  String toString() {
    return jsonEncode(this);
  }

  static APIException throwAPIException(Response response) {
    switch (response.statusCode) {
      case 400:
        APIError? apiError;
        if (response.body.isNotEmpty) {
          var jsonError = jsonDecode(response.body);
          apiError = APIError(jsonError['errorCode'], jsonError['errorMessage']);
        }
        return APIException(APIException.badRequest, error: apiError);
      case 401:
        return const APIException(APIException.unauthorized);
      case 403:
        return const APIException(APIException.forbidden);
      case 404:
        return const APIException(APIException.notFound);
      case 500:
        return const APIException(APIException.internalServerError);
      case 444:
        var downloadUrl = response.headers["location"];
        return APIException(APIException.upgradeRequired, arguments: downloadUrl);
      default:
        return const APIException(APIException.other);
    }
  }
}

class APIException implements Exception {
  static const String badRequest = 'api_common_bad_request';
  static const String unauthorized = 'api_common_unauthorized';
  static const String forbidden = 'api_common_forbidden';
  static const String notFound = 'api_common_not_found';
  static const String internalServerError = 'api_common_internal_server_error';
  static const String upgradeRequired = 'api_common_upgrade_required';
  static const String badResponseFormat = 'api_common_bad_response_format';
  static const String other = 'api_common_http_error';
  static const String timeout = 'api_common_http_timeout';
  static const String unknown = 'unexpected_error';

  final String message;
  final APIError? error;
  final dynamic arguments;

  const APIException(this.message, {this.arguments, this.error});

  Map<String, dynamic> toJson() => {'message': message, 'error': error, 'arguments': '$arguments'};

  @override
  String toString() {
    return jsonEncode(this);
  }
}
