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> SetResult(
        HttpContext context,
        int seasonId,
        SetAwardResultRequest request,
        AwardsDbContext db,
        IAdminAuditService adminAuditService)
    {
        var session = AdminEndpointConventions.CurrentSession(context);
        var category = await db.Categories
            .AsNoTracking()
            .FirstOrDefaultAsync(item => item.Id == request.CategoryId && item.SeasonId == seasonId);
        if (category is null)
        {
            return Results.BadRequest(new { message = "The selected category does not exist in this season." });
        }

        var candidate = await db.Candidates
            .AsNoTracking()
            .FirstOrDefaultAsync(item =>
                item.Id == request.CandidateId
                && item.SeasonId == seasonId
                && item.CategoryId == request.CategoryId);
        if (candidate is null)
        {
            return Results.BadRequest(new { message = "The selected candidate does not belong to the selected category." });
        }

        var existingResult = await db.Results.FirstOrDefaultAsync(item =>
            item.SeasonId == seasonId
            && item.CategoryId == request.CategoryId);

        if (existingResult is null)
        {
            existingResult = new AwardResult
            {
                SeasonId = seasonId,
                CategoryId = request.CategoryId,
                CandidateId = request.CandidateId,
                CategoryName = category.Name,
            };
            db.Results.Add(existingResult);
        }
        else
        {
            existingResult.CandidateId = request.CandidateId;
            existingResult.CategoryName = category.Name;
        }

        adminAuditService.AddEntry(
            session.TwitchUserId,
            "result.set",
            "result",
            $"{seasonId}:{request.CategoryId}",
            $"Gewinner für {category.Name} wurde gesetzt.",
            new
            {
                seasonId,
                categoryId = request.CategoryId,
                candidateId = request.CandidateId,
                candidateName = candidate.DisplayName,
            },
            RequestMetadataReader.Read(context));

        await db.SaveChangesAsync(context.RequestAborted);
        return Results.Ok(new
        {
            saved = true,
            resultId = existingResult.Id,
            seasonId,
            categoryId = request.CategoryId,
            candidateId = request.CandidateId,
        });
    }

    private static async Task<IResult> DeleteResult(
        HttpContext context,
        int resultId,
        AwardsDbContext db,
        IAdminAuditService adminAuditService)
    {
        var session = AdminEndpointConventions.CurrentSession(context);
        var result = await db.Results
            .Include(item => item.Category)
            .Include(item => item.Candidate)
            .FirstOrDefaultAsync(item => item.Id == resultId);
        if (result is null)
        {
            return Results.NotFound();
        }

        db.Results.Remove(result);
        adminAuditService.AddEntry(
            session.TwitchUserId,
            "result.delete",
            "result",
            result.Id.ToString(),
            $"Gewinner für {result.Category.Name} wurde entfernt.",
            new
            {
                result.SeasonId,
                result.CategoryId,
                result.CandidateId,
                candidateName = result.Candidate.DisplayName,
            },
            RequestMetadataReader.Read(context));

        await db.SaveChangesAsync(context.RequestAborted);
        return Results.Ok(new { deleted = true, resultId });
    }
}
