using GmRelay.Shared.Domain; namespace GmRelay.Web.Services; public sealed record PlayerAttendanceStats( Guid PlayerId, string DisplayName, string? TelegramUsername, long TotalSessions, long ConfirmedCount, long DeclinedCount, long NoResponseCount, long WaitlistedCount, long CancellationAffectedCount, decimal AttendanceRate ); public sealed record SessionAuditLogEntry( Guid Id, Guid SessionId, long ActorTelegramId, string ActorName, string ChangeType, string? OldValue, string? NewValue, DateTime ChangedAt ); public interface ISessionStore { Task> GetGroupsForGmAsync(long gmId); Task GetGroupAsync(Guid groupId); Task IsGroupManagerAsync(Guid groupId, long telegramId); Task IsGroupOwnerAsync(Guid groupId, long telegramId); Task> GetGroupManagersAsync(Guid groupId); Task> GetUpcomingSessionsAsync(Guid groupId); Task GetSessionAsync(Guid sessionId); Task GetBatchAsync(Guid batchId); Task UpdateSessionAsync(Guid sessionId, Guid groupId, string title, DateTime scheduledAt, string joinLink, int? maxPlayers); Task PromoteWaitlistedPlayerAsync(Guid sessionId, Guid groupId); Task UpdateBatchDetailsAsync(Guid batchId, Guid groupId, string title, string joinLink); Task UpdateBatchNotificationModeAsync(Guid batchId, Guid groupId, SessionNotificationMode notificationMode); Task RescheduleBatchAsync(Guid batchId, Guid groupId, DateTime firstScheduledAt, int intervalDays); Task CloneBatchAsync(Guid batchId, Guid groupId, BatchCloneInterval interval); Task> GetCampaignTemplatesAsync(Guid groupId); Task GetCampaignTemplateAsync(Guid templateId); Task CreateCampaignTemplateAsync(Guid groupId, CreateCampaignTemplateRequest request); Task DeleteCampaignTemplateAsync(Guid templateId, Guid groupId); Task CreateBatchFromTemplateAsync(Guid templateId, Guid groupId, DateTime firstScheduledAt); Task AddGroupCoGmAsync(Guid groupId, long ownerTelegramId, long coGmTelegramId, string displayName, string? telegramUsername); Task RemoveGroupCoGmAsync(Guid groupId, long coGmTelegramId); Task> GetSessionParticipantsAsync(Guid sessionId); Task RemovePlayerFromSessionAsync(Guid sessionId, Guid groupId, Guid participantId); Task> GetGroupAttendanceStatsAsync(Guid groupId); Task LogSessionChangeAsync(Guid sessionId, long actorTelegramId, string actorName, string changeType, string? oldValue, string? newValue); Task> GetSessionHistoryAsync(Guid sessionId); }