using GermanApp.Application.DTOs; using GermanApp.Application.Services; using GermanApp.Domain.Entities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace GermanApp.Presentation.Controllers; /// /// API controller for managing quizzes. /// This is part of the Presentation layer. /// [ApiController] [Route("api/[controller]")] [Authorize] public class QuizzesController : ControllerBase { private readonly QuizService _quizService; private readonly QuizQuestionService _quizQuestionService; public QuizzesController( QuizService quizService, QuizQuestionService quizQuestionService) { _quizService = quizService; _quizQuestionService = quizQuestionService; } /// /// Gets all quizzes. /// /// List of all quizzes [HttpGet] [AllowAnonymous] public async Task GetAllQuizzesAsync(CancellationToken cancellationToken = default) { var quizzes = await _quizService.GetAllQuizzesAsync(cancellationToken); return Ok(quizzes); } /// /// Gets all quizzes as list items (summary). /// /// List of quiz summary items [HttpGet("list")] [AllowAnonymous] public async Task GetAllQuizListItemsAsync(CancellationToken cancellationToken = default) { var quizzes = await _quizService.GetAllQuizListItemsAsync(cancellationToken); return Ok(quizzes); } /// /// Gets a specific quiz by its ID. /// /// The quiz ID /// The quiz with the specified ID [HttpGet("{id}")] [AllowAnonymous] public async Task GetQuizByIdAsync(int id, CancellationToken cancellationToken = default) { var quiz = await _quizService.GetQuizByIdAsync(id, cancellationToken); if (quiz == null) return NotFound(); return Ok(quiz); } /// /// Gets a quiz with its questions by ID. /// /// The quiz ID /// The quiz with questions [HttpGet("{id}/with-questions")] [AllowAnonymous] public async Task GetQuizWithQuestionsAsync(int id, CancellationToken cancellationToken = default) { var quiz = await _quizService.GetQuizWithQuestionsAsync(id, cancellationToken); if (quiz == null) return NotFound(); return Ok(quiz); } /// /// Gets all quizzes for a specific lesson. /// /// The lesson ID /// List of quizzes for the specified lesson [HttpGet("by-lesson/{lessonId}")] [AllowAnonymous] public async Task GetQuizzesByLessonAsync(int lessonId, CancellationToken cancellationToken = default) { var quizzes = await _quizService.GetQuizzesByLessonAsync(lessonId, cancellationToken); return Ok(quizzes); } /// /// Gets active quizzes for a specific lesson. /// /// The lesson ID /// List of active quizzes for the specified lesson [HttpGet("active/by-lesson/{lessonId}")] [AllowAnonymous] public async Task GetActiveQuizzesByLessonAsync(int lessonId, CancellationToken cancellationToken = default) { var quizzes = await _quizService.GetActiveQuizzesByLessonAsync(lessonId, cancellationToken); return Ok(quizzes); } /// /// Gets the first quiz for a lesson. /// /// The lesson ID /// The first quiz for the lesson [HttpGet("first/by-lesson/{lessonId}")] [AllowAnonymous] public async Task GetFirstQuizByLessonAsync(int lessonId, CancellationToken cancellationToken = default) { var quiz = await _quizService.GetFirstQuizByLessonAsync(lessonId, cancellationToken); if (quiz == null) return NotFound(); return Ok(quiz); } /// /// Gets all active quizzes. /// /// List of active quizzes [HttpGet("active")] [AllowAnonymous] public async Task GetActiveQuizzesAsync(CancellationToken cancellationToken = default) { var quizzes = await _quizService.GetActiveQuizzesAsync(cancellationToken); return Ok(quizzes); } /// /// Creates a new quiz. /// /// The quiz data /// The created quiz [HttpPost] [Authorize(Roles = "Admin")] public async Task CreateQuizAsync(CreateQuizDto dto, CancellationToken cancellationToken = default) { var quiz = await _quizService.CreateQuizAsync(dto, cancellationToken); return CreatedAtAction(nameof(GetQuizByIdAsync), new { id = quiz.Id }, quiz); } /// /// Updates an existing quiz. /// /// The quiz ID /// The updated quiz data /// The updated quiz [HttpPut("{id}")] [Authorize(Roles = "Admin")] public async Task UpdateQuizAsync(int id, UpdateQuizDto dto, CancellationToken cancellationToken = default) { var quiz = await _quizService.UpdateQuizAsync(id, dto, cancellationToken); if (quiz == null) return NotFound(); return Ok(quiz); } /// /// Deletes a quiz by its ID. /// /// The quiz ID /// No content on success [HttpDelete("{id}")] [Authorize(Roles = "Admin")] public async Task DeleteQuizAsync(int id, CancellationToken cancellationToken = default) { var result = await _quizService.DeleteQuizAsync(id, cancellationToken); if (!result) return NotFound(); return NoContent(); } /// /// Activates a quiz. /// /// The quiz ID /// The activated quiz [HttpPost("{id}/activate")] [Authorize(Roles = "Admin")] public async Task ActivateQuizAsync(int id, CancellationToken cancellationToken = default) { var quiz = await _quizService.ActivateQuizAsync(id, cancellationToken); if (quiz == null) return NotFound(); return Ok(quiz); } /// /// Deactivates a quiz. /// /// The quiz ID /// The deactivated quiz [HttpPost("{id}/deactivate")] [Authorize(Roles = "Admin")] public async Task DeactivateQuizAsync(int id, CancellationToken cancellationToken = default) { var quiz = await _quizService.DeactivateQuizAsync(id, cancellationToken); if (quiz == null) return NotFound(); return Ok(quiz); } /// /// Checks if a quiz exists by ID. /// /// The quiz ID /// True if the quiz exists [HttpGet("exists/{id}")] [AllowAnonymous] public async Task ExistsAsync(int id, CancellationToken cancellationToken = default) { var exists = await _quizService.ExistsAsync(id, cancellationToken); return Ok(new { exists }); } /// /// Checks if a quiz exists for a lesson. /// /// The lesson ID /// True if a quiz exists for the lesson [HttpGet("exists/by-lesson/{lessonId}")] [AllowAnonymous] public async Task ExistsByLessonAsync(int lessonId, CancellationToken cancellationToken = default) { var exists = await _quizService.ExistsByLessonAsync(lessonId, cancellationToken); return Ok(new { lessonId, exists }); } /// /// Gets the total number of quizzes. /// /// The total count of quizzes [HttpGet("count")] [AllowAnonymous] public async Task GetTotalQuizCountAsync(CancellationToken cancellationToken = default) { var count = await _quizService.GetTotalQuizCountAsync(cancellationToken); return Ok(new { count }); } /// /// Gets the number of quizzes for a lesson. /// /// The lesson ID /// The count of quizzes for the lesson [HttpGet("count/by-lesson/{lessonId}")] [AllowAnonymous] public async Task GetQuizCountByLessonAsync(int lessonId, CancellationToken cancellationToken = default) { var count = await _quizService.GetQuizCountByLessonAsync(lessonId, cancellationToken); return Ok(new { lessonId, count }); } /// /// Gets quizzes by passing score range. /// /// Minimum passing score /// Maximum passing score /// List of quizzes in the score range [HttpGet("by-passing-score/{minScore}/{maxScore}")] [AllowAnonymous] public async Task GetQuizzesByPassingScoreRangeAsync(int minScore, int maxScore, CancellationToken cancellationToken = default) { var quizzes = await _quizService.GetQuizzesByPassingScoreRangeAsync(minScore, maxScore, cancellationToken); return Ok(quizzes); } /// /// Gets quiz questions for a specific quiz. /// /// The quiz ID /// List of quiz questions for the quiz [HttpGet("{quizId}/questions")] [AllowAnonymous] public async Task GetQuizQuestionsByQuizAsync(int quizId, CancellationToken cancellationToken = default) { var questions = await _quizQuestionService.GetQuizQuestionsByQuizAsync(quizId, cancellationToken); return Ok(questions); } /// /// Gets active quiz questions for a specific quiz. /// /// The quiz ID /// List of active quiz questions for the quiz [HttpGet("{quizId}/questions/active")] [AllowAnonymous] public async Task GetActiveQuizQuestionsByQuizAsync(int quizId, CancellationToken cancellationToken = default) { var questions = await _quizQuestionService.GetActiveQuizQuestionsByQuizAsync(quizId, cancellationToken); return Ok(questions); } /// /// Gets random quiz questions for a quiz. /// /// The quiz ID /// Number of questions to return /// List of random quiz questions [HttpGet("{quizId}/questions/random/{count}")] [AllowAnonymous] public async Task GetRandomQuizQuestionsForQuizAsync(int quizId, int count, CancellationToken cancellationToken = default) { var questions = await _quizQuestionService.GetRandomQuizQuestionsForQuizAsync(quizId, count, cancellationToken); return Ok(questions); } /// /// Submits quiz answers and returns the result. /// /// The user ID /// The quiz ID /// The quiz answers submission /// The quiz result [HttpPost("submit/{userId}/{quizId}")] [Authorize] public async Task SubmitQuizAnswersAsync(int userId, int quizId, SubmitQuizDto dto, CancellationToken cancellationToken = default) { // Update the submission to use the correct quizId var submission = new SubmitQuizDto(quizId, dto.Answers); var result = await _quizQuestionService.SubmitQuizAnswersForQuizAsync(userId, submission, cancellationToken); return Ok(result); } /// /// Gets the total points for a quiz. /// /// The quiz ID /// The total points for the quiz [HttpGet("{quizId}/total-points")] [AllowAnonymous] public async Task GetTotalPointsForQuizAsync(int quizId, CancellationToken cancellationToken = default) { var points = await _quizQuestionService.GetTotalPointsForQuizAsync(quizId, cancellationToken); return Ok(new { quizId, points }); } }