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 phase = await EndpointHelpers.GetPhase(db);
            if (phase != Phase.Vote)
                return EndpointHelpers.PhaseMismatch(Phase.Vote, phase);

            var player = await EndpointHelpers.GetAuthenticatedPlayer(ctx, db);
            if (player is null) return Results.Unauthorized();
            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) =>
        {
            var phase = await EndpointHelpers.GetPhase(db);
            if (phase != Phase.Vote)
                return EndpointHelpers.PhaseMismatch(Phase.Vote, phase);

            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 (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 });
        });
    }
}
