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
}
}
}