import 'package:dio/dio.dart';

import '../../errors/app_exception.dart';
import '../../errors/auth_exception.dart';
import '../../errors/network_exception.dart';
import '../../errors/parse_exception.dart';
import '../../errors/server_exception.dart';

/// Converts a DioException raised against the Marianum-Connect API into one of
/// the app's typed AppExceptions. Keeps the dio dependency out of call sites
/// that just want to render an error message.
AppException mapMarianumConnectError(DioException error) {
  switch (error.type) {
    case DioExceptionType.connectionTimeout:
    case DioExceptionType.sendTimeout:
    case DioExceptionType.receiveTimeout:
    case DioExceptionType.transformTimeout:
      return NetworkException.timeout(technicalDetails: error.message);
    case DioExceptionType.connectionError:
      return NetworkException(technicalDetails: error.message);
    case DioExceptionType.badCertificate:
      return const NetworkException(
        userMessage:
            'Die sichere Verbindung zum Marianum-Connect-Server wurde abgelehnt.',
      );
    case DioExceptionType.badResponse:
      final status = error.response?.statusCode ?? -1;
      if (status == 401) {
        return AuthException.unauthorized(
          technicalDetails: 'MC 401: ${error.response?.data}',
        );
      }
      if (status == 403) {
        return AuthException.forbidden(
          technicalDetails: 'MC 403: ${error.response?.data}',
        );
      }
      return ServerException(
        statusCode: status,
        technicalDetails: 'MC HTTP $status: ${error.response?.data}',
      );
    case DioExceptionType.cancel:
    case DioExceptionType.unknown:
      final inner = error.error;
      if (inner is FormatException) {
        return ParseException(technicalDetails: inner.message);
      }
      return NetworkException(technicalDetails: error.message);
  }
}
