import 'package:firebase_auth/firebase_auth.dart'; import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart'; import 'package:travel_mate/services/error_service.dart'; /// Service for handling Firebase authentication operations. /// /// This service provides methods for user authentication including email/password /// sign-in, Google sign-in, Apple sign-in, password reset, and account management. /// It acts as a wrapper around Firebase Auth functionality. class AuthService { /// Error service for logging authentication errors. final _errorService = ErrorService(); /// Firebase Auth instance for authentication operations. final FirebaseAuth firebaseAuth = FirebaseAuth.instance; /// Gets the currently authenticated user. /// /// Returns null if no user is currently signed in. User? get currentUser => firebaseAuth.currentUser; /// Stream that emits authentication state changes. /// /// Emits the current user when authenticated, null when not authenticated. Stream get authStateChanges => firebaseAuth.authStateChanges(); /// Signs in a user with email and password. /// /// Returns a [UserCredential] containing the authenticated user's information. /// Throws [FirebaseAuthException] if authentication fails. Future signInWithEmailAndPassword({ required String email, required String password }) async { return await firebaseAuth.signInWithEmailAndPassword( email: email, password: password); } /// Creates a new user account with email and password. /// /// Returns a [UserCredential] containing the new user's information. /// Throws [FirebaseAuthException] if account creation fails. Future signUpWithEmailAndPassword({ required String email, required String password }) async { return await firebaseAuth.createUserWithEmailAndPassword( email: email, password: password); } /// Signs out the current user. /// /// Clears the authentication state and signs out the user from Firebase. Future signOut() async { await firebaseAuth.signOut(); } /// Sends a password reset email to the specified email address. /// /// The user will receive an email with instructions to reset their password. /// Throws [FirebaseAuthException] if the email is invalid or other errors occur. Future resetPassword(String email) async { await firebaseAuth.sendPasswordResetEmail(email: email); } /// Updates the display name of the current user. /// /// Requires a user to be currently authenticated. /// Throws if no user is signed in. Future updateDisplayName({ required String displayName, }) async { await currentUser!.updateDisplayName(displayName); } /// Deletes the current user's account permanently. /// /// Requires re-authentication with the user's current password for security. /// This operation cannot be undone. /// /// [password] - The user's current password for re-authentication /// [email] - The user's email address for re-authentication Future deleteAccount({ required String password, required String email, }) async { // Re-authenticate the user for security AuthCredential credential = EmailAuthProvider.credential(email: email, password: password); await currentUser!.reauthenticateWithCredential(credential); // Delete the user account permanently await currentUser!.delete(); await firebaseAuth.signOut(); } /// Resets the user's password after re-authentication. /// /// This method allows users to change their password by providing their /// current password for security verification. /// /// [currentPassword] - The user's current password for verification /// [newPassword] - The new password to set /// [email] - The user's email address for re-authentication Future resetPasswordFromCurrentPassword({ required String currentPassword, required String newPassword, required String email, }) async { // Re-authenticate the user for security AuthCredential credential = EmailAuthProvider.credential(email: email, password: currentPassword); await currentUser!.reauthenticateWithCredential(credential); // Update to the new password await currentUser!.updatePassword(newPassword); } /// Ensures Google Sign-In is properly initialized. /// /// This method must be called before attempting Google authentication. Future ensureInitialized(){ return GoogleSignInPlatform.instance.init(const InitParameters()); } /// Signs in a user using Google authentication. /// /// Handles the complete Google Sign-In flow including platform initialization /// and credential exchange with Firebase. /// /// Returns a [UserCredential] containing the authenticated user's information. /// Throws various exceptions if authentication fails. Future signInWithGoogle() async { try { await ensureInitialized(); final AuthenticationResults result = await GoogleSignInPlatform.instance.authenticate(const AuthenticateParameters()); final String? idToken = result.authenticationTokens.idToken; if (idToken == null) { throw FirebaseAuthException( code: 'ERROR_MISSING_GOOGLE_ID_TOKEN', message: 'Missing Google ID Token', ); } else { final OAuthCredential credential = GoogleAuthProvider.credential(idToken: idToken); UserCredential userCredential = await firebaseAuth.signInWithCredential(credential); // Return the UserCredential instead of void return userCredential; } } on GoogleSignInException catch (e) { _errorService.logError('Google Sign-In error: $e', StackTrace.current); rethrow; } on FirebaseAuthException catch (e) { _errorService.logError('Firebase error during Google Sign-In initialization: $e', StackTrace.current); rethrow; } catch (e) { _errorService.logError('Unknown error during Google Sign-In initialization: $e', StackTrace.current); rethrow; } } /// Signs in a user using Apple authentication. /// /// TODO: Implement Apple Sign-In functionality /// This method is currently a placeholder for future Apple authentication support. Future signInWithApple() async { // TODO: Implement Apple sign-in } }