using Backend.Contracts;
using Backend.Data;
using Backend.Services;
using Microsoft.EntityFrameworkCore;

namespace Backend.Endpoints;

public static partial class PublicEndpoints
{
    private static async Task<IResult> GetUserParticipation(
        HttpContext context,
        int year,
        AwardsDbContext db,
        IUserSessionService userSessionService)
    {
        var session = await userSessionService.ResolveSessionAsync(context, context.RequestAborted);
        if (session is null)
        {
            return Results.Unauthorized();
        }

        var season = await db.Seasons
            .AsNoTracking()
            .FirstOrDefaultAsync(item => item.Year == year);

        if (season is null)
        {
            return Results.NotFound();
        }

        var nominations = await db.Nominations
            .AsNoTracking()
            .Where(item => item.SeasonId == season.Id && item.SubmittedByTwitchId == session.TwitchUserId)
            .OrderBy(item => item.CategoryId)
            .ThenBy(item => item.Id)
            .Select(item => new
            {
                item.CategoryId,
                item.CategoryGroupName,
                item.Status,
                Nominee = item.CandidateId != null
                    ? item.Candidate!.DisplayName
                    : item.CandidateText ?? item.StreamUrl,
            })
            .ToArrayAsync();

        var groupedNominations = nominations
            .Where(item => item.Status != "rejected" && item.Status != "superseded")
            .Where(item => !string.IsNullOrWhiteSpace(item.Nominee))
            .GroupBy(item => new { item.CategoryId, item.CategoryGroupName })
            .Select(group => new UserNominationStateDto(
                group.Key.CategoryId,
                group.Key.CategoryGroupName,
                group.Select(item => item.Nominee!)
                    .Distinct(StringComparer.OrdinalIgnoreCase)
                    .ToArray()))
            .ToArray();

        var votes = await db.VoteEntries
            .AsNoTracking()
            .Where(item => item.Ballot.SeasonId == season.Id && item.Ballot.SubmittedByTwitchId == session.TwitchUserId)
            .OrderBy(item => item.CategoryId)
            .Select(item => new UserVoteStateDto(item.CategoryId, item.CandidateId))
            .ToArrayAsync();

        var clips = await db.ClipSubmissions
            .AsNoTracking()
            .Where(item => item.SeasonId == season.Id && item.SubmittedByTwitchId == session.TwitchUserId)
            .OrderByDescending(item => item.CreatedAt)
            .Take(12)
            .Select(item => new UserClipSubmissionStateDto(
                item.Id,
                item.CategoryId,
                item.ClipUrl,
                item.Title,
                item.Creator,
                item.Platform,
                item.Status,
                item.CreatedAt,
                item.ReviewNote,
                item.ReviewedAt))
            .ToArrayAsync();

        return Results.Ok(new UserParticipationResponse(
            season.Id,
            season.Year,
            groupedNominations,
            votes,
            clips));
    }
}
