using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Npgsql; namespace HuntingAppApi.Controllers; public sealed class CreateMessageRequest { public Guid? SenderParticipantId { get; set; } public string Message { get; set; } = ""; } [ApiController] [Authorize] [Route("api/hunts/{huntId:guid}/messages")] public sealed class MessagesController(NpgsqlDataSource dataSource) : ControllerBase { [HttpPost] public async Task Create(Guid huntId, [FromBody] CreateMessageRequest request, CancellationToken ct) { await using var conn = await dataSource.OpenConnectionAsync(ct); await using var cmd = new NpgsqlCommand(""" INSERT INTO hunt_message (hunt_id, sender_participant_id, message) VALUES (@hunt_id, @sender_participant_id, @message) """, conn); cmd.Parameters.AddWithValue("hunt_id", huntId); cmd.Parameters.AddWithValue("sender_participant_id", (object?)request.SenderParticipantId ?? DBNull.Value); cmd.Parameters.AddWithValue("message", request.Message); await cmd.ExecuteNonQueryAsync(ct); return NoContent(); } [HttpGet] public async Task Get(Guid huntId, CancellationToken ct) { var list = new List(); await using var conn = await dataSource.OpenConnectionAsync(ct); await using var cmd = new NpgsqlCommand(""" SELECT m.id, m.sender_participant_id, u.display_name, m.message, m.created_at FROM hunt_message m LEFT JOIN hunt_participant hp ON hp.id = m.sender_participant_id LEFT JOIN app_user u ON u.id = hp.user_id WHERE m.hunt_id = @hunt_id ORDER BY m.created_at DESC LIMIT 100 """, conn); cmd.Parameters.AddWithValue("hunt_id", huntId); await using var r = await cmd.ExecuteReaderAsync(ct); while (await r.ReadAsync(ct)) { list.Add(new { id = r.GetGuid(0), senderParticipantId = r.IsDBNull(1) ? (Guid?)null : r.GetGuid(1), senderName = r.IsDBNull(2) ? null : r.GetString(2), message = r.GetString(3), createdAt = r.GetFieldValue(4) }); } return Ok(list); } }