import 'package:flutter/widgets.dart' show Locale; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:pocketbase/pocketbase.dart'; import '../auth/auth_repository.dart'; import '../services/notification_service.dart'; import '../../models/tenant.dart'; import '../../models/user_profile.dart'; import 'locale_provider.dart'; class AuthState { const AuthState({ this.profile, this.activeTenant, this.memberships = const [], this.isLoading = true, this.error, }); final UserProfile? profile; final TenantMembership? activeTenant; final List memberships; final bool isLoading; final String? error; bool get isAuthenticated => profile != null; AuthState copyWith({ UserProfile? profile, TenantMembership? activeTenant, List? memberships, bool? isLoading, String? error, bool clearError = false, }) => AuthState( profile: profile ?? this.profile, activeTenant: activeTenant ?? this.activeTenant, memberships: memberships ?? this.memberships, isLoading: isLoading ?? this.isLoading, error: clearError ? null : (error ?? this.error), ); } class AuthNotifier extends StateNotifier { AuthNotifier({this.onLocaleLoaded}) : super(const AuthState()) { _init(); } final void Function(String languageCode)? onLocaleLoaded; final _repo = AuthRepository.instance; Future _init() async { final loggedIn = await _repo.isLoggedIn(); if (!loggedIn) { state = const AuthState(isLoading: false); return; } try { final result = await _repo.refreshSession(); state = AuthState( profile: result.user, memberships: result.tenants, activeTenant: result.tenants.isEmpty ? null : result.tenants.first, isLoading: false, ); final isLab = result.tenants.isNotEmpty && result.tenants.first.tenant.isLab; NotificationService.loginUser(result.user.id, isLab: isLab); _applyLocale(result.user.preferredLanguage); } catch (_) { state = const AuthState(isLoading: false); } } void _applyLocale(String? code) { if (code != null && code.isNotEmpty) { onLocaleLoaded?.call(code); } } Future signIn( String email, String password, { required bool rememberSession, }) async { state = state.copyWith(isLoading: true, clearError: true); try { final result = await _repo.login( email, password, rememberSession: rememberSession, ); state = AuthState( profile: result.user, memberships: result.tenants, activeTenant: result.tenants.isEmpty ? null : result.tenants.first, isLoading: false, ); final isLab = result.tenants.isNotEmpty && result.tenants.first.tenant.isLab; NotificationService.loginUser(result.user.id, isLab: isLab); _applyLocale(result.user.preferredLanguage); } catch (e) { state = state.copyWith(isLoading: false, error: _parseError(e)); } } Future register({ required String email, required String password, String? firstName, String? lastName, }) async { state = state.copyWith(isLoading: true, clearError: true); try { final result = await _repo.register( email: email, password: password, firstName: firstName, lastName: lastName, ); state = AuthState( profile: result.user, memberships: result.tenants, activeTenant: result.tenants.isEmpty ? null : result.tenants.first, isLoading: false, ); } catch (e) { state = state.copyWith(isLoading: false, error: _parseError(e)); rethrow; } } Future signOut() async { await _repo.logout(); await NotificationService.logoutUser(); state = const AuthState(isLoading: false); } void setActiveTenant(TenantMembership membership) { state = state.copyWith(activeTenant: membership); } Future refresh() async { try { final result = await _repo.refreshSession(); final currentId = state.activeTenant?.tenant.id; final newActive = currentId != null ? result.tenants.firstWhere( (m) => m.tenant.id == currentId, orElse: () => result.tenants.isNotEmpty ? result.tenants.first : state.activeTenant!, ) : (result.tenants.isNotEmpty ? result.tenants.first : null); state = state.copyWith( profile: result.user, memberships: result.tenants, activeTenant: newActive, ); } catch (_) {} } Future updateLanguage(String languageCode) async { final userId = state.profile?.id; if (userId == null) return; await _repo.updateUserLanguage(userId, languageCode); } Future updateTenantInfo({ required String tenantId, required String companyName, String? defaultCurrency, }) async { await _repo.updateTenant( tenantId, companyName: companyName, defaultCurrency: defaultCurrency, ); await refresh(); } String _parseError(Object e) { if (e is ClientException) { final code = e.statusCode; if (code == 400 || code == 401 || code == 403) { return 'E-posta veya şifre hatalı.'; } final msg = e.response['message'] as String? ?? ''; if (msg.isNotEmpty) return msg; } return 'Bağlantı hatası. Lütfen tekrar deneyin.'; } } final authProvider = StateNotifierProvider((ref) { return AuthNotifier( onLocaleLoaded: (code) => ref.read(localeProvider.notifier).setLocale(Locale(code)), ); });