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 CreateCategory( HttpContext context, int seasonId, UpsertCategoryRequest request, AwardsDbContext db, IAdminAuditService adminAuditService) { var session = AdminEndpointConventions.CurrentSession(context); var validationError = ValidateCategoryRequest(request); if (validationError is not null) { return validationError; } var season = await db.Seasons.FirstOrDefaultAsync(item => item.Id == seasonId); if (season is null) { return Results.NotFound(); } var normalizedSlug = request.Slug.Trim(); if (await db.Categories.AnyAsync(item => item.SeasonId == seasonId && item.Slug.ToLower() == normalizedSlug.ToLower())) { return Results.BadRequest(new { message = "A category with this slug already exists in the selected season." }); } var category = new Category { SeasonId = seasonId, GroupName = request.GroupName.Trim(), Name = request.Name.Trim(), Slug = normalizedSlug, Description = request.Description.Trim(), SortOrder = request.SortOrder, MaxNomineesPerUser = request.MaxNomineesPerUser, ViewerRangeMin = request.ViewerRangeMin, ViewerRangeMax = request.ViewerRangeMax, }; db.Categories.Add(category); adminAuditService.AddEntry( session.TwitchUserId, "category.create", "category", request.Slug.Trim(), $"Kategorie {request.Name.Trim()} wurde angelegt.", new { seasonId, request.GroupName, request.SortOrder }, RequestMetadataReader.Read(context)); await db.SaveChangesAsync(context.RequestAborted); return Results.Ok(new { saved = true, categoryId = category.Id }); } private static async Task UpdateCategory( HttpContext context, int categoryId, UpsertCategoryRequest request, AwardsDbContext db, IAdminAuditService adminAuditService) { var session = AdminEndpointConventions.CurrentSession(context); var validationError = ValidateCategoryRequest(request); if (validationError is not null) { return validationError; } var category = await db.Categories.FirstOrDefaultAsync(item => item.Id == categoryId); if (category is null) { return Results.NotFound(); } var normalizedSlug = request.Slug.Trim(); if (await db.Categories.AnyAsync(item => item.SeasonId == category.SeasonId && item.Id != categoryId && item.Slug.ToLower() == normalizedSlug.ToLower())) { return Results.BadRequest(new { message = "A category with this slug already exists in the selected season." }); } category.GroupName = request.GroupName.Trim(); category.Name = request.Name.Trim(); category.Slug = normalizedSlug; category.Description = request.Description.Trim(); category.SortOrder = request.SortOrder; category.MaxNomineesPerUser = request.MaxNomineesPerUser; category.ViewerRangeMin = request.ViewerRangeMin; category.ViewerRangeMax = request.ViewerRangeMax; adminAuditService.AddEntry( session.TwitchUserId, "category.update", "category", category.Id.ToString(), $"Kategorie {request.Name.Trim()} wurde aktualisiert.", new { request.GroupName, request.SortOrder, request.MaxNomineesPerUser }, RequestMetadataReader.Read(context)); await db.SaveChangesAsync(context.RequestAborted); return Results.Ok(new { saved = true, categoryId = category.Id }); } private static async Task DeleteCategory( HttpContext context, int categoryId, AwardsDbContext db, IAdminAuditService adminAuditService) { var session = AdminEndpointConventions.CurrentSession(context); var category = await db.Categories.FirstOrDefaultAsync(item => item.Id == categoryId); if (category is null) { return Results.NotFound(); } var candidates = await db.Candidates.Where(item => item.CategoryId == categoryId).ToArrayAsync(); if (candidates.Length > 0) { db.Candidates.RemoveRange(candidates); } db.Categories.Remove(category); adminAuditService.AddEntry( session.TwitchUserId, "category.delete", "category", category.Id.ToString(), $"Kategorie {category.Name} wurde gelöscht.", new { removedCandidates = candidates.Length }, RequestMetadataReader.Read(context)); await db.SaveChangesAsync(context.RequestAborted); return Results.Ok(new { deleted = true, categoryId }); } }