using Dapper; using GmRelay.Shared.Domain; using GmRelay.Shared.Platform; using Npgsql; namespace GmRelay.Shared.Features.Sessions.ListSessions; public sealed record SessionListItemDto(Guid Id, string Title, DateTime ScheduledAt, string Status, int? MaxPlayers, int PlayerCount, int WaitlistCount, bool CanManage); public sealed record SessionListResult( IReadOnlyList Sessions, bool CanManage); public sealed class ListSessionsHandler( NpgsqlDataSource dataSource) { public async Task HandleAsync(ListSessionsCommand command, CancellationToken cancellationToken) { await using var connection = await dataSource.OpenConnectionAsync(cancellationToken); var sessions = await connection.QueryAsync( @"SELECT s.id as Id, s.title as Title, s.scheduled_at as ScheduledAt, s.status as Status, s.max_players as MaxPlayers, COUNT(sp.id) FILTER (WHERE sp.is_gm = false AND sp.registration_status = @Active) as PlayerCount, COUNT(sp.id) FILTER (WHERE sp.is_gm = false AND sp.registration_status = @Waitlisted) as WaitlistCount, EXISTS ( SELECT 1 FROM group_managers gm JOIN players manager_player ON manager_player.id = gm.player_id WHERE gm.group_id = s.group_id AND manager_player.platform = @Platform AND manager_player.external_user_id = @ExternalUserId ) AS CanManage FROM sessions s JOIN game_groups g ON s.group_id = g.id LEFT JOIN session_participants sp ON s.id = sp.session_id WHERE g.platform = @Platform AND g.external_group_id = @ExternalGroupId AND s.status != @Cancelled AND s.scheduled_at > NOW() GROUP BY s.id, s.title, s.scheduled_at, s.status, s.max_players, s.group_id ORDER BY s.scheduled_at ASC", new { Platform = command.Group.Platform.ToString(), ExternalGroupId = command.Group.ExternalGroupId, ExternalUserId = command.User.ExternalUserId, Cancelled = SessionStatus.Cancelled, Active = ParticipantRegistrationStatus.Active, Waitlisted = ParticipantRegistrationStatus.Waitlisted }); var sessionsList = sessions.ToList(); var canManage = sessionsList.Count > 0 && sessionsList.First().CanManage; return new SessionListResult(sessionsList, canManage); } }