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

namespace Backend.Endpoints;

public static partial class PublicEndpoints
{
    private static async Task<IResult> GetOverview(AwardsDbContext db)
    {
        var siteSettings = await db.SiteSettings.AsNoTracking().FirstOrDefaultAsync(item => item.Id == 1);
        var season = await db.Seasons
            .AsNoTracking()
            .Include(item => item.Categories.OrderBy(category => category.SortOrder))
            .ThenInclude(category => category.Candidates)
            .OrderByDescending(item => item.Year)
            .FirstOrDefaultAsync(item => item.IsCurrent);

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

        if (siteSettings is null)
        {
            return Results.Problem("Site settings are missing.");
        }

        var winnerPreviewRows = await db.Results
            .AsNoTracking()
            .Include(result => result.Season)
            .Include(result => result.Candidate)
            .Where(result => result.Season.Year < season.Year)
            .OrderByDescending(result => result.Season.Year)
            .ThenBy(result => result.CategoryName)
            .Take(8)
            .Select(result => new
            {
                Year = result.Season.Year,
                result.CategoryName,
                WinnerName = result.Candidate.DisplayName,
                WinnerSlug = result.Candidate.ChannelSlug,
                WinnerPlatform = result.Candidate.Platform,
            })
            .ToArrayAsync();

        var winnerPreviewItems = winnerPreviewRows
            .Select(result => new WinnerPreviewDto(
                result.Year,
                result.CategoryName,
                result.WinnerName,
                result.WinnerSlug,
                result.WinnerPlatform,
                SeasonMappings.BuildProfileUrl(result.WinnerPlatform, result.WinnerSlug)))
            .ToArray();

        var archiveYearRows = await db.Results
            .AsNoTracking()
            .Where(result => result.Season.Year < season.Year)
            .GroupBy(result => result.Season.Year)
            .Select(group => new
            {
                Year = group.Key,
                WinnerCount = group.Count(),
            })
            .OrderByDescending(item => item.Year)
            .ToArrayAsync();

        var archiveYears = archiveYearRows
            .Select(item => new ArchiveYearDto(item.Year, item.WinnerCount))
            .ToArray();

        var phaseKey = SeasonMappings.NormalizePhaseKey(season.CurrentPhase);
        var publicCategories = season.Categories
            .Where(category => ShouldExposePublicCategory(phaseKey, category.Candidates.Count))
            .ToArray();
        var response = new OverviewResponse(
            season.Id,
            season.Year,
            season.Name,
            season.ShowDate,
            season.ShowStartsAt,
            SeasonMappings.NormalizeSeasonStreamUrl(season.ShowStreamUrl),
            season.CurrentPhase,
            season.IsCommunityOnly,
            "Twitch",
            new[]
            {
                new TimelineItem("nomination", "Nominierung", season.NominationStartsAt, season.NominationEndsAt, SeasonMappings.ResolveTimelineState("nomination", phaseKey)),
                new TimelineItem("voting", "Voting", season.VotingStartsAt, season.VotingEndsAt, SeasonMappings.ResolveTimelineState("voting", phaseKey)),
                new TimelineItem("preparation", "Aufbereitung", season.ReviewStartsAt, season.ReviewEndsAt, SeasonMappings.ResolveTimelineState("preparation", phaseKey)),
                new TimelineItem("show", "Award Show", season.ShowDate, season.ShowDate, SeasonMappings.ResolveTimelineState("show", phaseKey)),
            },
            publicCategories
                .Select(category => new FeaturedCategoryDto(
                    category.Id,
                    category.GroupName,
                    category.Name,
                    category.Description,
                    category.MaxNomineesPerUser))
                .ToArray(),
            winnerPreviewItems,
            archiveYears,
            new PublicSiteContentDto(
                siteSettings.HostDisplayName,
                siteSettings.HostTagline,
                siteSettings.NewsletterUrl,
                siteSettings.PrivacyEmail,
                siteSettings.PrivacyPolicyContent,
                SeasonMappings.ReadSocialLinks(siteSettings),
                SeasonMappings.BuildFooterLinks(siteSettings)),
            SeasonMappings.ReadFaqItems(siteSettings));

        return Results.Ok(response);
    }
}
