using Core.Entities; using Core.Utility; using WebApp.Models; namespace WebApp.Services; /// /// Service for calendar-related operations. /// public class CalendarService : ICalendarService { private readonly IEventOccurrenceService _eventOccurrenceService; private readonly ITeamMeetingHistoryService _teamMeetingHistoryService; public CalendarService( IEventOccurrenceService eventOccurrenceService, ITeamMeetingHistoryService teamMeetingHistoryService) { _eventOccurrenceService = eventOccurrenceService; _teamMeetingHistoryService = teamMeetingHistoryService; } public async Task> GetAllCalendarItemsAsync() { var items = new List(); await AddEventItemsAsync(items, includeStudentNames: true); await AddMeetingItemsAsync(items); return items; } public async Task> GetUpcomingCalendarItemsAsync(int count = 3) { var today = DateTime.Today; var items = new List(); await AddEventItemsAsync(items, startDate: today, includeStudentNames: false); await AddMeetingItemsAsync(items, startDate: today); // Sort by date and take top N return items .OrderBy(item => item.Start) .Take(count) .ToList(); } private async Task AddEventItemsAsync( List items, DateTime? startDate = null, bool includeStudentNames = false) { try { var occurrences = await _eventOccurrenceService.GetEventOccurrencesAsync(); var eventOccurrences = occurrences as EventOccurrence[] ?? occurrences.ToArray(); // Filter by start date if provided if (startDate.HasValue) { eventOccurrences = eventOccurrences .Where(occ => occ.StartTime.Date >= startDate.Value) .ToArray(); } Dictionary>? teamsByEventId = null; if (includeStudentNames) { // Get all unique event definition IDs that have occurrences var eventDefinitionIds = eventOccurrences .Where(occ => occ?.EventDefinition?.Id != null) .Select(occ => occ!.EventDefinition!.Id) .Distinct() .ToList(); // Load teams for all event definitions teamsByEventId = await _eventOccurrenceService.GetTeamsByEventDefinitionIdsAsync(eventDefinitionIds); } // Add event occurrences foreach (var occ in eventOccurrences) { try { List? studentFirstNames = null; if (includeStudentNames && occ.EventDefinition != null && teamsByEventId != null) { studentFirstNames = teamsByEventId.TryGetValue(occ.EventDefinition.Id, out var teams) ? TeamStudentNameFormatter.FormatStudentListForEvent( occ.EventDefinition, teams, new TeamStudentNameFormatter.FormatOptions { CaptainIndicator = TeamStudentNameFormatter.CaptainIndicatorStyle.Star, Ordering = TeamStudentNameFormatter.OrderingStyle.Alphabetical }) : []; } var calendarEventItem = new CalendarEventItem(occ, studentFirstNames); items.Add(new CalendarItemWrapper(calendarEventItem)); } catch (Exception) { // Continue processing other items } } } catch (Exception) { // Continue - don't fail the entire calendar load if events fail } } private async Task AddMeetingItemsAsync( List items, DateTime? startDate = null) { try { var meetingHistories = await _teamMeetingHistoryService.GetMeetingHistoriesAsync(); IEnumerable meetings = meetingHistories; if (startDate.HasValue) { meetings = meetings.Where(m => m.MeetingDate.Date >= startDate.Value); } foreach (var meetingHistory in meetings) { try { var calendarMeetingItem = new CalendarMeetingItem(meetingHistory); items.Add(new CalendarItemWrapper(calendarMeetingItem)); } catch (Exception) { // Continue processing other items } } } catch (Exception) { // Continue - don't fail the entire calendar load if meetings fail } } }