using Novelly.Api.Common; using Novelly.Api.Common.Validation; namespace Novelly.Api.Chapters; public static class ChapterEndpoints { public static IEndpointRouteBuilder MapChapterEndpoints(this IEndpointRouteBuilder app) { var novelScoped = app.MapGroup("/api/novels/{novelId:guid}/chapters").WithTags("Chapters") .AddEndpointFilter() .AddEndpointFilter(); novelScoped.MapGet("/", async (Guid novelId, ChapterService service, CancellationToken ct) => { var chapters = await service.ListAsync(novelId, ct); var displayNumbers = ChapterNumbering.DisplayNumbers(chapters); return Results.Ok(chapters.Select(c => c.ToSummaryResponse(displayNumbers.TryGetValue(c.Id, out var n) ? n : null))); }) .WithSummary("List a novel's chapters in manuscript order."); novelScoped.MapPost("/", async ( Guid novelId, CreateChapterRequest request, ChapterService service, CancellationToken ct) => { var chapter = await service.CreateAsync(novelId, request, ct); if (chapter is null) { return Results.NotFound(); } var displayNumber = await service.DisplayNumberAsync(chapter, ct); var created = chapter.ToResponse(displayNumber); return Results.Created($"/api/chapters/{created.Id}", created); }) .WithSummary("Add a chapter."); var chapters = app.MapGroup("/api/chapters").WithTags("Chapters") .AddEndpointFilter() .AddEndpointFilter(); chapters.MapGet("/{id:guid}", async (Guid id, ChapterService service, CancellationToken ct) => { var chapter = await service.GetAsync(id, ct); if (chapter is null) { return Results.NotFound(); } var displayNumber = await service.DisplayNumberAsync(chapter, ct); return chapter.ToResponse(displayNumber).ToApiResult(); }) .WithSummary("Read a chapter with its beats and prose."); chapters.MapPatch("/{id:guid}", async ( Guid id, UpdateChapterRequest request, ChapterService service, CancellationToken ct) => { var chapter = await service.UpdateAsync(id, request, ct); if (chapter is null) { return Results.NotFound(); } var displayNumber = await service.DisplayNumberAsync(chapter, ct); return chapter.ToResponse(displayNumber).ToApiResult(); }) .WithSummary("Update a chapter."); chapters.MapDelete("/{id:guid}", async (Guid id, ChapterService service, CancellationToken ct) => await service.DeleteAsync(id, ct) ? Results.NoContent() : Results.NotFound()) .WithSummary("Move a chapter to the trash."); return app; } }