import 'dart:io'; import 'package:english_learning/core/services/repositories/user_repository.dart'; import 'package:flutter/material.dart'; import 'package:jwt_decoder/jwt_decoder.dart'; class UserProvider with ChangeNotifier { final UserRepository _userRepository = UserRepository(); bool _isLoggedIn = false; String? _jwtToken; Map? _userData; File? _selectedImage; bool get isLoggedIn => _isLoggedIn; String? get jwtToken => _jwtToken; Map? get userData => _userData; File? get selectedImage => _selectedImage; UserProvider() { _loadLoginStatus(); } Future _loadLoginStatus() async { try { _jwtToken = await _userRepository.getToken(); if (_jwtToken != null) { if (JwtDecoder.isExpired(_jwtToken!)) { await logout(); } else { _isLoggedIn = true; await _loadUserData(); } } } catch (e) { print('Error loading login status: $e'); } notifyListeners(); } Future _loadUserData() async { _userData = await _userRepository.getUserData(); if (_userData == null) { await refreshUserData(); } } Future refreshUserData() async { try { if (_jwtToken != null) { final response = await _userRepository.getMe(_jwtToken!); if (response.statusCode == 200) { _userData = response.data['payload']; // Save all user data securely await _userRepository.saveUserData(_userData!); notifyListeners(); } } } catch (e) { print('Error refreshing user data: $e'); } } Future login({required String email, required String password}) async { try { final response = await _userRepository.loginUser({ 'EMAIL': email, 'PASSWORD': password, }); if (response.statusCode == 200 && response.data['payload']['TOKEN'] != null) { String token = response.data['payload']['TOKEN']; String refreshToken = response.data['payload']['REFRESH_TOKEN']; if (token.startsWith('Bearer ')) { token = token.substring(7); } _jwtToken = token; await _userRepository.saveToken(_jwtToken!); await _userRepository.saveRefreshToken(refreshToken); _isLoggedIn = true; await refreshUserData(); return true; } return false; } catch (e) { print('Login error: $e'); return false; } } Future register({ required String name, required String email, required String nisn, required String password, required String confirmPassword, }) async { try { final response = await _userRepository.registerUser({ "NAME_USERS": name, "EMAIL": email, "NISN": nisn, "PASSWORD": password, "CONFIRM_PASSWORD": confirmPassword, }); if (response.statusCode == 200) { return true; } return false; } catch (e) { print('Registration error: $e'); return false; } } Future logout() async { try { final response = await _userRepository.logoutUser(); if (response.statusCode == 200) { _isLoggedIn = false; _jwtToken = null; _userData = null; await _userRepository.deleteToken(); await _userRepository.deleteRefreshToken(); await _userRepository.deleteUserData(); notifyListeners(); return true; } return false; } catch (e) { print('Logout error: $e'); _isLoggedIn = false; _jwtToken = null; _userData = null; await _userRepository.deleteToken(); await _userRepository.deleteRefreshToken(); await _userRepository.deleteUserData(); notifyListeners(); return false; } } Future forgotPassword({required String email}) async { try { final response = await _userRepository.forgotPassword(email); if (response.statusCode == 200) { print("Password reset email sent successfully!"); return true; } else if (response.statusCode == 404) { print("Email is not registered!"); return false; } return false; } catch (e) { print('Forgot Password error: $e'); return false; } } Future refreshToken() async { try { final refreshToken = await _userRepository.getRefreshToken(); if (refreshToken == null) return false; final response = await _userRepository.dioClient.refreshAccessToken(refreshToken); if (response.statusCode == 200) { String newToken = response.data['payload']['TOKEN']; String newRefreshToken = response.data['payload']['REFRESH_TOKEN']; if (newToken.startsWith('Bearer ')) { newToken = newToken.substring(7); } _jwtToken = newToken; await _userRepository.saveToken(_jwtToken!); await _userRepository.saveRefreshToken(newRefreshToken); return true; } return false; } catch (e) { print('Error refreshing token: $e'); return false; } } Future isTokenValid() async { if (_jwtToken == null) return false; if (JwtDecoder.isExpired(_jwtToken!)) { return await refreshToken(); } return true; } Future getValidToken() async { try { if (await isTokenValid()) { return _jwtToken; } return null; } catch (e) { print('Error in getValidToken: $e'); return null; } } Future updateUserProfile(Map updatedData) async { try { final token = await getValidToken(); final userId = _userData?['ID']; if (token != null && userId != null) { final response = await _userRepository.updateUserProfile( userId, updatedData, token, imageFile: _selectedImage, ); if (response.statusCode == 200) { _userData = response.data['payload']; // Save updated user data securely await _userRepository.saveUserData(_userData!); _selectedImage = null; // Reset the selected image after successful update notifyListeners(); } } } catch (e) { print('Error updating user profile: $e'); rethrow; } } Future updatePassword({ required String oldPassword, required String newPassword, required String confirmPassword, }) async { try { final token = await getValidToken(); final userId = _userData?['ID']; if (token != null && userId != null) { final response = await _userRepository.updatePassword( userId, oldPassword, newPassword, confirmPassword, token, ); if (response.statusCode == 200) { print("Password updated successfully!"); return true; } } return false; } catch (e) { print('Error updating password: $e'); return false; } } Future reportIssue(String report) async { try { final token = await getValidToken(); if (token != null) { final response = await _userRepository.reportIssue(report, token); if (response.statusCode == 201) { print("Issue reported successfully!"); return true; } } return false; } catch (e) { print('Error reporting issue: $e'); return false; } } String? getUserName() { return _userData?['NAME_USERS']; } void setSelectedImage(File? image) { _selectedImage = image; notifyListeners(); } }