import 'package:firebase_auth/firebase_auth.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'session_service.dart'; /// Service for handling Firebase Authentication class AuthService { static final FirebaseAuth _auth = FirebaseAuth.instance; static final FirebaseFirestore _firestore = FirebaseFirestore.instance; /// Get current user static User? get currentUser { return _auth.currentUser; } /// Criar documento do usuário na Firestore após signup static Future createUserRole( String uid, String role, { String? classId, String? schoolClassId, String? displayName, }) async { try { print('DEBUG: Criando documento users/$uid com role: $role'); final Map data = { 'role': role, 'createdAt': FieldValue.serverTimestamp(), }; if (classId != null && classId.isNotEmpty) { data['classId'] = classId; } if (schoolClassId != null && schoolClassId.isNotEmpty) { data['schoolClassId'] = schoolClassId; } if (displayName != null && displayName.isNotEmpty) { data['displayName'] = displayName; } await _firestore.collection('users').doc(uid).set(data); print('DEBUG: Documento criado com sucesso'); } catch (e) { print('DEBUG: Erro ao criar documento: $e'); throw Exception('Erro ao criar perfil do usuário'); } } /// Criar inscrição do aluno na turma escolhida static Future createEnrollment({ required String studentId, required String classId, required String studentName, }) async { try { print( 'DEBUG: Criando enrollment para student=$studentId, class=$classId', ); final existing = await _firestore .collection('enrollments') .where('studentId', isEqualTo: studentId) .where('classId', isEqualTo: classId) .limit(1) .get(); if (existing.docs.isNotEmpty) { print('DEBUG: Enrollment já existe, ignorando'); return; } await _firestore.collection('enrollments').add({ 'classId': classId, 'studentId': studentId, 'studentName': studentName, 'joinedAt': FieldValue.serverTimestamp(), }); print('DEBUG: Enrollment criado com sucesso'); } catch (e) { print('DEBUG: Erro ao criar enrollment: $e'); throw Exception('Erro ao associar aluno à turma'); } } /// Ler classId do aluno na Firestore static Future getStudentClassId(String uid) async { try { final doc = await _firestore.collection('users').doc(uid).get(); if (doc.exists) { return doc.data()?['classId'] as String?; } return null; } catch (e) { print('DEBUG: Erro ao ler classId: $e'); return null; } } /// Ler role do usuário na Firestore static Future getUserRole(String uid) async { try { print('DEBUG: Lendo documento users/$uid'); final doc = await _firestore.collection('users').doc(uid).get(); if (doc.exists) { final role = doc.data()?['role'] as String?; print('DEBUG: Role encontrado: $role'); return role; } print('DEBUG: Documento não existe'); return null; } catch (e) { print('DEBUG: Erro ao ler documento: $e'); return null; } } /// Get auth state changes stream static Stream get authStateChanges { return _auth.authStateChanges(); } /// Sign up with email and password static Future signUpWithEmailAndPassword({ required String email, required String password, String? displayName, String? role, String? classId, String? schoolClassId, }) async { try { print('DEBUG: Tentando criar conta para email: $email'); print('DEBUG: Password length: ${password.length}'); UserCredential result = await _auth.createUserWithEmailAndPassword( email: email, password: password, ); print('DEBUG: Conta criada com sucesso para: ${result.user?.email}'); print('DEBUG: User ID: ${result.user?.uid}'); print('DEBUG: Email verified: ${result.user?.emailVerified}'); // Update user profile with display name if (displayName != null && displayName.isNotEmpty) { await result.user?.updateDisplayName(displayName); print('DEBUG: Display name atualizado para: $displayName'); } // Criar documento na Firestore com role (e classId se aluno) if (role != null && result.user != null) { await createUserRole( result.user!.uid, role, classId: classId, schoolClassId: schoolClassId, displayName: displayName, ); } // Verificar se o email foi verificado if (result.user != null && !result.user!.emailVerified) { print('DEBUG: Email não verificado, tentando enviar verificação...'); await result.user!.sendEmailVerification(); print('DEBUG: Email de verificação enviado'); } return result; } on FirebaseAuthException catch (e) { print('DEBUG: Erro Firebase ao criar conta: ${e.code} - ${e.message}'); String errorMessage = _getErrorMessage(e.code); print('DEBUG: Mensagem de erro: $errorMessage'); throw Exception(errorMessage); } catch (e) { print('DEBUG: Erro genérico ao criar conta: $e'); throw Exception('Ocorreu um problema. Tente novamente'); } } /// Sign in with email and password static Future signInWithEmailAndPassword({ required String email, required String password, }) async { try { print('DEBUG: Tentando login para email: $email'); print('DEBUG: Password length: ${password.length}'); // Verificar se há usuário atual User? currentUser = _auth.currentUser; print('DEBUG: Usuário atual: ${currentUser?.email}'); UserCredential result = await _auth.signInWithEmailAndPassword( email: email, password: password, ); print('DEBUG: Login realizado com sucesso para: ${result.user?.email}'); print('DEBUG: User ID: ${result.user?.uid}'); print('DEBUG: Email verified: ${result.user?.emailVerified}'); print('DEBUG: Display name: ${result.user?.displayName}'); // Reload user data to ensure we have the latest information await result.user?.reload(); print('DEBUG: User data reloaded'); print('DEBUG: Display name after reload: ${result.user?.displayName}'); return result; } on FirebaseAuthException catch (e) { print('DEBUG: Erro Firebase ao fazer login: ${e.code} - ${e.message}'); String errorMessage = _getErrorMessage(e.code); print('DEBUG: Mensagem de erro: $errorMessage'); throw Exception(errorMessage); } catch (e) { print('DEBUG: Erro genérico ao fazer login: $e'); throw Exception('Ocorreu um problema. Tente novamente'); } } /// Sign out static Future signOut() async { try { print('DEBUG: Tentando fazer logout'); await _auth.signOut(); // Clear saved session await SessionService.clearSession(); print('DEBUG: Logout e limpeza de sessão realizados com sucesso'); } catch (e) { print('DEBUG: Erro ao fazer logout: $e'); } } /// Attempt auto-login with saved credentials static Future attemptAutoLogin() async { try { final sessionData = await SessionService.shouldAutoLogin(); if (sessionData['shouldAutoLogin'] == true) { final email = sessionData['email']; print('DEBUG: Attempting auto-login for: $email'); // Note: For security reasons, we cannot auto-login without password // This method just checks if auto-login is available // The actual login still requires user to enter password return true; } return false; } catch (e) { print('DEBUG: Error in auto-login attempt: $e'); return false; } } /// Get user-friendly error message static String _getErrorMessage(String code) { print('DEBUG: Processando código de erro: $code'); switch (code) { case 'weak-password': return 'A palavra-passe é muito fraca. Use pelo menos 8 caracteres.'; case 'invalid-email': return 'O email fornecido é inválido. Verifique o formato.'; case 'user-disabled': return 'Esta conta foi desativada. Contacte o suporte.'; case 'user-not-found': return 'Nenhum utilizador encontrado com este email. Verifique os dados.'; case 'wrong-password': return 'Palavra-passe incorreta. Tente novamente.'; case 'email-already-in-use': return 'O email inserido já se encontra registrado'; case 'operation-not-allowed': return 'Operação não permitida. Tente novamente.'; case 'invalid-credential': return 'Credenciais inválidos. Verifique email e palavra-passe.'; case 'too-many-requests': return 'Muitas tentativas. Aguarde alguns minutos antes de tentar novamente.'; case 'network-request-failed': return 'Falha de conexão. Verifique sua internet e tente novamente.'; default: return 'Ocorreu um problema. Tente novamente'; } } }