using System.Text.Json; using Fitness_core_BE.Exceptions; using Fitness_core_BE.Helpers; using Fitness_core_BE.Infra.UoW; using Fitness_core_BE.Interfaces; using Fitness_core_BE.Interfaces.Services; using Fitness_core_BE.Models; using Fitness_core_BE.Models.IOs; namespace Fitness_core_BE.Services { public class AdminSuggestionService : IAdminSuggestionService { private readonly IAdminSuggestionRepository _repository; private readonly UserRoleHelper _userRoleHelper; private readonly IUnitOfWork _uow; public AdminSuggestionService(IAdminSuggestionRepository repository, UserRoleHelper userRoleHelper, IUnitOfWork uow) => (_repository, _userRoleHelper, _uow) = (repository, userRoleHelper, uow); public async Task ListAsync() { var (workouts, meals) = await _repository.GetPublishedAsync(); return new { workouts, meals }; } public async Task CreateWorkoutAsync(AdminWorkoutSuggestionRequest request, HttpContext httpContext) { await EnsureAdminAsync(httpContext); if (string.IsNullOrWhiteSpace(request.Name) || request.Days.Count == 0) throw new BadRequestException("Name and at least one workout day are required."); await _uow.BeginAsync(); try { var category = await GetWorkoutCategoryAsync(request.Category, request.CategoryDescription); var plan = new WorkoutPlan { WorkoutPlanId = Guid.NewGuid(), WorkoutPlanName = request.Name.Trim(), Description = request.Description, FKWorkoutCategoryId = category.WorkoutCategoryId, IsTemplate = true, IsActive = true, CreateDate = DateTime.UtcNow }; foreach (var day in request.Days.Where(d => !string.IsNullOrWhiteSpace(d.Day))) { var item = new WorkoutItem { WorkoutItemId = Guid.NewGuid(), ExerciseDay = day.Day.Trim(), Description = day.Description, Exercises = JsonSerializer.Serialize(day.Exercises), HowToDo = JsonSerializer.Serialize(new { suitableFor = day.SuitableFor, exercises = day.Exercises }), Duration = day.Duration, WormUp = day.WarmUp, Cooldown = day.Cooldown, IsActive = true, CreateDate = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; var order = 1; foreach (var exercise in day.Exercises.Where(e => !string.IsNullOrWhiteSpace(e.Name))) { item.WorkoutExercises.Add(new WorkoutExercise { WorkoutExerciseId = Guid.NewGuid(), Name = exercise.Name.Trim(), MuscleGroup = exercise.Position, Sets = exercise.Sets, Reps = exercise.Reps, Description = exercise.Description, BreathIn = exercise.BreathIn, BreathOut = exercise.BreathOut, VideoUrl = exercise.VideoUrl, SortOrder = order++, IsActive = true, CreateDate = DateTime.UtcNow }); } plan.WorkoutItems.Add(item); } await _repository.AddWorkoutAsync(plan); await _uow.CommitAsync(); return new { plan.WorkoutPlanId, numberOfDays = plan.WorkoutItems.Count }; } catch { await _uow.RollbackAsync(); throw; } } public async Task CreateMealAsync(AdminMealSuggestionRequest request, HttpContext httpContext) { await EnsureAdminAsync(httpContext); if (string.IsNullOrWhiteSpace(request.Name) || request.Meals.Count == 0) throw new BadRequestException("Name and at least one meal are required."); await _uow.BeginAsync(); try { var category = await GetMealCategoryAsync(request.Category, request.CategoryDescription); var plan = new MealPlan { MealPlanId = Guid.NewGuid(), Name = request.Name.Trim(), Description = request.Description, FKMealCategoryId = category.MealCategoryId, IsTemplate = true, IsActive = true, CreateDate = DateTime.UtcNow }; foreach (var meal in request.Meals.Where(m => !string.IsNullOrWhiteSpace(m.Name))) plan.MealItems.Add(new Models.Meal { MealId = Guid.NewGuid(), Name = meal.Name.Trim(), Description = meal.Description, Calories = meal.Calories, Protein = meal.Protein, Carbohydrates = meal.Carbohydrates, Fats = meal.Fats, ServingSize = meal.ServingSize, MealItems = JsonSerializer.Serialize(meal.Foods), PreparationNotes = meal.PreparationNotes, IsActive = true, CreateDate = DateTime.UtcNow }); await _repository.AddMealAsync(plan); await _uow.CommitAsync(); return new { plan.MealPlanId, mealCount = plan.MealItems.Count }; } catch { await _uow.RollbackAsync(); throw; } } private async Task EnsureAdminAsync(HttpContext context) { var id = DataExtractor.GetUserIdFromContext(context); if ((await _userRoleHelper.GetAdminId(id).ConfigureAwait(false)) is not Guid) throw new ForbiddenException("Only admins can manage platform suggestions."); } private async Task GetWorkoutCategoryAsync(string name, string? description) { name = string.IsNullOrWhiteSpace(name) ? "General Fitness" : name.Trim(); var category = await _repository.FindWorkoutCategoryAsync(name); if (category != null) return category; category = new WorkoutCategory { WorkoutCategoryId = Guid.NewGuid(), WorkoutCategoryName = name, Description = description, IsActive = true, CreateDate = DateTime.UtcNow }; await _repository.AddWorkoutCategoryAsync(category); return category; } private async Task GetMealCategoryAsync(string name, string? description) { name = string.IsNullOrWhiteSpace(name) ? "Balanced Nutrition" : name.Trim(); var category = await _repository.FindMealCategoryAsync(name); if (category != null) return category; category = new MealCategory { MealCategoryId = Guid.NewGuid(), Name = name, Description = description, IsActive = true, CreateDate = DateTime.UtcNow }; await _repository.AddMealCategoryAsync(category); return category; } } }