import 'package:dio/dio.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../core/auth_storage.dart'; import '../core/team_selection_storage.dart'; import '../shared/api_client.dart'; import '../shared/models/user.dart'; class AuthState { const AuthState({ this.user, this.accessToken, this.refreshToken, this.loading = false, this.error, }); final User? user; final String? accessToken; final String? refreshToken; final bool loading; final String? error; bool get isAuthenticated => accessToken != null && accessToken!.isNotEmpty && user != null; AuthState copyWith({ User? user, String? accessToken, String? refreshToken, bool? loading, String? error, bool clearError = false, }) { return AuthState( user: user ?? this.user, accessToken: accessToken ?? this.accessToken, refreshToken: refreshToken ?? this.refreshToken, loading: loading ?? this.loading, error: clearError ? null : (error ?? this.error), ); } } class AuthNotifier extends StateNotifier { AuthNotifier() : super(const AuthState()); void setSession({ required User user, required String accessToken, required String refreshToken, }) { state = AuthState( user: user, accessToken: accessToken, refreshToken: refreshToken, loading: false, ); AuthStorage.save( user: user, accessToken: accessToken, refreshToken: refreshToken, ); } Future restoreSession() async { final stored = await AuthStorage.load(); if (stored == null) return; state = AuthState( user: stored.user, accessToken: stored.accessToken, refreshToken: stored.refreshToken, loading: false, ); } /// Dopo restore: verifica token o rinnova con refresh (evita 401 su /teams). Future validateOrRefreshSession() async { if (!state.isAuthenticated) return false; final client = ApiClient(accessToken: state.accessToken); try { final user = await client.me(); state = state.copyWith(user: user); await AuthStorage.save( user: user, accessToken: state.accessToken!, refreshToken: state.refreshToken!, ); return true; } on DioException catch (e) { if (e.response?.statusCode != 401) { return true; } } catch (_) { return true; } return refreshSession(); } Future refreshSession() async { final refreshToken = state.refreshToken; if (refreshToken == null || refreshToken.isEmpty) { logout(); return false; } try { final client = ApiClient(); final result = await client.refreshSession(refreshToken); setSession( user: result.user, accessToken: result.tokens.accessToken, refreshToken: result.tokens.refreshToken, ); return true; } catch (_) { logout(); return false; } } void setLoading(bool loading) { state = state.copyWith(loading: loading, clearError: true); } void setError(String message) { state = state.copyWith(loading: false, error: message); } void logout() { state = const AuthState(); AuthStorage.clear(); TeamSelectionStorage.clear(); } } final authProvider = StateNotifierProvider( (ref) => AuthNotifier(), );