using GameList.Contracts; using GameList.Data; using GameList.Domain; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace GameList.Endpoints; public static class VoteEndpoints { public static void MapVoteEndpoints(this IEndpointRouteBuilder app) { app.MapGet("/api/votes/mine", async (HttpContext ctx, AppDbContext db) => { var player = await EndpointHelpers.GetAuthenticatedPlayer(ctx, db); if (player is null) return Results.Unauthorized(); var phase = await EndpointHelpers.GetPhase(db, player.Id); if (phase != Phase.Vote) return EndpointHelpers.PhaseMismatch(Phase.Vote, phase); var votes = await db.Votes.AsNoTracking() .Where(v => v.PlayerId == player.Id) .Select(v => new { v.SuggestionId, v.Score }) .ToListAsync(); return Results.Ok(votes); }); app.MapPost("/api/votes", async ([FromBody] VoteRequest request, HttpContext ctx, AppDbContext db) => { if (request.Score is < 0 or > 10) return Results.BadRequest(new { error = "Score must be between 0 and 10." }); var player = await EndpointHelpers.GetAuthenticatedPlayer(ctx, db); if (player is null) return Results.Unauthorized(); if (player.VotesFinal) return Results.BadRequest(new { error = "Votes are finalized. Unfinalize before changing scores." }); var phase = await EndpointHelpers.GetPhase(db, player.Id); if (phase != Phase.Vote) return EndpointHelpers.PhaseMismatch(Phase.Vote, phase); if (string.IsNullOrWhiteSpace(player.DisplayName)) return Results.BadRequest(new { error = "Set a display name before voting." }); var suggestionExists = await db.Suggestions.AnyAsync(s => s.Id == request.SuggestionId); if (!suggestionExists) return Results.BadRequest(new { error = "Suggestion not found." }); var vote = await db.Votes.FirstOrDefaultAsync(v => v.PlayerId == player.Id && v.SuggestionId == request.SuggestionId); if (vote == null) { vote = new Vote { PlayerId = player.Id, SuggestionId = request.SuggestionId, Score = request.Score }; db.Votes.Add(vote); } else { vote.Score = request.Score; } await db.SaveChangesAsync(); return Results.Ok(new { vote.Id, vote.Score }); }); app.MapPost("/api/votes/finalize", async ([FromBody] VoteFinalizeRequest request, HttpContext ctx, AppDbContext db) => { var player = await EndpointHelpers.GetAuthenticatedPlayer(ctx, db); if (player is null) return Results.Unauthorized(); var phase = await EndpointHelpers.GetPhase(db, player.Id); if (phase != Phase.Vote) return EndpointHelpers.PhaseMismatch(Phase.Vote, phase); player.VotesFinal = request.Final; await db.SaveChangesAsync(); return Results.Ok(new { player.VotesFinal }); }); } }