import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:go_router/go_router.dart'; import '../../../../core/theme/app_colors.dart'; import '../../../../core/services/auth_service.dart'; import '../../../../core/services/session_service.dart'; import '../../../../l10n/app_localizations.dart'; class SplashPage extends StatefulWidget { const SplashPage({super.key}); @override State createState() => _SplashPageState(); } class _SplashPageState extends State { @override void initState() { super.initState(); _checkAuthenticationAndNavigate(); } void _checkAuthenticationAndNavigate() async { try { print('DEBUG: Checking authentication state...'); // Always show splash for full 3 seconds for complete animation await Future.delayed(const Duration(seconds: 3)); // Check if user is currently authenticated final currentUser = AuthService.currentUser; if (currentUser != null) { print('DEBUG: User already authenticated: ${currentUser.email}'); print( 'DEBUG: User displayName before reload: ${currentUser.displayName}', ); // Reload user data to get latest information from Firebase await currentUser.reload(); // Get the updated user final updatedUser = AuthService.currentUser; print( 'DEBUG: User displayName after reload: ${updatedUser?.displayName}', ); // Update session with current user if needed await SessionService.updateSessionWithCurrentUser(); // Navigate to dashboard if (mounted) { print('DEBUG: Navigating to student dashboard'); context.go('/student-dashboard'); } return; } // Check if user should be auto-logged in final sessionData = await SessionService.shouldAutoLogin(); if (sessionData['shouldAutoLogin'] == true) { print('DEBUG: Auto-login available for: ${sessionData['email']}'); if (mounted) { // Navigate to login page with pre-filled data print('DEBUG: Navigating to login for auto-login'); context.go('/login'); } } else { print('DEBUG: No auto-login available, going to role selection'); if (mounted) { context.go('/role-selection'); } } } catch (e) { print('DEBUG: Error in authentication check: $e'); // Fallback to role selection if (mounted) { context.go('/role-selection'); } } } @override Widget build(BuildContext context) { return Scaffold( body: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ AppColors.background, AppColors.primaryTeal.withOpacity(0.05), AppColors.primaryOrange.withOpacity(0.03), AppColors.background, ], ), ), child: Stack( children: [ // Animated background particles ...List.generate(25, (index) => _buildParticle(index)), // Main content Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Modern logo with gradient animation Stack( alignment: Alignment.center, children: [ // Outer ring animation Container( width: 160, height: 160, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: AppColors.primaryTeal.withOpacity(0.2), width: 2, ), ), ) .animate() .scale( duration: const Duration(milliseconds: 2000), curve: Curves.easeInOut, begin: const Offset(0.8, 0.8), end: const Offset(1.2, 1.2), ) .then() .scale( duration: const Duration(milliseconds: 2000), curve: Curves.easeInOut, begin: const Offset(1.2, 1.2), end: const Offset(0.8, 0.8), ), // Middle ring animation Container( width: 120, height: 120, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: AppColors.primaryOrange.withOpacity(0.3), width: 3, ), ), ) .animate() .scale( duration: const Duration(milliseconds: 1500), curve: Curves.easeInOut, begin: const Offset(1.0, 1.0), end: const Offset(1.1, 1.1), ) .then() .scale( duration: const Duration(milliseconds: 1500), curve: Curves.easeInOut, begin: const Offset(1.1, 1.1), end: const Offset(1.0, 1.0), ), // Main logo container Container( width: 80, height: 80, decoration: BoxDecoration( gradient: const LinearGradient( colors: [ AppColors.primaryTeal, AppColors.primaryOrange, ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: AppColors.primaryTeal.withOpacity(0.3), blurRadius: 20, offset: const Offset(0, 8), ), BoxShadow( color: AppColors.primaryOrange.withOpacity( 0.2, ), blurRadius: 15, offset: const Offset(0, 4), ), ], ), child: const Icon( Icons.school, size: 40, color: Colors.white, ), ) .animate() .scale( duration: const Duration(milliseconds: 800), curve: Curves.elasticOut, ) .then() .shimmer( duration: const Duration(milliseconds: 2500), color: Colors.white.withOpacity(0.4), ) .then() .rotate( duration: const Duration(milliseconds: 1000), curve: Curves.easeInOut, begin: 0.0, end: 0.05, ) .then() .rotate( duration: const Duration(milliseconds: 1000), curve: Curves.easeInOut, begin: 0.05, end: 0.0, ), ], ), const SizedBox(height: 40), // School name with gradient ShaderMask( shaderCallback: (bounds) => const LinearGradient( colors: [ AppColors.primaryTeal, AppColors.primaryOrange, ], begin: Alignment.centerLeft, end: Alignment.centerRight, ).createShader(bounds), child: Text( AppLocalizations.of(context)!.appTitle, style: Theme.of(context).textTheme.headlineMedium ?.copyWith( color: Colors.white, fontWeight: FontWeight.bold, letterSpacing: 1.2, ), ), ) .animate() .fadeIn( duration: const Duration(milliseconds: 1000), delay: const Duration(milliseconds: 500), ) .slideY( duration: const Duration(milliseconds: 800), delay: const Duration(milliseconds: 500), begin: 0.3, ), const SizedBox(height: 12), // School name subtitle ShaderMask( shaderCallback: (bounds) => LinearGradient( colors: [ AppColors.primaryOrange.withOpacity(0.8), AppColors.primaryTeal.withOpacity(0.8), ], begin: Alignment.centerLeft, end: Alignment.centerRight, ).createShader(bounds), child: Text( AppLocalizations.of(context)!.schoolName, style: Theme.of(context).textTheme.bodyMedium ?.copyWith( color: Colors.white, fontWeight: FontWeight.w500, ), ), ) .animate() .fadeIn( duration: const Duration(milliseconds: 1000), delay: const Duration(milliseconds: 700), ) .slideY( duration: const Duration(milliseconds: 800), delay: const Duration(milliseconds: 700), begin: 0.2, ), const SizedBox(height: 40), // Modern loading indicator Column( children: [ // Loading dots Row( mainAxisSize: MainAxisSize.min, children: [ _buildLoadingDot(0), const SizedBox(width: 8), _buildLoadingDot(1), const SizedBox(width: 8), _buildLoadingDot(2), ], ), const SizedBox(height: 16), // Loading text Text( 'A preparar a sua experiência...', style: Theme.of(context).textTheme.bodySmall ?.copyWith( color: AppColors.primaryOrange, fontWeight: FontWeight.w500, ), ) .animate() .fadeIn( duration: const Duration(milliseconds: 800), delay: const Duration(milliseconds: 1200), ) .then() .shimmer( duration: const Duration(milliseconds: 2000), color: AppColors.primaryTeal.withOpacity(0.3), ), ], ), ], ), ), ], ), ), ); } Widget _buildLoadingDot(int index) { return Container( width: 12, height: 12, decoration: const BoxDecoration( gradient: LinearGradient( colors: [AppColors.primaryTeal, AppColors.primaryOrange], begin: Alignment.topLeft, end: Alignment.bottomRight, ), shape: BoxShape.circle, ), ) .animate() .scale( duration: const Duration(milliseconds: 600), delay: Duration(milliseconds: index * 200), curve: Curves.elasticOut, begin: const Offset(0.0, 0.0), end: const Offset(1.0, 1.0), ) .then() .scale( duration: const Duration(milliseconds: 400), delay: Duration(milliseconds: 800 + index * 200), begin: const Offset(1.0, 1.0), end: const Offset(0.8, 0.8), ) .then() .scale( duration: const Duration(milliseconds: 400), begin: const Offset(0.8, 0.8), end: const Offset(1.0, 1.0), ); } Widget _buildParticle(int index) { final random = index * 137.5; return Positioned( top: (random % 400) + 50, left: (random % 300) + 50, child: Container( width: 2, height: 2, decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColors.primaryTeal.withOpacity(0.3), AppColors.primaryOrange.withOpacity(0.2), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), shape: BoxShape.circle, ), ) .animate() .moveY( duration: Duration(milliseconds: 4000 + (index * 200)), begin: 0.0, end: -200.0, curve: Curves.easeInOut, ) .fadeIn( duration: const Duration(milliseconds: 1000), delay: Duration(milliseconds: index * 150), ) .then() .fadeOut(duration: const Duration(milliseconds: 1000)), ); } }