using Fitness_core_BE.Interfaces; using Fitness_core_BE.Models; using Microsoft.EntityFrameworkCore; namespace Fitness_core_BE.Repos { public class FacilityClassRepository : IFacilityClassRepository { private readonly TenantDbContext _context; public FacilityClassRepository(TenantDbContext context) { _context = context; } public async Task CreateFacilityClass(FacilityClass facilityClass) { facilityClass.FacilityClassId = Guid.NewGuid(); facilityClass.CreatedAt = DateTime.UtcNow; facilityClass.IsActive = true; _context.FacilityClasses.Add(facilityClass); return facilityClass; } public async Task> GetFacilityClasses(Guid clientId, bool includeInactive = false) { var query = _context.FacilityClasses .Include(fc => fc.Facility) .Where(fc => fc.FKClientId == clientId); if (!includeInactive) query = query.Where(fc => fc.IsActive); return await query.OrderBy(fc => fc.Name).ToListAsync(); } public Task GetFacilityClassById(Guid facilityClassId) => _context.FacilityClasses .Include(fc => fc.Facility) .FirstOrDefaultAsync(fc => fc.FacilityClassId == facilityClassId); public async Task UpdateFacilityClass(FacilityClass facilityClass) { var existing = await _context.FacilityClasses.FindAsync(facilityClass.FacilityClassId) ?? throw new KeyNotFoundException("Class not found"); existing.Name = facilityClass.Name; existing.Description = facilityClass.Description; existing.RecurrenceType = facilityClass.RecurrenceType; existing.StartTimeOfDay = facilityClass.StartTimeOfDay; existing.DurationMinutes = facilityClass.DurationMinutes; existing.WeekDaysMask = facilityClass.WeekDaysMask; existing.MonthDays = facilityClass.MonthDays; existing.SeriesStartDate = facilityClass.SeriesStartDate; existing.SeriesEndDate = facilityClass.SeriesEndDate; existing.Capacity = facilityClass.Capacity; existing.IsUnlimitedCapacity = facilityClass.IsUnlimitedCapacity; existing.IsActive = facilityClass.IsActive; existing.OccurrencesGeneratedThrough = facilityClass.OccurrencesGeneratedThrough; return existing; } public Task> GetClassesNeedingGenerationAsync(Guid clientId, DateTime horizon) => _context.FacilityClasses .Where(fc => fc.FKClientId == clientId && fc.IsActive && fc.RecurrenceType != "Custom" && fc.OccurrencesGeneratedThrough < horizon) .ToListAsync(); public async Task> GetExistingOccurrenceStartTimesAsync(Guid facilityClassId, DateTime from, DateTime to) { var times = await _context.FacilitySessions .Where(s => s.FKFacilityClassId == facilityClassId && s.StartTime >= from && s.StartTime < to) .Select(s => s.StartTime) .ToListAsync(); return times.ToHashSet(); } public async Task AddOccurrencesAsync(IEnumerable occurrences) { var list = occurrences.ToList(); foreach (var occurrence in list) { occurrence.FacilitySessionId = Guid.NewGuid(); occurrence.CreatedAt = DateTime.UtcNow; occurrence.IsCancelled = false; } await _context.FacilitySessions.AddRangeAsync(list); } public Task> GetOccurrencesForClassAsync(Guid facilityClassId, bool includeCancelled) { var query = _context.FacilitySessions.Where(s => s.FKFacilityClassId == facilityClassId); if (!includeCancelled) query = query.Where(s => !s.IsCancelled); return query.OrderByDescending(s => s.StartTime).ToListAsync(); } public async Task DeleteFutureUnbookedOccurrencesAsync(Guid facilityClassId, DateTime nowUtc) { var candidates = await _context.FacilitySessions .Where(s => s.FKFacilityClassId == facilityClassId && s.StartTime > nowUtc) .Where(s => !_context.Bookings.Any(b => b.FKFacilitySessionId == s.FacilitySessionId)) .ToListAsync(); _context.FacilitySessions.RemoveRange(candidates); return candidates.Count; } public async Task LinkPlanToClassAsync(Guid customerPlanId, Guid facilityClassId) { _context.CustomerPlanClasses.Add(new CustomerPlanClass { CustomerPlanClassId = Guid.NewGuid(), FKCustomerPlanId = customerPlanId, FKFacilityClassId = facilityClassId }); } public Task> GetSchedulingConflictsAsync(Guid clientId) { return _context.Bookings .Include(b => b.Facility) .Where(b => b.FKClientId == clientId && b.FKFacilitySessionId == null && b.Status == "Confirmed") .Where(b => _context.FacilitySessions.Any(s => s.FKFacilityId == b.FKFacilityId && s.FKFacilityClassId != null && !s.IsCancelled && s.StartTime < b.EndTime && s.EndTime > b.StartTime)) .ToListAsync(); } } }