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

namespace Backend.Endpoints;

public static partial class AdminSeasonManagementEndpoints
{
    private static async Task<IResult> GetSeasonDetail(int seasonId, AwardsDbContext db)
    {
        var season = await db.Seasons
            .AsNoTracking()
            .FirstOrDefaultAsync(item => item.Id == seasonId);

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

        var candidates = await db.Candidates
            .AsNoTracking()
            .Where(item => item.SeasonId == seasonId)
            .OrderBy(item => item.DisplayName)
            .Select(item => new AdminCandidateItemDto(
                item.Id,
                item.CategoryId,
                item.DisplayName,
                item.ChannelSlug,
                item.Platform))
            .ToArrayAsync();

        var candidateCounts = candidates
            .GroupBy(item => item.CategoryId)
            .ToDictionary(grouping => grouping.Key, grouping => grouping.Count());

        var categoryRows = await db.Categories
            .AsNoTracking()
            .Where(item => item.SeasonId == seasonId)
            .OrderBy(item => item.SortOrder)
            .ThenBy(item => item.Name)
            .Select(category => new
            {
                category.Id,
                category.GroupName,
                category.Name,
                category.Slug,
                category.Description,
                category.SortOrder,
                category.MaxNomineesPerUser,
            })
            .ToArrayAsync();

        var categories = categoryRows
            .Select(category => new AdminCategoryItemDto(
                category.Id,
                category.GroupName,
                category.Name,
                category.Slug,
                category.Description,
                category.SortOrder,
                category.MaxNomineesPerUser,
                candidateCounts.TryGetValue(category.Id, out var count) ? count : 0))
            .ToArray();

        var pendingNominations = await db.Nominations
            .AsNoTracking()
            .Where(item => item.SeasonId == seasonId && item.Status == "pending")
            .OrderByDescending(item => item.CreatedAt)
            .Select(item => new AdminNominationReviewItemDto(
                item.Id,
                item.CategoryId,
                item.Category.Name,
                item.SubmittedByTwitchId,
                item.CandidateText ?? string.Empty,
                item.StreamUrl,
                item.Status,
                item.CreatedAt,
                item.CandidateId,
                item.CandidateId != null ? item.Candidate!.DisplayName : null,
                item.ReviewNote,
                item.ReviewedByTwitchId,
                item.ReviewedAt))
            .ToArrayAsync();

        var reviewedNominations = await db.Nominations
            .AsNoTracking()
            .Where(item => item.SeasonId == seasonId && item.Status != "pending")
            .OrderByDescending(item => item.ReviewedAt ?? item.CreatedAt)
            .Select(item => new AdminNominationReviewItemDto(
                item.Id,
                item.CategoryId,
                item.Category.Name,
                item.SubmittedByTwitchId,
                item.CandidateText ?? (item.CandidateId != null ? item.Candidate!.DisplayName : string.Empty),
                item.StreamUrl,
                item.Status,
                item.CreatedAt,
                item.CandidateId,
                item.CandidateId != null ? item.Candidate!.DisplayName : null,
                item.ReviewNote,
                item.ReviewedByTwitchId,
                item.ReviewedAt))
            .ToArrayAsync();

        var resultItems = await db.Results
            .AsNoTracking()
            .Where(item => item.SeasonId == seasonId)
            .OrderBy(item => item.Category.SortOrder)
            .ThenBy(item => item.Category.Name)
            .Select(item => new AdminAwardResultItemDto(
                item.Id,
                item.CategoryId,
                item.Category.Name,
                item.CandidateId,
                item.Candidate.DisplayName,
                item.Candidate.ChannelSlug,
                item.Candidate.Platform))
            .ToArrayAsync();

        var clipSubmissions = await db.ClipSubmissions
            .AsNoTracking()
            .Where(item => item.SeasonId == seasonId)
            .OrderByDescending(item => item.CreatedAt)
            .Select(item => new AdminClipSubmissionItemDto(
                item.Id,
                item.CategoryId,
                item.CandidateId,
                item.SubmittedByTwitchId,
                item.ClipUrl,
                item.Title,
                item.Creator,
                item.Platform,
                item.Status,
                item.CreatedAt,
                item.ReviewNote,
                item.ReviewedByTwitchId,
                item.ReviewedAt))
            .ToArrayAsync();

        return Results.Ok(new AdminSeasonDetailResponse(
            season.Id,
            season.Year,
            season.Name,
            NormalizeSeasonStreamUrl(season.ShowStreamUrl),
            season.CurrentPhase,
            season.IsCurrent,
            season.IsCommunityOnly,
            season.NominationStartsAt,
            season.NominationEndsAt,
            season.VotingStartsAt,
            season.VotingEndsAt,
            season.ReviewStartsAt,
            season.ReviewEndsAt,
            season.ShowDate,
            season.ShowStartsAt,
            categories,
            candidates,
            pendingNominations,
            reviewedNominations,
            resultItems,
            clipSubmissions));
    }
}
