aggregateNeomageStats method

Future<NeomageStats> aggregateNeomageStats()

Aggregates stats from all Neomage sessions across all projects. Uses a disk cache to avoid reprocessing historical data.

Implementation

Future<NeomageStats> aggregateNeomageStats() async {
  final allSessionFiles = await getAllSessionFiles();

  if (allSessionFiles.isEmpty) {
    return _getEmptyStats();
  }

  final updatedCache = await withStatsCacheLock(() async {
    final cache = await loadStatsCache();
    final yesterday = getYesterdayDateString();

    var result = cache;

    if (cache.lastComputedDate == null) {
      // No cache — process all historical data.
      final historicalStats = await processSessionFiles(
        allSessionFiles,
        options: ProcessOptions(toDate: yesterday),
      );

      if (historicalStats.sessionStats.isNotEmpty ||
          historicalStats.dailyActivity.isNotEmpty) {
        result = mergeCacheWithNewStats(
          existingCache: cache,
          newStats: historicalStats,
          newLastComputedDate: yesterday,
        );
        await saveStatsCache(result);
      }
    } else if (isDateBefore(cache.lastComputedDate!, yesterday)) {
      // Cache is stale — process new days.
      final nextDay = getNextDay(cache.lastComputedDate!);
      final newStats = await processSessionFiles(
        allSessionFiles,
        options: ProcessOptions(fromDate: nextDay, toDate: yesterday),
      );

      if (newStats.sessionStats.isNotEmpty ||
          newStats.dailyActivity.isNotEmpty) {
        result = mergeCacheWithNewStats(
          existingCache: cache,
          newStats: newStats,
          newLastComputedDate: yesterday,
        );
        await saveStatsCache(result);
      } else {
        result = cache.copyWith(lastComputedDate: yesterday);
        await saveStatsCache(result);
      }
    }

    return result;
  });

  // Always process today's data live (it's incomplete).
  final today = getTodayDateString();
  final todayStats = await processSessionFiles(
    allSessionFiles,
    options: ProcessOptions(fromDate: today, toDate: today),
  );

  return cacheToStats(updatedCache, todayStats);
}