using BpsRwApp.Models; namespace BpsRwApp.Services; /// /// Service implementation untuk menangani statistik aplikasi /// Menggunakan base service untuk common functionality /// public class StatisticsService : BaseService, IStatisticsService { private readonly ICacheService _cacheService; private readonly IAppConfigurationService _appConfig; private readonly IValidationService _validationService; /// /// Cache key untuk statistik /// private const string StatisticsCacheKey = "current_statistics"; /// /// Constructor dengan dependency injection /// /// Logger untuk logging /// Memory cache untuk caching /// Configuration untuk settings /// Cache service /// Application configuration service /// Validation service public StatisticsService( ILogger logger, Microsoft.Extensions.Caching.Memory.IMemoryCache cache, IConfiguration configuration, ICacheService cacheService, IAppConfigurationService appConfig, IValidationService validationService) : base(logger, cache, configuration) { _cacheService = cacheService ?? throw new ArgumentNullException(nameof(cacheService)); _appConfig = appConfig ?? throw new ArgumentNullException(nameof(appConfig)); _validationService = validationService ?? throw new ArgumentNullException(nameof(validationService)); } /// public async Task GetCurrentStatisticsAsync() { return await ExecuteWithErrorHandlingAsync( async () => await _cacheService.GetOrSetWithSlidingAsync( StatisticsCacheKey, LoadStatisticsFromSourceAsync, _appConfig.CacheSettings.StatisticsSlidingExpiration, _appConfig.CacheSettings.StatisticsExpiration, Microsoft.Extensions.Caching.Memory.CacheItemPriority.High), "Fetching current statistics", GetDefaultStatistics()); } /// public async Task GetStatisticsByPeriodAsync(DateTime startDate, DateTime endDate) { return await ExecuteWithErrorHandlingAsync( async () => { var validation = _validationService.ValidateDateRange(startDate, endDate); if (!validation.IsValid) { throw new ArgumentException(string.Join("; ", validation.Errors)); } return await LoadStatisticsByPeriodFromSourceAsync(startDate, endDate); }, $"Fetching statistics for period {startDate:yyyy-MM-dd} to {endDate:yyyy-MM-dd}"); } /// public async Task UpdateStatisticsAsync(StatisticsModel statistics) { return await ExecuteWithErrorHandlingAsync( async () => { ArgumentNullException.ThrowIfNull(statistics); var validation = _validationService.ValidateStatistics(statistics); if (!validation.IsValid) { _logger.LogWarning("Invalid statistics data: {Errors}", string.Join("; ", validation.Errors)); return false; } // Simulate async update operation if (_appConfig.DevelopmentSettings.SimulatedDelayMs > 0) { await Task.Delay(_appConfig.DevelopmentSettings.SimulatedDelayMs); } else { await Task.Delay(10); } // Clear cache after update _cacheService.Remove(StatisticsCacheKey); return true; }, "Updating statistics", false); } /// /// Load statistics from data source (placeholder for actual implementation) /// /// Current statistics private async Task LoadStatisticsFromSourceAsync() { // In a real application, this would load from database, API, etc. await Task.CompletedTask; // Get base values from configuration var baseUsers = _appConfig.StatisticsSettings.BaseUsers; var baseWaste = _appConfig.StatisticsSettings.BaseWaste; // Simulate some growth over time var daysSinceStart = (DateTime.UtcNow - new DateTime(2024, 1, 1)).Days; var growthFactor = Math.Min(_appConfig.StatisticsSettings.MaxGrowthFactor, 1.0 + (daysSinceStart * _appConfig.StatisticsSettings.GrowthFactorMultiplier)); return new StatisticsModel { TotalUsers = (int)(baseUsers * growthFactor), WasteCollected = baseWaste * (decimal)growthFactor, RewardsDistributed = (int)(_appConfig.StatisticsSettings.BaseRewards * growthFactor), EnvironmentImpact = Math.Min(99.9m, _appConfig.StatisticsSettings.BaseEnvironmentImpact + (decimal)(growthFactor * 2)) }; } /// /// Load statistics for specific period (placeholder) /// /// Start date /// End date /// Period statistics private async Task LoadStatisticsByPeriodFromSourceAsync(DateTime startDate, DateTime endDate) { await Task.CompletedTask; // Calculate period-specific statistics var days = (endDate - startDate).Days + 1; var dailyAverage = await GetDailyAverageAsync(); return new StatisticsModel { TotalUsers = dailyAverage.TotalUsers * days / 365, WasteCollected = dailyAverage.WasteCollected * days, RewardsDistributed = dailyAverage.RewardsDistributed * days, EnvironmentImpact = dailyAverage.EnvironmentImpact }; } /// /// Get daily average statistics /// /// Daily average statistics private async Task GetDailyAverageAsync() { await Task.CompletedTask; return new StatisticsModel { TotalUsers = 3, // New users per day WasteCollected = 0.1m, // Tons per day RewardsDistributed = 5, // Rewards per day EnvironmentImpact = 98.5m // Overall impact }; } /// /// Get default statistics when error occurs /// /// Default statistics private StatisticsModel GetDefaultStatistics() { return new StatisticsModel { TotalUsers = _appConfig.StatisticsSettings.BaseUsers, WasteCollected = _appConfig.StatisticsSettings.BaseWaste, RewardsDistributed = _appConfig.StatisticsSettings.BaseRewards, EnvironmentImpact = _appConfig.StatisticsSettings.BaseEnvironmentImpact }; } }