package com.mycrib.cache import com.mycrib.shared.network.* import com.mycrib.storage.TokenStorage import kotlinx.coroutines.* /** * Manager responsible for prefetching and caching data when the app launches. * This ensures all screens have immediate access to data without making API calls. */ class DataPrefetchManager { private val residenceApi = ResidenceApi() private val taskApi = TaskApi() private val documentApi = DocumentApi() private val contractorApi = ContractorApi() private val lookupsApi = LookupsApi() /** * Prefetch all essential data on app launch. * This runs asynchronously and populates the DataCache. */ suspend fun prefetchAllData(): Result = withContext(Dispatchers.Default) { try { val token = TokenStorage.getToken() if (token == null) { return@withContext Result.failure(Exception("Not authenticated")) } println("DataPrefetchManager: Starting data prefetch...") // Launch all prefetch operations in parallel val jobs = listOf( async { prefetchResidences(token) }, async { prefetchMyResidences(token) }, async { prefetchTasks(token) }, async { prefetchDocuments(token) }, async { prefetchContractors(token) }, async { prefetchLookups(token) } ) // Wait for all jobs to complete jobs.awaitAll() // Mark cache as initialized DataCache.setCacheInitialized(true) println("DataPrefetchManager: Data prefetch completed successfully") Result.success(Unit) } catch (e: Exception) { println("DataPrefetchManager: Error during prefetch: ${e.message}") e.printStackTrace() Result.failure(e) } } /** * Refresh specific data types. * Useful for pull-to-refresh functionality. */ suspend fun refreshResidences(): Result = withContext(Dispatchers.Default) { try { val token = TokenStorage.getToken() ?: return@withContext Result.failure(Exception("Not authenticated")) prefetchResidences(token) prefetchMyResidences(token) Result.success(Unit) } catch (e: Exception) { Result.failure(e) } } suspend fun refreshTasks(): Result = withContext(Dispatchers.Default) { try { val token = TokenStorage.getToken() ?: return@withContext Result.failure(Exception("Not authenticated")) prefetchTasks(token) Result.success(Unit) } catch (e: Exception) { Result.failure(e) } } suspend fun refreshDocuments(): Result = withContext(Dispatchers.Default) { try { val token = TokenStorage.getToken() ?: return@withContext Result.failure(Exception("Not authenticated")) prefetchDocuments(token) Result.success(Unit) } catch (e: Exception) { Result.failure(e) } } suspend fun refreshContractors(): Result = withContext(Dispatchers.Default) { try { val token = TokenStorage.getToken() ?: return@withContext Result.failure(Exception("Not authenticated")) prefetchContractors(token) Result.success(Unit) } catch (e: Exception) { Result.failure(e) } } // Private prefetch methods private suspend fun prefetchResidences(token: String) { try { println("DataPrefetchManager: Fetching residences...") val result = residenceApi.getResidences(token) if (result is ApiResult.Success) { DataCache.updateResidences(result.data) println("DataPrefetchManager: Cached ${result.data.size} residences") } } catch (e: Exception) { println("DataPrefetchManager: Error fetching residences: ${e.message}") } } private suspend fun prefetchMyResidences(token: String) { try { println("DataPrefetchManager: Fetching my residences...") val result = residenceApi.getMyResidences(token) if (result is ApiResult.Success) { DataCache.updateMyResidences(result.data) println("DataPrefetchManager: Cached my residences") } } catch (e: Exception) { println("DataPrefetchManager: Error fetching my residences: ${e.message}") } } private suspend fun prefetchTasks(token: String) { try { println("DataPrefetchManager: Fetching tasks...") val result = taskApi.getTasks(token) if (result is ApiResult.Success) { DataCache.updateAllTasks(result.data) println("DataPrefetchManager: Cached tasks") } } catch (e: Exception) { println("DataPrefetchManager: Error fetching tasks: ${e.message}") } } private suspend fun prefetchDocuments(token: String) { try { println("DataPrefetchManager: Fetching documents...") val result = documentApi.getDocuments( token = token, residenceId = null, documentType = null, category = null, contractorId = null, isActive = null, expiringSoon = null, tags = null, search = null ) if (result is ApiResult.Success) { DataCache.updateDocuments(result.data) println("DataPrefetchManager: Cached ${result.data.size} documents") } } catch (e: Exception) { println("DataPrefetchManager: Error fetching documents: ${e.message}") } } private suspend fun prefetchContractors(token: String) { try { println("DataPrefetchManager: Fetching contractors...") val result = contractorApi.getContractors( token = token, specialty = null, isFavorite = null, isActive = null, search = null ) if (result is ApiResult.Success) { // API returns List, not List // Skip caching for now - full Contractor objects will be cached when fetched individually println("DataPrefetchManager: Fetched ${result.data.size} contractor summaries") } } catch (e: Exception) { println("DataPrefetchManager: Error fetching contractors: ${e.message}") } } private suspend fun prefetchLookups(token: String) { // Lookups are handled separately by LookupsViewModel with their own caching println("DataPrefetchManager: Skipping lookups prefetch (handled by LookupsViewModel)") } companion object { private var instance: DataPrefetchManager? = null fun getInstance(): DataPrefetchManager { if (instance == null) { instance = DataPrefetchManager() } return instance!! } } }