import '../models/bean.dart'; import '../models/machine.dart'; import '../models/recipe.dart'; import '../models/journal_entry.dart'; import '../models/drink.dart'; class CoffeeStatistics { final int totalBeans; final int totalMachines; final int totalRecipes; final int totalJournalEntries; final int totalDrinks; final double averageRating; final int preferredBeans; final String mostUsedRoastLevel; final List> coffeeConsumptionTrend; final List topRatedDrinks; final List> recentActivity; final Map monthlyStats; CoffeeStatistics({ required this.totalBeans, required this.totalMachines, required this.totalRecipes, required this.totalJournalEntries, required this.totalDrinks, required this.averageRating, required this.preferredBeans, required this.mostUsedRoastLevel, required this.coffeeConsumptionTrend, required this.topRatedDrinks, required this.recentActivity, required this.monthlyStats, }); } class StatisticsService { static Future getStatistics( List beans, List machines, List recipes, List journalEntries, List drinks, ) async { try { // Calculate average rating final averageRating = drinks.isNotEmpty ? drinks.fold(0.0, (sum, drink) => sum + drink.rating) / drinks.length : 0.0; // Find most used roast level final roastLevelCounts = {}; for (final bean in beans) { roastLevelCounts[bean.roastLevel.toString().split('.').last] = (roastLevelCounts[bean.roastLevel.toString().split('.').last] ?? 0) + 1; } final mostUsedRoastLevel = roastLevelCounts.entries .fold?>( null, (max, entry) => max == null || entry.value > max.value ? entry : max, ) ?.key ?? 'MEDIUM'; // Calculate coffee consumption trend (last 6 months) final coffeeConsumptionTrend = _calculateConsumptionTrend(journalEntries); // Get top rated drinks final topRatedDrinks = List.from(drinks) ..sort((a, b) => b.rating.compareTo(a.rating)) ..take(5); // Recent activity final recentActivity = _getRecentActivity( beans, machines, recipes, journalEntries, drinks, ); // Monthly stats final monthlyStats = _calculateMonthlyStats(journalEntries); return CoffeeStatistics( totalBeans: beans.length, totalMachines: machines.length, totalRecipes: recipes.length, totalJournalEntries: journalEntries.length, totalDrinks: drinks.length, averageRating: (averageRating * 10).round() / 10, preferredBeans: beans.where((bean) => bean.preferred).length, mostUsedRoastLevel: mostUsedRoastLevel, coffeeConsumptionTrend: coffeeConsumptionTrend, topRatedDrinks: topRatedDrinks, recentActivity: recentActivity, monthlyStats: monthlyStats, ); } catch (error) { throw Exception('Error calculating statistics: $error'); } } static List> _calculateConsumptionTrend( List journalEntries, ) { final now = DateTime.now(); final months = >[]; for (int i = 5; i >= 0; i--) { final date = DateTime(now.year, now.month - i, 1); final monthName = _getMonthName(date); final count = journalEntries.where((entry) { final entryDate = entry.date; return entryDate.month == date.month && entryDate.year == date.year; }).length; months.add({'month': monthName, 'count': count}); } return months; } static List> _getRecentActivity( List beans, List machines, List recipes, List journalEntries, List drinks, ) { final activities = >[]; // Add recent journal entries for (final entry in journalEntries.take(5)) { activities.add({ 'date': entry.date, 'type': 'Journal', 'description': 'Enjoyed ${entry.drink.name}', }); } // Add recent beans for (final bean in beans.take(3)) { activities.add({ 'date': bean.roastedDate, 'type': 'Bean', 'description': 'Added ${bean.name} from ${bean.originCountry ?? 'Unknown'}', }); } activities.sort( (a, b) => (b['date'] as DateTime).compareTo(a['date'] as DateTime), ); return activities.take(10).toList(); } static Map _calculateMonthlyStats( List journalEntries, ) { final now = DateTime.now(); final currentMonth = now.month; final currentYear = now.year; final currentMonthCount = journalEntries.where((entry) { return entry.date.month == currentMonth && entry.date.year == currentYear; }).length; final lastMonth = currentMonth == 1 ? 12 : currentMonth - 1; final lastYear = currentMonth == 1 ? currentYear - 1 : currentYear; final lastMonthCount = journalEntries.where((entry) { return entry.date.month == lastMonth && entry.date.year == lastYear; }).length; final growth = lastMonthCount > 0 ? (((currentMonthCount - lastMonthCount) / lastMonthCount) * 100) .round() : 0; return { 'currentMonth': currentMonthCount, 'lastMonth': lastMonthCount, 'growth': growth, }; } static String _getMonthName(DateTime date) { const months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', ]; return '${months[date.month - 1]} ${date.year.toString().substring(2)}'; } }