import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:injectable/injectable.dart'; import '../../data/models/user.dart'; import '../../data/models/user_role.dart'; import '../../data/datasources/keycloak_auth_service.dart'; import '../../data/datasources/permission_engine.dart'; import '../../../../core/storage/dashboard_cache_manager.dart'; // === ÉVÉNEMENTS === abstract class AuthEvent extends Equatable { const AuthEvent(); @override List get props => []; } class AuthLoginRequested extends AuthEvent { final String email; final String password; const AuthLoginRequested(this.email, this.password); @override List get props => [email, password]; } class AuthLogoutRequested extends AuthEvent { const AuthLogoutRequested(); } class AuthStatusChecked extends AuthEvent { const AuthStatusChecked(); } class AuthTokenRefreshRequested extends AuthEvent { const AuthTokenRefreshRequested(); } // === ÉTATS === abstract class AuthState extends Equatable { const AuthState(); @override List get props => []; } class AuthInitial extends AuthState {} class AuthLoading extends AuthState {} class AuthUnauthenticated extends AuthState {} class AuthAuthenticated extends AuthState { final User user; final UserRole effectiveRole; final List effectivePermissions; final String accessToken; const AuthAuthenticated({ required this.user, required this.effectiveRole, required this.effectivePermissions, required this.accessToken, }); @override List get props => [user, effectiveRole, effectivePermissions, accessToken]; } class AuthError extends AuthState { final String message; const AuthError(this.message); @override List get props => [message]; } // === BLOC === @lazySingleton class AuthBloc extends Bloc { final KeycloakAuthService _authService; AuthBloc(this._authService) : super(AuthInitial()) { on(_onLoginRequested); on(_onLogoutRequested); on(_onStatusChecked); on(_onTokenRefreshRequested); } Future _onLoginRequested(AuthLoginRequested event, Emitter emit) async { emit(AuthLoading()); try { final user = await _authService.login(event.email, event.password); if (user != null) { final permissions = await PermissionEngine.getEffectivePermissions(user); final token = await _authService.getValidToken(); await DashboardCacheManager.invalidateForRole(user.primaryRole); emit(AuthAuthenticated( user: user, effectiveRole: user.primaryRole, effectivePermissions: permissions, accessToken: token ?? '', )); } else { emit(const AuthError('Identifiants incorrects.')); } } catch (e) { emit(AuthError('Erreur de connexion: $e')); } } Future _onLogoutRequested(AuthLogoutRequested event, Emitter emit) async { emit(AuthLoading()); await _authService.logout(); await DashboardCacheManager.clear(); emit(AuthUnauthenticated()); } Future _onStatusChecked(AuthStatusChecked event, Emitter emit) async { final tokenValid = await _authService.getValidToken(); final isAuth = tokenValid != null; if (!isAuth) { emit(AuthUnauthenticated()); return; } final user = await _authService.getCurrentUser(); if (user == null) { emit(AuthUnauthenticated()); return; } final permissions = await PermissionEngine.getEffectivePermissions(user); final token = await _authService.getValidToken(); emit(AuthAuthenticated( user: user, effectiveRole: user.primaryRole, effectivePermissions: permissions, accessToken: token ?? '', )); } Future _onTokenRefreshRequested(AuthTokenRefreshRequested event, Emitter emit) async { if (state is AuthAuthenticated) { final newToken = await _authService.refreshToken(); final success = newToken != null; if (success) { add(AuthStatusChecked()); } else { add(AuthLogoutRequested()); } } } }