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

namespace Backend.Endpoints;

public static partial class AdminSeasonManagementEndpoints
{
    private static async Task<IResult> UpdateSeason(
        HttpContext context,
        int seasonId,
        UpdateSeasonRequest request,
        AwardsDbContext db,
        IAdminAuditService adminAuditService)
    {
        var session = AdminEndpointConventions.CurrentSession(context);
        var season = await db.Seasons.FirstOrDefaultAsync(item => item.Id == seasonId);
        if (season is null)
        {
            return Results.NotFound();
        }

        var validationError = ValidateSeasonRequest(request);
        if (validationError is not null)
        {
            return validationError;
        }

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

        var wasCurrent = season.IsCurrent;
        var previousPhase = season.CurrentPhase;
        var previousPhaseKey = SeasonMappings.NormalizePhaseKey(previousPhase);
        var requestedPhaseKey = SeasonMappings.NormalizePhaseKey(request.CurrentPhase);
        var shouldValidateReadiness = request.IsCurrent
            || (string.Equals(requestedPhaseKey, "completed", StringComparison.Ordinal)
                && !string.Equals(previousPhaseKey, "completed", StringComparison.Ordinal));
        if (shouldValidateReadiness)
        {
            var readinessIssues = await BuildSeasonReadinessIssuesAsync(
                db,
                seasonId,
                request.CurrentPhase,
                request.IsCurrent,
                context.RequestAborted);
            if (readinessIssues.Length > 0)
            {
                return CreateReadinessError(readinessIssues);
            }
        }

        season.Year = request.Year;
        season.Name = request.Name.Trim();
        season.CurrentPhase = request.CurrentPhase.Trim();
        season.IsCommunityOnly = request.IsCommunityOnly;
        season.NominationStartsAt = request.NominationStartsAt;
        season.NominationEndsAt = request.NominationEndsAt;
        season.VotingStartsAt = request.VotingStartsAt;
        season.VotingEndsAt = request.VotingEndsAt;
        season.ReviewStartsAt = request.ReviewStartsAt;
        season.ReviewEndsAt = request.ReviewEndsAt;
        season.ShowDate = request.ShowDate;
        season.ShowStartsAt = request.ShowStartsAt;

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

        season.IsCurrent = request.IsCurrent;
        var actionType = "season.update";
        var summary = $"Season {season.Year} wurde aktualisiert.";
        if (!string.Equals(previousPhase.Trim(), season.CurrentPhase, StringComparison.OrdinalIgnoreCase))
        {
            actionType = "season.phase.update";
            summary = $"Phase fuer Season {season.Year} wurde auf {season.CurrentPhase} gesetzt.";
        }
        else if (wasCurrent != request.IsCurrent)
        {
            actionType = "season.public.update";
            summary = request.IsCurrent
                ? $"Season {season.Year} wurde als Public-Kontext aktiviert."
                : $"Season {season.Year} wurde aus dem Public-Kontext entfernt.";
        }

        adminAuditService.AddEntry(
            session.TwitchUserId,
            actionType,
            "season",
            season.Id.ToString(),
            summary,
            new
            {
                request.Year,
                request.Name,
                previousPhase,
                request.CurrentPhase,
                wasCurrent,
                request.IsCurrent,
                request.IsCommunityOnly,
                request.ShowDate,
                request.ShowStartsAt,
            },
            RequestMetadataReader.Read(context));

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