// lib/screens/login.dart import 'dart:async'; // Import for TimeoutException import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; // Keep for potential future use, though not strictly necessary for the new logic import 'package:environment_monitoring_app/services/api_service.dart'; import 'package:environment_monitoring_app/auth_provider.dart'; import 'package:environment_monitoring_app/home_page.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @override State createState() => _LoginScreenState(); } class _LoginScreenState extends State { final _formKey = GlobalKey(); final TextEditingController _emailController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); bool _isLoading = false; String _errorMessage = ''; @override void dispose() { _emailController.dispose(); _passwordController.dispose(); super.dispose(); } Future _login() async { if (!_formKey.currentState!.validate()) { return; } setState(() { _isLoading = true; _errorMessage = ''; }); final auth = Provider.of(context, listen: false); final apiService = Provider.of(context, listen: false); final String email = _emailController.text.trim(); final String password = _passwordController.text.trim(); // --- START: MODIFIED Internet-First Strategy with Improved Fallback --- try { // --- Attempt 1: Online Login --- debugPrint("Login attempt: Trying online authentication..."); final Map result = await apiService .login(email, password) .timeout(const Duration(seconds: 10)); if (result['success'] == true) { // --- Online Success --- final String token = result['data']['token']; final Map profile = result['data']['profile']; await auth.login(token, profile, password); if (auth.isFirstLogin) { await auth.setIsFirstLogin(false); } if (!mounted) return; Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (context) => const HomePage()), ); } else { // --- Online Failure (API Error) --- setState(() { _errorMessage = result['message'] ?? 'Invalid email or password.'; }); _showSnackBar(_errorMessage, isError: true); } } on TimeoutException catch (_) { // --- Online Failure (Timeout) --- debugPrint("Login attempt: Online request timed out after 10 seconds. Triggering offline fallback."); _showSnackBar("Slow connection detected. Trying offline login...", isError: true); await _attemptOfflineLogin(auth, email, password); } catch (e) { // --- Online Failure (Other Network Error, e.g., SocketException) --- debugPrint("Login attempt: Network error ($e). Triggering offline fallback immediately."); _showSnackBar("Connection failed. Trying offline login...", isError: true); // FIX: Removed the unreliable connectivity check. Treat all exceptions here as a reason to try offline. await _attemptOfflineLogin(auth, email, password); } finally { if (mounted) { setState(() { _isLoading = false; }); } } // --- END: MODIFIED Internet-First Strategy --- } /// Helper function to perform offline validation and update UI. Future _attemptOfflineLogin(AuthProvider auth, String email, String password) async { final bool offlineSuccess = await auth.loginOffline(email, password); if (mounted) { if (offlineSuccess) { Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (context) => const HomePage()), ); } else { setState(() { _errorMessage = "Offline login failed. Check credentials or connect to internet to sync."; }); _showSnackBar(_errorMessage, isError: true); } } } void _showSnackBar(String message, {bool isError = false}) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message), backgroundColor: isError ? Theme.of(context).colorScheme.error : null, ), ); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Login'), centerTitle: true, ), body: Center( child: SingleChildScrollView( padding: const EdgeInsets.all(16.0), child: Form( key: _formKey, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "PSTW MMS V4", style: Theme.of(context).textTheme.headlineMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 32), Center( child: Image.asset( 'assets/icon_3_512x512.png', height: 120, width: 120, ), ), const SizedBox(height: 48), TextFormField( controller: _emailController, decoration: const InputDecoration(labelText: "Email"), keyboardType: TextInputType.emailAddress, validator: (val) => val == null || val.isEmpty ? "Enter your email" : null, ), const SizedBox(height: 16), TextFormField( controller: _passwordController, decoration: const InputDecoration(labelText: "Password"), obscureText: true, validator: (val) => val == null || val.length < 6 ? "Minimum 6 characters" : null, ), const SizedBox(height: 24), _isLoading ? const CircularProgressIndicator() : ElevatedButton( onPressed: _login, style: ElevatedButton.styleFrom( minimumSize: const Size(double.infinity, 50), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), ), child: const Text( 'Login', style: TextStyle(fontSize: 18), ), ), if (_errorMessage.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 12), child: Text( _errorMessage, style: TextStyle(color: Theme.of(context).colorScheme.error), textAlign: TextAlign.center, ), ), const SizedBox(height: 15), TextButton( onPressed: () { Navigator.pushNamed(context, '/forgot-password'); }, child: const Text('Forgot Password?'), ), TextButton( onPressed: () { Navigator.pushNamed(context, '/register'); }, child: const Text('Don\'t have an account? Register'), ), ], ), ), ), ), ); } }