using GermanApp.Application.DTOs; using GermanApp.Domain.Entities; using GermanApp.Domain.Exceptions; using GermanApp.Domain.Interfaces; namespace GermanApp.Application.UseCases.Commands; /// /// Command for creating a new quiz. /// This follows the CQRS pattern - commands represent write operations. /// public record CreateQuizCommand(CreateQuizDto QuizData) : ICommand; /// /// Handler for the CreateQuizCommand. /// public class CreateQuizCommandHandler : ICommandHandler { private readonly IQuizRepository _quizRepository; private readonly ILessonRepository _lessonRepository; public CreateQuizCommandHandler( IQuizRepository quizRepository, ILessonRepository lessonRepository) { _quizRepository = quizRepository; _lessonRepository = lessonRepository; } public async Task Handle(CreateQuizCommand command, CancellationToken cancellationToken) { // Validate that the lesson exists var lesson = await _lessonRepository.GetByIdAsync(command.QuizData.LessonId, cancellationToken); if (lesson == null) throw new NotFoundException("Lesson does not exist"); // Validate business rules if (command.QuizData.PassingScore < 0 || command.QuizData.PassingScore > 100) { throw new ValidationException("Passing score must be between 0 and 100"); } if (command.QuizData.TimeLimitMinutes < 0) { throw new ValidationException("Time limit cannot be negative"); } // Convert DTO to domain entity var quiz = command.QuizData.ToEntity(); // Add to repository var createdQuiz = await _quizRepository.AddAsync(quiz, cancellationToken); // Return DTO representation return createdQuiz.ToDto(); } } /// /// Command for updating an existing quiz. /// public record UpdateQuizCommand(int Id, UpdateQuizDto QuizData) : ICommand; /// /// Handler for the UpdateQuizCommand. /// public class UpdateQuizCommandHandler : ICommandHandler { private readonly IQuizRepository _quizRepository; private readonly ILessonRepository _lessonRepository; public UpdateQuizCommandHandler( IQuizRepository quizRepository, ILessonRepository lessonRepository) { _quizRepository = quizRepository; _lessonRepository = lessonRepository; } public async Task Handle(UpdateQuizCommand command, CancellationToken cancellationToken) { var quiz = await _quizRepository.GetByIdAsync(command.Id, cancellationToken); if (quiz == null) return null; // Validate that the lesson exists var lesson = await _lessonRepository.GetByIdAsync(command.QuizData.LessonId, cancellationToken); if (lesson == null) throw new NotFoundException("Lesson does not exist"); // Validate business rules if (command.QuizData.PassingScore < 0 || command.QuizData.PassingScore > 100) { throw new ValidationException("Passing score must be between 0 and 100"); } if (command.QuizData.TimeLimitMinutes < 0) { throw new ValidationException("Time limit cannot be negative"); } // Update the quiz quiz.UpdateFromDto(command.QuizData); await _quizRepository.UpdateAsync(quiz, cancellationToken); // Reload and return var updatedQuiz = await _quizRepository.GetByIdAsync(command.Id, cancellationToken); return updatedQuiz?.ToDto(); } } /// /// Command for deleting a quiz. /// public record DeleteQuizCommand(int Id) : ICommand; /// /// Handler for the DeleteQuizCommand. /// public class DeleteQuizCommandHandler : ICommandHandler { private readonly IQuizRepository _quizRepository; public DeleteQuizCommandHandler(IQuizRepository quizRepository) { _quizRepository = quizRepository; } public async Task Handle(DeleteQuizCommand command, CancellationToken cancellationToken) { var quiz = await _quizRepository.GetByIdAsync(command.Id, cancellationToken); if (quiz == null) return false; await _quizRepository.DeleteAsync(quiz, cancellationToken); return true; } } /// /// Command for getting a quiz with its questions. /// public record GetQuizWithQuestionsCommand(int Id) : ICommand; /// /// Handler for the GetQuizWithQuestionsCommand. /// public class GetQuizWithQuestionsCommandHandler : ICommandHandler { private readonly IQuizRepository _quizRepository; public GetQuizWithQuestionsCommandHandler(IQuizRepository quizRepository) { _quizRepository = quizRepository; } public async Task Handle(GetQuizWithQuestionsCommand command, CancellationToken cancellationToken) { var quiz = await _quizRepository.GetWithQuestionsAsync(command.Id, cancellationToken); return quiz?.ToQuizWithQuestionsDto(); } }