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

namespace Backend.Endpoints;

public static partial class AdminSeasonManagementEndpoints
{
    private static async Task<IResult> CreateSeason(
        HttpContext context,
        CreateSeasonRequest request,
        AwardsDbContext db,
        IAdminAuditService adminAuditService)
    {
        var session = AdminEndpointConventions.CurrentSession(context);
        var validationError = ValidateSeasonRequest(request);
        if (validationError is not null)
        {
            return validationError;
        }

        if (await db.Seasons.AnyAsync(item => item.Year == request.Year))
        {
            return Results.BadRequest(new { message = $"A season for {request.Year} already exists." });
        }

        var settings = await db.SiteSettings
            .AsNoTracking()
            .FirstOrDefaultAsync(item => item.Id == 1, context.RequestAborted);
        var initialWorkflowRulesJson = WorkflowRuleSettings.Serialize(WorkflowRuleSettings.Read(settings));

        var season = new Season
        {
            Year = request.Year,
            Name = request.Name.Trim(),
            IsDemo = false,
            CurrentPhase = request.CurrentPhase.Trim(),
            IsCurrent = request.IsCurrent,
            IsCommunityOnly = request.IsCommunityOnly,
            NominationStartsAt = request.NominationStartsAt,
            NominationEndsAt = request.NominationEndsAt,
            VotingStartsAt = request.VotingStartsAt,
            VotingEndsAt = request.VotingEndsAt,
            ReviewStartsAt = request.ReviewStartsAt,
            ReviewEndsAt = request.ReviewEndsAt,
            ShowDate = request.ShowDate,
            ShowStartsAt = request.ShowStartsAt,
            SubcategoryTemplatesJson = "[]",
            WorkflowRulesJson = initialWorkflowRulesJson,
        };

        db.Seasons.Add(season);
        var copiedCategoryCount = 0;
        if (request.CopyStructureFromSeasonId is { } sourceSeasonId)
        {
            if (sourceSeasonId <= 0)
            {
                return Results.BadRequest(new { message = "A valid source season is required for copying structure." });
            }

            var sourceSeasonExists = await db.Seasons
                .AsNoTracking()
                .AnyAsync(item => item.Id == sourceSeasonId, context.RequestAborted);
            if (!sourceSeasonExists)
            {
                return Results.BadRequest(new { message = "Source season for structure copy was not found." });
            }

            var sourceCategories = await db.Categories
                .AsNoTracking()
                .Where(item => item.SeasonId == sourceSeasonId)
                .OrderBy(item => item.SortOrder)
                .ThenBy(item => item.Name)
                .ToArrayAsync(context.RequestAborted);

            copiedCategoryCount = sourceCategories.Length;
            var sourceSeason = await db.Seasons
                .AsNoTracking()
                .FirstAsync(item => item.Id == sourceSeasonId, context.RequestAborted);
            season.SubcategoryTemplatesJson = sourceSeason.SubcategoryTemplatesJson;
            season.WorkflowRulesJson = string.IsNullOrWhiteSpace(sourceSeason.WorkflowRulesJson)
                ? initialWorkflowRulesJson
                : sourceSeason.WorkflowRulesJson;
            foreach (var category in sourceCategories)
            {
                db.Categories.Add(new Category
                {
                    Season = season,
                    GroupName = category.GroupName,
                    Name = category.Name,
                    Slug = category.Slug,
                    Description = category.Description,
                    SortOrder = category.SortOrder,
                    MaxNomineesPerUser = category.MaxNomineesPerUser,
                    ViewerRangeMin = category.ViewerRangeMin,
                    ViewerRangeMax = category.ViewerRangeMax,
                });
            }
        }

        var readinessIssues = BuildNewSeasonReadinessIssues(
            request.CurrentPhase,
            request.IsCurrent,
            copiedCategoryCount);
        if (readinessIssues.Length > 0)
        {
            return CreateReadinessError(readinessIssues);
        }

        await UnsetOtherCurrentSeasonsAsync(db, request.IsCurrent, null, context.RequestAborted);

        adminAuditService.AddEntry(
            session.TwitchUserId,
            "season.create",
            "season",
            request.Year.ToString(),
            copiedCategoryCount > 0
                ? $"Season {request.Year} wurde angelegt und {copiedCategoryCount} Kategorien wurden kopiert."
                : $"Season {request.Year} wurde angelegt.",
            new
            {
                request.IsCurrent,
                request.IsCommunityOnly,
                request.CurrentPhase,
                request.ShowDate,
                request.ShowStartsAt,
                request.CopyStructureFromSeasonId,
                copiedCategoryCount,
            },
            RequestMetadataReader.Read(context));

        await db.SaveChangesAsync(context.RequestAborted);
        return Results.Ok(new { saved = true, seasonId = season.Id, copiedCategoryCount });
    }
}
