import 'package:dio/dio.dart'; import '../../../../core/constants/api_constants.dart'; import '../../../../core/errors/exceptions.dart'; import '../../../../core/network/dio_client.dart'; import '../models/auth_response_model.dart'; import '../models/login_dto.dart'; import '../models/register_dto.dart'; import '../models/user_model.dart'; /// Remote data source for authentication operations abstract class AuthRemoteDataSource { /// Login user with email and password Future login(LoginDto loginDto); /// Register new user Future register(RegisterDto registerDto); /// Get current user profile Future getProfile(); /// Refresh access token Future refreshToken(); } /// Implementation of AuthRemoteDataSource class AuthRemoteDataSourceImpl implements AuthRemoteDataSource { final DioClient dioClient; AuthRemoteDataSourceImpl({required this.dioClient}); @override Future login(LoginDto loginDto) async { try { final response = await dioClient.post( ApiConstants.login, data: loginDto.toJson(), ); if (response.statusCode == ApiConstants.statusOk) { return AuthResponseModel.fromJson(response.data); } else { throw ServerException('Login failed with status: ${response.statusCode}'); } } on DioException catch (e) { throw _handleDioError(e); } catch (e) { throw ServerException('Unexpected error during login: $e'); } } @override Future register(RegisterDto registerDto) async { try { final response = await dioClient.post( ApiConstants.register, data: registerDto.toJson(), ); if (response.statusCode == ApiConstants.statusCreated) { return AuthResponseModel.fromJson(response.data); } else { throw ServerException('Registration failed with status: ${response.statusCode}'); } } on DioException catch (e) { throw _handleDioError(e); } catch (e) { throw ServerException('Unexpected error during registration: $e'); } } @override Future getProfile() async { try { final response = await dioClient.get(ApiConstants.profile); if (response.statusCode == ApiConstants.statusOk) { return UserModel.fromJson(response.data); } else { throw ServerException('Get profile failed with status: ${response.statusCode}'); } } on DioException catch (e) { throw _handleDioError(e); } catch (e) { throw ServerException('Unexpected error getting profile: $e'); } } @override Future refreshToken() async { try { final response = await dioClient.post(ApiConstants.refreshToken); if (response.statusCode == ApiConstants.statusOk) { return AuthResponseModel.fromJson(response.data); } else { throw ServerException('Token refresh failed with status: ${response.statusCode}'); } } on DioException catch (e) { throw _handleDioError(e); } catch (e) { throw ServerException('Unexpected error refreshing token: $e'); } } /// Handle Dio errors and convert to custom exceptions Exception _handleDioError(DioException error) { switch (error.type) { case DioExceptionType.connectionTimeout: case DioExceptionType.sendTimeout: case DioExceptionType.receiveTimeout: return NetworkException('Connection timeout. Please check your internet connection.'); case DioExceptionType.badResponse: final statusCode = error.response?.statusCode; final message = error.response?.data?['message'] ?? error.message; switch (statusCode) { case ApiConstants.statusUnauthorized: return InvalidCredentialsException(message ?? 'Invalid email or password'); case ApiConstants.statusForbidden: return UnauthorizedException(message ?? 'Access forbidden'); case ApiConstants.statusNotFound: return NotFoundException(message ?? 'Resource not found'); case ApiConstants.statusUnprocessableEntity: return ValidationException(message ?? 'Validation failed'); case 409: // Conflict return ConflictException(message ?? 'Email already exists'); case ApiConstants.statusTooManyRequests: return ServerException('Too many requests. Please try again later.'); case ApiConstants.statusInternalServerError: case ApiConstants.statusBadGateway: case ApiConstants.statusServiceUnavailable: case ApiConstants.statusGatewayTimeout: return ServerException(message ?? 'Server error. Please try again later.'); default: return ServerException(message ?? 'Unknown error occurred'); } case DioExceptionType.connectionError: return NetworkException('No internet connection. Please check your network.'); case DioExceptionType.badCertificate: return NetworkException('SSL certificate error'); case DioExceptionType.cancel: return NetworkException('Request was cancelled'); default: return ServerException(error.message ?? 'Unknown error occurred'); } } }