import 'package:dio/dio.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:get_it/get_it.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../data/cache/cache_store.dart'; import '../../features/calendar/data/repositories/calendar_repository.dart'; import '../../features/contacts/data/repositories/friend_repository.dart'; import '../../features/messages/data/repositories/inbox_repository.dart'; import '../../core/inbox/inbox_sync_store.dart'; import '../../features/contacts/data/repositories/user_repository.dart'; import '../../core/auth/session_controller.dart'; import '../../data/network/api_client.dart'; import '../../data/network/i_api_client.dart'; import '../../data/storage/token_storage.dart'; import '../../core/config/env.dart'; import '../../features/auth/data/apis/auth_api.dart'; import '../../features/auth/data/repositories/auth_repository.dart'; import '../../features/auth/data/repositories/auth_repository_impl.dart'; import '../../features/auth/presentation/bloc/auth_bloc.dart'; import '../../features/auth/presentation/bloc/auth_event.dart'; import '../../features/chat/presentation/bloc/chat_bloc.dart'; import '../../core/chat/chat_api.dart'; import '../../core/chat/chat_history_repository.dart'; import '../../features/chat/data/apis/chat_api_impl.dart'; import '../../features/calendar/data/apis/calendar_api.dart'; import '../../features/calendar/data/services/calendar_service.dart'; import '../../shared/state/calendar_state_manager.dart'; import '../../features/contacts/data/apis/friends_api.dart'; import '../../features/messages/data/apis/inbox_api.dart'; import '../../features/settings/data/apis/settings_api.dart'; import '../../features/settings/data/apis/automation_jobs_api.dart'; import '../../features/settings/data/repositories/user_profile_cache_repository.dart'; import '../../features/settings/data/services/user_profile_service.dart'; import '../../features/settings/data/services/memory_service.dart'; import '../../features/contacts/data/apis/users_api.dart'; import '../../features/todo/data/apis/todo_api.dart'; import '../../features/todo/data/repositories/todo_repository.dart'; import '../services/app_prewarm_orchestrator.dart'; import '../services/session_scope_manager.dart'; import '../services/auth_session_controller.dart'; import '../../core/notification/services/reminder_scheduler_service.dart'; import '../../core/notification/services/reminder_permission_service.dart'; import '../../core/notification/services/reminder_reconcile_service.dart'; import '../../core/notification/services/reminder_notification_router.dart'; final sl = GetIt.instance; Future configureDependencies() async { if (sl.isRegistered()) { await sl.reset(); } final SecureTokenStorage tokenStorage; final dio = Dio(BaseOptions(baseUrl: Env.apiUrl)); tokenStorage = SecureTokenStorage( const FlutterSecureStorage( aOptions: AndroidOptions(encryptedSharedPreferences: true), iOptions: IOSOptions( accessibility: KeychainAccessibility.first_unlock_this_device, ), ), ); final apiClient = ApiClient( baseUrl: Env.apiUrl, tokenStorage: tokenStorage, dio: dio, ); sl.registerSingleton(apiClient); final authApi = AuthApi(apiClient); sl.registerSingleton(authApi); final sharedPreferences = await SharedPreferences.getInstance(); sl.registerSingleton(sharedPreferences); final memoryCacheStore = MemoryCacheStore(); final persistentCacheStore = PersistentCacheStore(prefs: sharedPreferences); final hybridCacheStore = HybridCacheStore( memory: memoryCacheStore, persistent: persistentCacheStore, ); sl.registerSingleton(memoryCacheStore); sl.registerSingleton(persistentCacheStore); sl.registerSingleton(hybridCacheStore); sl.registerSingleton( SessionScopeManager(cacheStore: hybridCacheStore), ); sl.registerSingleton( CacheInvalidator(store: hybridCacheStore), ); final usersApi = UsersApi(apiClient); sl.registerSingleton(usersApi); sl.registerSingleton(UserRepositoryImpl(apiClient)); final userProfileService = UserProfileService(apiClient); sl.registerSingleton(userProfileService); final userProfileCacheRepository = UserProfileCacheRepository( store: hybridCacheStore, remoteLoader: userProfileService.getMe, ); sl.registerSingleton(userProfileCacheRepository); final calendarApi = CalendarApi(apiClient); sl.registerSingleton(calendarApi); final reminderScheduler = ReminderSchedulerService(); sl.registerSingleton(reminderScheduler); sl.registerSingleton( ReminderPermissionService(scheduler: reminderScheduler), ); sl.registerSingleton( ReminderReconcileService(scheduler: reminderScheduler), ); sl.registerSingleton( ReminderNotificationRouter(scheduler: reminderScheduler), dispose: (service) => service.dispose(), ); final calendarService = CalendarService( apiClient: apiClient, invalidator: sl(), reminderReconcileService: sl(), ); sl.registerSingleton(calendarService); final calendarRepository = CalendarRepository( store: hybridCacheStore, apiClient: apiClient, reminderReconcileService: sl(), ); sl.registerSingleton(calendarRepository); final friendsApi = FriendsApi(apiClient); sl.registerSingleton(friendsApi); sl.registerSingleton( FriendRepositoryImpl(apiClient: apiClient, store: hybridCacheStore), ); final settingsApi = SettingsApi(apiClient); sl.registerSingleton(settingsApi); final automationJobsApi = AutomationJobsApi(apiClient); sl.registerSingleton(automationJobsApi); final memoryService = MemoryService(apiClient); sl.registerSingleton(memoryService); final inboxApi = InboxApi(apiClient); sl.registerSingleton(inboxApi); final inboxRepository = InboxRepositoryImpl( apiClient: apiClient, store: hybridCacheStore, ); sl.registerSingleton(inboxRepository); sl.registerSingleton( InboxSyncStore(repository: inboxRepository, inboxApi: inboxApi), dispose: (store) => store.dispose(), ); final chatApi = ChatApiImpl(apiClient); sl.registerSingleton(chatApi); final chatHistoryRepository = ChatHistoryRepository( chatApi: chatApi, store: hybridCacheStore, ); sl.registerSingleton(chatHistoryRepository); final todoApi = TodoApi(apiClient); sl.registerSingleton(todoApi); sl.registerSingleton( TodoRepository( api: todoApi, store: hybridCacheStore, invalidator: sl(), ), ); final authRepository = AuthRepositoryImpl( api: authApi, tokenStorage: tokenStorage, onLogout: () async { apiClient.resetInterceptor(); if (sl.isRegistered()) { await sl().invalidate(); } }, ); sl.registerSingleton(authRepository); sl.registerSingleton( AppPrewarmOrchestrator( calendarRepository: calendarRepository, inboxRepository: sl(), chatHistoryRepository: chatHistoryRepository, ), ); final authBloc = AuthBloc(authRepository); sl.registerSingleton(authBloc); sl.registerSingleton(AuthSessionController(authBloc)); sl.registerSingleton( ChatBloc( chatApi: chatApi, historyRepository: chatHistoryRepository, onCalendarMutated: () async { final calendarRepository = sl(); final selected = sl().selectedDate; await Future.wait([ calendarRepository.getDayEvents(selected, forceRefresh: true), calendarRepository.getMonthEvents( DateTime(selected.year, selected.month, 1), forceRefresh: true, ), ]); }, ), ); apiClient.setRefreshCallback((token) async { try { await authRepository.refreshSession(token); return true; } catch (_) { return false; } }); apiClient.setAuthFailureCallback(() async { if (sl.isRegistered()) { await sl().invalidate(); } authBloc.add( const AuthSessionInvalidated( source: AuthInvalidationSource.unauthorized401, ), ); }); sl.registerSingleton(CalendarStateManager()); }