using CsvHelper; using FabApprovalWorkerService.Models; using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; namespace FabApprovalWorkerService.Services; public interface ITrainingRecordService { IEnumerable ScrapeRecordsFromCsvFile(CsvReader csvReader); ConcurrentDictionary<(string, string), TrainingRecord> SortAndFilterTrainingRecordsByCompletionDate(IEnumerable trainingRecords); } public class TrainingRecordService { private readonly ILogger _logger; public TrainingRecordService(ILogger logger) { _logger = logger; if (_logger is null) throw new ArgumentNullException("ILogger not injected"); } public IEnumerable ScrapeTrainingRecordsFromCsvFile([DisallowNull] CsvReader csvReader) { if (csvReader is null) throw new ArgumentNullException("csvReader cannot be null"); try { _logger.LogInformation("Attempting to scrape training records from CSV file"); using (csvReader) { return csvReader.GetRecords(); } } catch (Exception ex) { _logger.LogError("An exception occurred when attempting to scrape training records from CSV file. Exception: {ex}", ex.Message); throw; } } public ConcurrentDictionary<(string, string), TrainingRecord> SortAndFilterTrainingRecordsByCompletionDate([DisallowNull] IEnumerable trainingRecords) { if (trainingRecords is null) throw new ArgumentNullException("trainingRecords cannot be null"); ConcurrentDictionary<(string, string), TrainingRecord> recordsMap = new(); try { _logger.LogInformation("Attempting to sort and filter training records"); IOrderedEnumerable sortedRecords = trainingRecords.OrderByDescending(t => t.UserId) .ThenBy(t => t.ItemId) .ThenByDescending(t => t.CompletionDate); foreach (TrainingRecord trainingRecord in sortedRecords) { if (!recordsMap.TryGetValue((trainingRecord.FirstName + trainingRecord.LastName, trainingRecord.ItemId), out TrainingRecord? existingRecord)) { recordsMap[(trainingRecord.FirstName + trainingRecord.LastName, trainingRecord.ItemId)] = trainingRecord; } } return recordsMap; } catch (Exception ex) { _logger.LogError("An exception occurred when attempting to sort and filter training records. Exception: {ex}", ex.Message); return recordsMap; } } }