import 'package:dio/dio.dart'; import 'package:real_estate_mobile/core/constants/api_constants.dart'; import 'package:real_estate_mobile/core/network/api_client.dart'; import 'package:real_estate_mobile/core/network/api_exceptions.dart'; import 'package:real_estate_mobile/core/storage/secure_storage.dart'; import 'package:real_estate_mobile/features/auth/data/models/auth_response.dart'; import 'package:real_estate_mobile/features/auth/data/models/register_request.dart'; import 'package:real_estate_mobile/features/auth/data/models/user_model.dart'; class AuthRepository { final Dio _dio = ApiClient.instance.dio; Future> login({ required String email, required String password, }) async { try { final response = await _dio.post( ApiConstants.authLogin, data: {'email': email, 'password': password}, ); final data = response.data['data'] as Map; // Check if 2FA is required if (data['requiresTwoFactor'] == true) { return { 'requiresTwoFactor': true, 'tempToken': data['tempToken'], }; } final authResponse = AuthResponse.fromJson(data); await SecureStorage.saveTokens( accessToken: authResponse.accessToken, refreshToken: authResponse.refreshToken, ); return { 'requiresTwoFactor': false, 'user': authResponse.user, }; } on DioException catch (e) { if (e.error is ApiException) { throw e.error as ApiException; } throw ApiException( message: e.message ?? 'Login failed', statusCode: e.response?.statusCode, ); } } /// Verify 2FA TOTP token during login Future verifyTwoFactor({ required String tempToken, required String token, }) async { try { final response = await _dio.post( ApiConstants.twoFactorVerify, data: {'tempToken': tempToken, 'token': token}, ); final data = response.data['data'] as Map; final authResponse = AuthResponse.fromJson(data); await SecureStorage.saveTokens( accessToken: authResponse.accessToken, refreshToken: authResponse.refreshToken, ); return authResponse; } on DioException catch (e) { if (e.error is ApiException) throw e.error as ApiException; throw ApiException( message: e.message ?? '2FA verification failed', statusCode: e.response?.statusCode, ); } } /// Verify backup code during login Future verifyBackupCode({ required String tempToken, required String backupCode, }) async { try { final response = await _dio.post( ApiConstants.twoFactorVerifyBackup, data: {'tempToken': tempToken, 'backupCode': backupCode}, ); final data = response.data['data'] as Map; final authResponse = AuthResponse.fromJson(data); await SecureStorage.saveTokens( accessToken: authResponse.accessToken, refreshToken: authResponse.refreshToken, ); return authResponse; } on DioException catch (e) { if (e.error is ApiException) throw e.error as ApiException; throw ApiException( message: e.message ?? 'Backup code verification failed', statusCode: e.response?.statusCode, ); } } Future getMe() async { try { final response = await _dio.get(ApiConstants.authMe); final data = response.data['data'] as Map; return UserModel.fromJson(data); } on DioException catch (e) { if (e.error is ApiException) { throw e.error as ApiException; } throw ApiException( message: e.message ?? 'Failed to fetch user', statusCode: e.response?.statusCode, ); } } Future logout() async { try { await _dio.post(ApiConstants.authLogout); } catch (_) { // Ignore logout API errors — still clear local tokens } finally { await SecureStorage.clearTokens(); } } /// Social auth (Google, Facebook, etc.) — calls POST /auth/social Future socialAuth({ required String provider, required String providerId, required String email, String? name, String? avatar, }) async { try { final response = await _dio.post( ApiConstants.authSocial, data: { 'provider': provider, 'providerId': providerId, 'email': email, if (name != null) 'name': name, if (avatar != null) 'avatar': avatar, }, ); final data = response.data['data'] as Map; final authResponse = AuthResponse.fromJson(data); await SecureStorage.saveTokens( accessToken: authResponse.accessToken, refreshToken: authResponse.refreshToken, ); return authResponse.user; } on DioException catch (e) { if (e.error is ApiException) throw e.error as ApiException; throw ApiException( message: e.message ?? 'Social login failed', statusCode: e.response?.statusCode, ); } } /// Register returns { message, user } — no tokens. /// The user must verify their email before logging in. Future> register(RegisterRequest request) async { try { final response = await _dio.post( ApiConstants.authRegister, data: request.toJson(), ); final data = response.data['data'] as Map; return data; } on DioException catch (e) { if (e.error is ApiException) { throw e.error as ApiException; } throw ApiException( message: e.message ?? 'Registration failed', statusCode: e.response?.statusCode, ); } } }