import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:real_estate_mobile/core/network/api_exceptions.dart'; import 'package:real_estate_mobile/features/auth/data/auth_repository.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'; // Auth state enum AuthStatus { initial, loading, success, error } class AuthState { final AuthStatus status; final UserModel? user; final String? errorMessage; final List fieldErrors; final String registeredEmail; const AuthState({ this.status = AuthStatus.initial, this.user, this.errorMessage, this.fieldErrors = const [], this.registeredEmail = '', }); AuthState copyWith({ AuthStatus? status, UserModel? user, String? errorMessage, List? fieldErrors, String? registeredEmail, }) { return AuthState( status: status ?? this.status, user: user ?? this.user, errorMessage: errorMessage, fieldErrors: fieldErrors ?? this.fieldErrors, registeredEmail: registeredEmail ?? this.registeredEmail, ); } String? getFieldError(String fieldName) { final match = fieldErrors.where((e) => e.field == fieldName); if (match.isEmpty) return null; return match.first.errors.isNotEmpty ? match.first.errors.first : null; } } // Auth notifier class AuthNotifier extends StateNotifier { final AuthRepository _repository; AuthNotifier(this._repository) : super(const AuthState()); Future login({ required String email, required String password, }) async { state = state.copyWith( status: AuthStatus.loading, errorMessage: null, fieldErrors: [], ); try { final result = await _repository.login( email: email, password: password, ); if (result['requiresTwoFactor'] == true) { state = state.copyWith( status: AuthStatus.error, errorMessage: '2FA verification required', ); return; } state = state.copyWith( status: AuthStatus.success, user: result['user'] as UserModel, ); } on ApiException catch (e) { state = state.copyWith( status: AuthStatus.error, errorMessage: e.fieldErrors.isNotEmpty ? 'Please fix the errors below' : e.message, fieldErrors: e.fieldErrors, ); } catch (e) { state = state.copyWith( status: AuthStatus.error, errorMessage: 'An unexpected error occurred', ); } } Future register({ required String name, required String email, required String password, required String role, }) async { state = state.copyWith( status: AuthStatus.loading, errorMessage: null, fieldErrors: [], ); // Split name into firstName and lastName final nameParts = name.trim().split(RegExp(r'\s+')); final firstName = nameParts.first; final lastName = nameParts.length > 1 ? nameParts.sublist(1).join(' ') : null; try { final user = await _repository.register( RegisterRequest( email: email, password: password, role: role, firstName: firstName, lastName: lastName, ), ); state = state.copyWith( status: AuthStatus.success, user: user, registeredEmail: email, ); } on ApiException catch (e) { state = state.copyWith( status: AuthStatus.error, errorMessage: e.fieldErrors.isNotEmpty ? 'Please fix the errors below' : e.message, fieldErrors: e.fieldErrors, ); } catch (e) { state = state.copyWith( status: AuthStatus.error, errorMessage: 'An unexpected error occurred', ); } } void reset() { state = const AuthState(); } } // Providers final authRepositoryProvider = Provider((ref) { return AuthRepository(); }); final authProvider = StateNotifierProvider((ref) { return AuthNotifier(ref.watch(authRepositoryProvider)); });