import 'package:flutter/foundation.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:firebase_auth/firebase_auth.dart' as fb; import '../../shared/models/user.dart'; import '../api/api_client.dart'; import '../config/app_config.dart'; import '../locale/language_provider.dart'; import 'auth_service.dart'; import 'secure_storage.dart'; enum AuthStatus { unknown, authenticated, unauthenticated } class AuthState { final AuthStatus status; final User? user; final bool isLoading; final String? error; const AuthState({ this.status = AuthStatus.unknown, this.user, this.isLoading = false, this.error, }); AuthState copyWith({ AuthStatus? status, User? user, bool? isLoading, String? error, }) { return AuthState( status: status ?? this.status, user: user ?? this.user, isLoading: isLoading ?? this.isLoading, error: error, ); } } class AuthNotifier extends StateNotifier { final AuthService? _authService; AuthNotifier(AuthService authService) : _authService = authService, super(const AuthState()) { _checkAuth(); } @visibleForTesting AuthNotifier.test(super.initialState) : _authService = null; Future _checkAuth() async { final isAuth = await _authService!.isAuthenticated(); state = state.copyWith( status: isAuth ? AuthStatus.authenticated : AuthStatus.unauthenticated, ); } Future signInWithEmail(String email, String password) async { state = state.copyWith(isLoading: true, error: null); try { final user = await _authService!.signInWithEmail(email, password); state = AuthState( status: AuthStatus.authenticated, user: user, ); } catch (e) { state = state.copyWith( isLoading: false, error: _mapError(e), ); } } Future signInWithGoogle() async { state = state.copyWith(isLoading: true, error: null); try { final user = await _authService!.signInWithGoogle(); state = AuthState( status: AuthStatus.authenticated, user: user, ); } catch (e) { state = state.copyWith( isLoading: false, error: _mapError(e), ); } } Future register(String email, String password, String name) async { state = state.copyWith(isLoading: true, error: null); try { final user = await _authService!.registerWithEmail(email, password, name); state = AuthState( status: AuthStatus.authenticated, user: user, ); } catch (e) { state = state.copyWith( isLoading: false, error: _mapError(e), ); } } Future signOut() async { await _authService!.signOut(); state = const AuthState(status: AuthStatus.unauthenticated); } String _mapError(dynamic e) { if (e is fb.FirebaseAuthException) { switch (e.code) { case 'wrong-password': case 'user-not-found': return 'Неверный email или пароль'; case 'email-already-in-use': return 'Email уже зарегистрирован'; case 'weak-password': return 'Пароль слишком простой'; case 'invalid-email': return 'Некорректный email'; default: return 'Ошибка авторизации: ${e.message}'; } } return 'Произошла ошибка. Попробуйте позже.'; } } final appConfigProvider = Provider((ref) { return AppConfig.development; }); final secureStorageProvider = Provider((ref) { return SecureStorageService(); }); final apiClientProvider = Provider((ref) { final config = ref.read(appConfigProvider); final storage = ref.read(secureStorageProvider); return ApiClient( baseUrl: config.apiBaseUrl, storage: storage, languageGetter: () => ref.read(languageProvider), ); }); final authServiceProvider = Provider((ref) { return AuthService( firebaseAuth: fb.FirebaseAuth.instance, apiClient: ref.read(apiClientProvider), storage: ref.read(secureStorageProvider), ); }); final authProvider = StateNotifierProvider((ref) { return AuthNotifier(ref.read(authServiceProvider)); });