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();
}
}