using GermanApp.Application.DTOs; using GermanApp.Application.UseCases.Commands; using GermanApp.Domain.Entities; using GermanApp.Domain.Interfaces; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace GermanApp.Presentation.Endpoints; /// /// Minimal API endpoints for Lesson resources. /// This is part of the Presentation layer. /// public static class LessonsEndpoints { public static void MapLessonsEndpoints(this WebApplication app) { var group = app.MapGroup("/api/lessons"); // GET /api/lessons group.MapGet("/", async ([FromServices] ILessonRepository repository) => { var lessons = await repository.GetAllAsync(); return Results.Ok(lessons.Select(l => l.ToDto())); }) .RequireAuthorization() .WithName("GetAllLessons") .WithOpenApi(operation => new(operation) { Summary = "Get all lessons", Description = "Retrieves all available German lessons" }); // GET /api/lessons/{id} group.MapGet("/{id}", async ([FromRoute] int id, [FromServices] ILessonRepository repository) => { var lesson = await repository.GetByIdAsync(id); return lesson is null ? Results.NotFound() : Results.Ok(lesson.ToDto()); }) .RequireAuthorization() .WithName("GetLessonById") .WithOpenApi(operation => new(operation) { Summary = "Get lesson by ID", Description = "Retrieves a specific lesson by its identifier" }); // GET /api/lessons/beginner group.MapGet("/beginner", async ([FromServices] ILessonRepository repository) => { // Beginner lessons are A1 (level 1) and A2 (level 2) var beginnerLessons = new List(); var level1Lessons = await repository.GetByLevelAsync(1); var level2Lessons = await repository.GetByLevelAsync(2); beginnerLessons.AddRange(level1Lessons); beginnerLessons.AddRange(level2Lessons); return Results.Ok(beginnerLessons.OrderBy(l => l.LevelId).ThenBy(l => l.Order).Select(l => l.ToDto())); }) .RequireAuthorization() .WithName("GetBeginnerLessons") .WithOpenApi(operation => new(operation) { Summary = "Get beginner lessons", Description = "Retrieves all lessons at beginner level (A1-A2)" }); // GET /api/lessons/advanced group.MapGet("/advanced", async ([FromServices] ILessonRepository repository) => { // Advanced lessons are B2 (level 4) and C1 (level 5) var advancedLessons = new List(); var level4Lessons = await repository.GetByLevelAsync(4); var level5Lessons = await repository.GetByLevelAsync(5); advancedLessons.AddRange(level4Lessons); advancedLessons.AddRange(level5Lessons); return Results.Ok(advancedLessons.OrderBy(l => l.LevelId).ThenBy(l => l.Order).Select(l => l.ToDto())); }) .RequireAuthorization() .WithName("GetAdvancedLessons") .WithOpenApi(operation => new(operation) { Summary = "Get advanced lessons", Description = "Retrieves all lessons at advanced level (B2-C1)" }); // GET /api/lessons/level/{level} group.MapGet("/level/{level}", async ([FromRoute] int level, [FromServices] ILessonRepository repository) => { var lessons = await repository.GetByLevelAsync(level); return Results.Ok(lessons.Select(l => l.ToDto())); }) .RequireAuthorization() .WithName("GetLessonsByLevel") .WithOpenApi(operation => new(operation) { Summary = "Get lessons by level", Description = "Retrieves all lessons at a specific proficiency level" }); // POST /api/lessons group.MapPost("/", async ( [FromBody] CreateLessonDto dto, [FromServices] ICommandHandler handler, CancellationToken cancellationToken) => { var command = new CreateLessonCommand(dto); var result = await handler.Handle(command, cancellationToken); return Results.Created($"/api/lessons/{result.Id}", result); }) .RequireAuthorization() .WithName("CreateLesson") .WithOpenApi(operation => new(operation) { Summary = "Create a new lesson", Description = "Creates a new German lesson" }); // PUT /api/lessons/{id} group.MapPut("/{id}", async ( [FromRoute] int id, [FromBody] UpdateLessonDto dto, [FromServices] ILessonRepository repository) => { var existingLesson = await repository.GetByIdAsync(id); if (existingLesson is null) return Results.NotFound(); // Map DTO to entity existingLesson.UpdateFromDto(dto); await repository.UpdateAsync(existingLesson); return Results.Ok(existingLesson.ToDto()); }) .RequireAuthorization() .WithName("UpdateLesson") .WithOpenApi(operation => new(operation) { Summary = "Update a lesson", Description = "Updates an existing lesson" }); // DELETE /api/lessons/{id} group.MapDelete("/{id}", async ([FromRoute] int id, [FromServices] ILessonRepository repository) => { var lesson = await repository.GetByIdAsync(id); if (lesson is null) return Results.NotFound(); await repository.DeleteAsync(lesson); return Results.NoContent(); }) .RequireAuthorization() .WithName("DeleteLesson") .WithOpenApi(operation => new(operation) { Summary = "Delete a lesson", Description = "Deletes a lesson by its identifier" }); } }