import 'dart:async'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:user_repository/user_repository.dart'; part 'auth_event.dart'; part 'auth_state.dart'; class AuthBloc extends Bloc { final UserRepository _userRepository; final PhoneVerificationService phoneVerificationService = PhoneVerificationService(); String? _verificationId; AuthBloc({required UserRepository userRepository}) : _userRepository = userRepository, super(AuthStateInitial()) { on(_onAuthEventLoginOAuth); on(_onAuthEventVerifyOAuth); on(_onAuthEventAddEmailAndPassword); on(_updatePassword); on(_linkWithPhoneNumber); on(_linkWithPhoneNumberOtp); } void _onAuthEventLoginOAuth( AuthEventLoginOAuth event, Emitter emit) async { emit(AuthStateProcess()); try { await _userRepository.signInWithPhoneNumber(event.phone); emit(const AuthStateVerifyOAuth(false)); } catch (e) { emit(const AuthStateFailure()); } } void _onAuthEventVerifyOAuth( AuthEventVerifyOAuth event, Emitter emit) async { emit(AuthStateProcess()); try { final bool isVerified = await _userRepository.verifyOTP(event.code); if (isVerified) { emit(AuthStateSuccess()); } else { emit(const AuthStateVerifyOAuth(true)); } } catch (e) { emit(const AuthStateFailure()); } } void _onAuthEventAddEmailAndPassword( AuthEventAddEmailAndPassword event, Emitter emit) async { emit(AuthStateProcess()); try { final String? error = await _userRepository.addEmailAndPassword( event.email, event.password); if (error == null) { emit(AuthStateSuccess()); } else { if (error == 'requires-recent-login') { emit(AuthStateRequiresRecentLogin()); } else if (error == 'email-already-in-use') { emit(AuthStateEmailAlreadyInUse()); } else { emit(const AuthStateFailure()); } } } catch (e) { emit(const AuthStateFailure()); } } void _updatePassword( AuthEventUpdatePassword event, Emitter emit) async { emit(AuthStateProcess()); try { final error = await _userRepository.updatePassword( event.actualPassword, event.password); if (error == null) { emit(AuthStateSuccess()); } else { switch (error) { case UpdatePassworErros.credentialsWrong: emit(const AuthStateFailure(message: "Contrasena incorrecta")); break; case UpdatePassworErros.userNotFound: emit(const AuthStateFailure(message: "Usuario no encontrado")); break; case UpdatePassworErros.unknown: emit(const AuthStateFailure(message: "Error inesperado.")); break; } } } catch (e) { emit(const AuthStateFailure(message: "Error inesperado.")); } } void _linkWithPhoneNumber( LinkWithPhoneNumber event, Emitter emit) async { emit(AuthStateProcess()); try { await for (PhoneAuthEvent event in phoneVerificationService.verifyPhoneNumber(event.phoneNumber)) { switch (event.type) { case PhoneAuthEventType.verificationCompleted: final credential = event.data; print('Verificacion completada. Credencial: $credential'); break; case PhoneAuthEventType.verificationFailed: final exception = event.data; print('Verificacion fallida. Excepcion: $exception'); emit(AuthStateFailure(message: "Error inesperado. $exception")); return; case PhoneAuthEventType.codeAutoRetrievalTimeout: final verificationId = event.data as String; print('Tiempo de espera agotado. ID: $verificationId'); emit(const AuthStateFailure( message: "Tiempo de espera agotado.", )); break; case PhoneAuthEventType.codeSent: final eventData = event.data as Map; final verificationId = eventData['verificationId'] as String; final resendToken = eventData['resendToken'] as int?; print('Codigo enviado. ID: $verificationId, resendToken: $resendToken'); _verificationId = verificationId; emit(const AuthStateVerifyOAuth(false)); break; } } } catch (e) { emit(const AuthStateFailure(message: "Error inesperado.")); } } void _linkWithPhoneNumberOtp( LinkWithPhoneNumberOtp event, Emitter emit) async { emit(AuthStateProcess()); try { final bool isVerified = await _userRepository.linkWithOTP( event.phoneNumber, _verificationId ?? '', event.code); if (isVerified) { emit(AuthStateSuccess()); } else { emit(const AuthStateVerifyOAuth(true)); } } catch (e) { emit(AuthStateFailure(message: "Error inesperado. $e")); } } }