import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:go_router/go_router.dart'; import '../../../../l10n/app_localizations.dart'; import '../../../../core/services/auth_service.dart'; import '../../../../core/services/session_service.dart'; import '../../../../shared/presentation/widgets/custom_notification.dart'; class LoginPage extends StatefulWidget { final String? selectedRole; const LoginPage({super.key, this.selectedRole}); @override State createState() => _LoginPageState(); } class _LoginPageState extends State { final _formKey = GlobalKey(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); bool _isLoading = false; bool _obscurePassword = true; bool _rememberMe = false; @override void dispose() { _emailController.dispose(); _passwordController.dispose(); super.dispose(); } @override void initState() { super.initState(); _loadSavedSession(); } void _loadSavedSession() async { try { final sessionData = await SessionService.getCurrentSession(); if (sessionData['email'] != null) { setState(() { _emailController.text = sessionData['email']; _rememberMe = sessionData['rememberMe'] ?? false; }); } } catch (e) { print('DEBUG: Error loading saved session: $e'); } } void _handleLogin() async { if (_formKey.currentState!.validate()) { setState(() { _isLoading = true; }); try { // Get email and password from controllers final email = _emailController.text.trim(); final password = _passwordController.text.trim(); print('DEBUG: Iniciando processo de login para: $email'); // Attempt login with Firebase final result = await AuthService.signInWithEmailAndPassword( email: email, password: password, ); print('DEBUG: Login Firebase bem-sucedido'); print( 'DEBUG: Role selecionado na tela anterior: ${widget.selectedRole}', ); // Ler role na Firestore final uid = result?.user?.uid; if (uid == null) throw Exception('Erro ao obter UID'); final actualRole = await AuthService.getUserRole(uid); print('DEBUG: Role real do usuário na Firestore: $actualRole'); // Se não há role selecionado, redirecionar para role-selection final selectedRole = widget.selectedRole; if (selectedRole == null) { await AuthService.signOut(); if (mounted) { setState(() => _isLoading = false); context.go('/role-selection'); } return; } // Validar se o role selecionado corresponde ao role real if (actualRole != null && selectedRole != actualRole) { // Fazer logout imediato antes de mostrar erro await AuthService.signOut(); setState(() { _isLoading = false; }); String errorMessage; if (selectedRole == 'teacher' && actualRole == 'student') { errorMessage = 'Este email está registado como Aluno. Não pode aceder à área de Professores.'; } else if (selectedRole == 'student' && actualRole == 'teacher') { errorMessage = 'Este email está registado como Professor. Não pode aceder à área de Alunos.'; } else { errorMessage = 'O tipo de utilizador selecionado não corresponde ao perfil registado.'; } _showRoleErrorDialog('Acesso Negado', errorMessage); return; } // Save session based on remember me preference await SessionService.saveSession( rememberMe: _rememberMe, email: email, displayName: AuthService.currentUser?.displayName, ); if (mounted) { setState(() { _isLoading = false; }); // Show success message NotificationHelper.showSuccess( context, message: 'Login realizado com sucesso!', ); // Redirecionar baseado no role real if (actualRole == 'teacher') { context.go('/teacher-dashboard'); } else { context.go('/student-dashboard'); } } } catch (e) { print('DEBUG: Erro no login: $e'); if (mounted) { setState(() { _isLoading = false; }); } // Show error message NotificationHelper.showError( context, message: e.toString().replaceAll('Exception: ', ''), ); } } } void _showRoleErrorDialog(String title, String message) { showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return AlertDialog( title: Text( title, style: TextStyle( color: Theme.of(context).colorScheme.onSurface, fontWeight: FontWeight.bold, ), ), content: Text( message, style: TextStyle(color: Theme.of(context).colorScheme.onSurface), ), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); context.go('/role-selection'); }, child: Text( 'Voltar', style: TextStyle(color: Theme.of(context).colorScheme.primary), ), ), ], ); }, ); } @override Widget build(BuildContext context) { return PopScope( canPop: false, onPopInvokedWithResult: (didPop, result) { if (!didPop) { context.go('/role-selection'); } }, child: Scaffold( body: Stack( children: [ // Main content Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Theme.of(context).colorScheme.background, Theme.of(context).colorScheme.primary.withOpacity(0.1), Theme.of(context).colorScheme.secondary.withOpacity(0.05), Theme.of(context).colorScheme.background, ], ), ), child: SafeArea( child: Center( child: SingleChildScrollView( padding: const EdgeInsets.all(24.0), child: Form( key: _formKey, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: 60), // Logo/Title Container( padding: const EdgeInsets.all(20.0), decoration: BoxDecoration( color: Theme.of( context, ).colorScheme.surface.withOpacity(0.9), borderRadius: BorderRadius.circular(16.0), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 10.0, offset: const Offset(0, 4), ), ], ), child: Column( children: [ Text( 'EPVC', style: TextStyle( fontSize: 32, fontWeight: FontWeight.bold, foreground: Paint() ..shader = LinearGradient( colors: [ Theme.of( context, ).colorScheme.primary, Theme.of( context, ).colorScheme.secondary, ], ).createShader( Rect.fromLTWH(0, 0, 200, 20), ), ), ), const SizedBox(height: 8), Text( 'Escola Profissional de Vila do Conde', style: TextStyle( fontSize: 14, color: Theme.of( context, ).colorScheme.onSurface, fontWeight: FontWeight.w500, ), ), ], ), ).animate().fadeIn( duration: const Duration(milliseconds: 800), ), const SizedBox(height: 40), // Login form Container( padding: const EdgeInsets.all(24.0), decoration: BoxDecoration( color: Theme.of( context, ).colorScheme.surface.withOpacity(0.9), borderRadius: BorderRadius.circular(16.0), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 10.0, offset: const Offset(0, 4), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( 'Entrar', style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Theme.of( context, ).colorScheme.onSurface, ), ), const SizedBox(height: 24), // Email field TextFormField( controller: _emailController, keyboardType: TextInputType.emailAddress, style: TextStyle( color: Theme.of( context, ).colorScheme.onSurface, ), decoration: InputDecoration( labelText: 'Email', labelStyle: TextStyle( color: Theme.of( context, ).colorScheme.onSurface, ), hintStyle: TextStyle( color: Theme.of( context, ).colorScheme.onSurfaceVariant, ), prefixIcon: Icon( Icons.email, color: Theme.of( context, ).colorScheme.primary, ), border: InputBorder.none, enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8.0), borderSide: BorderSide( color: Theme.of( context, ).colorScheme.outline.withOpacity(0.5), ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8.0), borderSide: BorderSide( color: Theme.of( context, ).colorScheme.primary, ), ), filled: true, fillColor: Theme.of( context, ).colorScheme.surface, ), validator: (value) { if (value == null || value.isEmpty) { return 'Email é obrigatório'; } if (!value.contains('@')) { return 'Email inválido'; } return null; }, ), const SizedBox(height: 16), // Password field TextFormField( controller: _passwordController, obscureText: _obscurePassword, style: TextStyle( color: Theme.of( context, ).colorScheme.onSurface, ), decoration: InputDecoration( labelText: 'Palavra-passe', labelStyle: TextStyle( color: Theme.of( context, ).colorScheme.onSurface, ), hintStyle: TextStyle( color: Theme.of( context, ).colorScheme.onSurfaceVariant, ), prefixIcon: Icon( Icons.lock, color: Theme.of( context, ).colorScheme.primary, ), suffixIcon: IconButton( icon: Icon( _obscurePassword ? Icons.visibility : Icons.visibility_off, color: Theme.of( context, ).colorScheme.primary, ), onPressed: () { setState(() { _obscurePassword = !_obscurePassword; }); }, ), border: InputBorder.none, enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8.0), borderSide: BorderSide( color: Theme.of( context, ).colorScheme.outline.withOpacity(0.5), ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8.0), borderSide: BorderSide( color: Theme.of( context, ).colorScheme.primary, ), ), filled: true, fillColor: Theme.of( context, ).colorScheme.surface, ), validator: (value) { if (value == null || value.isEmpty) { return 'Palavra-passe é obrigatória'; } if (value.length < 6) { return 'Palavra-passe muito curta'; } return null; }, ), const SizedBox(height: 12), // Remember me checkbox Row( children: [ Checkbox( value: _rememberMe, onChanged: (bool? value) { setState(() { _rememberMe = value ?? false; }); }, activeColor: Theme.of( context, ).colorScheme.primary, checkColor: Colors.white, ), GestureDetector( onTap: () { setState(() { _rememberMe = !_rememberMe; }); }, child: Text( 'Manter sessão iniciada', style: TextStyle( color: Theme.of( context, ).colorScheme.onSurface, fontSize: 14, fontWeight: _rememberMe ? FontWeight.w500 : FontWeight.normal, ), ), ), ], ), const SizedBox(height: 12), // Login button SizedBox( height: 50, child: ElevatedButton( onPressed: _isLoading ? null : _handleLogin, style: ElevatedButton.styleFrom( backgroundColor: Theme.of( context, ).colorScheme.primary, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( 8.0, ), ), elevation: 2, ), child: _isLoading ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( Colors.white, ), ), ) : Text( 'Entrar', style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), ), ), const SizedBox(height: 16), // Signup link GestureDetector( onTap: () { context.go('/signup'); }, child: Text( 'Não tem conta? Criar aqui', style: TextStyle( color: Theme.of( context, ).colorScheme.primary, fontWeight: FontWeight.w500, ), ), ), ], ), ).animate().fadeIn( duration: const Duration(milliseconds: 1000), ), const SizedBox(height: 40), ], ), ), ), ), ), ), // Custom back button Positioned( top: 50, left: 16, child: Container( decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface.withOpacity(0.8), borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Theme.of( context, ).colorScheme.shadow.withOpacity(0.1), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: IconButton( icon: Icon( Icons.arrow_back, color: Theme.of(context).colorScheme.onSurface, ), onPressed: () => context.go('/role-selection'), ), ), ), ], ), ), ); } }