using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; using WorkClub.Api.Services; using WorkClub.Application.Tasks.DTOs; namespace WorkClub.Api.Endpoints.Tasks; public static class TaskEndpoints { public static void MapTaskEndpoints(this IEndpointRouteBuilder app) { var group = app.MapGroup("/api/tasks"); group.MapGet("", GetTasks) .RequireAuthorization("RequireMember") .WithName("GetTasks"); group.MapGet("{id:guid}", GetTask) .RequireAuthorization("RequireMember") .WithName("GetTask"); group.MapPost("", CreateTask) .RequireAuthorization("RequireManager") .WithName("CreateTask"); group.MapPatch("{id:guid}", UpdateTask) .RequireAuthorization("RequireMember") .WithName("UpdateTask"); group.MapDelete("{id:guid}", DeleteTask) .RequireAuthorization("RequireAdmin") .WithName("DeleteTask"); group.MapPost("{id:guid}/assign", AssignTaskToMe) .RequireAuthorization("RequireMember") .WithName("AssignTaskToMe"); group.MapDelete("{id:guid}/assign", UnassignTaskFromMe) .RequireAuthorization("RequireMember") .WithName("UnassignTaskFromMe"); } private static async Task> GetTasks( TaskService taskService, HttpContext httpContext, [FromQuery] string? status = null, [FromQuery] int page = 1, [FromQuery] int pageSize = 20) { var externalUserId = httpContext.User.FindFirst("sub")?.Value; var result = await taskService.GetTasksAsync(status, page, pageSize, externalUserId); return TypedResults.Ok(result); } private static async Task, NotFound>> GetTask( Guid id, TaskService taskService, HttpContext httpContext) { var externalUserId = httpContext.User.FindFirst("sub")?.Value; var result = await taskService.GetTaskByIdAsync(id, externalUserId); if (result == null) return TypedResults.NotFound(); return TypedResults.Ok(result); } private static async Task, BadRequest>> CreateTask( CreateTaskRequest request, TaskService taskService, HttpContext httpContext) { var userIdClaim = httpContext.User.FindFirst("sub")?.Value; if (string.IsNullOrEmpty(userIdClaim) || !Guid.TryParse(userIdClaim, out var createdById)) { return TypedResults.BadRequest("Invalid user ID"); } var (task, error) = await taskService.CreateTaskAsync(request, createdById); if (error != null || task == null) return TypedResults.BadRequest(error ?? "Failed to create task"); return TypedResults.Created($"/api/tasks/{task.Id}", task); } private static async Task, NotFound, UnprocessableEntity, Conflict>> UpdateTask( Guid id, UpdateTaskRequest request, TaskService taskService, HttpContext httpContext) { var externalUserId = httpContext.User.FindFirst("sub")?.Value; var (task, error, isConflict) = await taskService.UpdateTaskAsync(id, request, externalUserId); if (error != null) { if (error == "Task not found") return TypedResults.NotFound(); if (isConflict) return TypedResults.Conflict(error); return TypedResults.UnprocessableEntity(error); } return TypedResults.Ok(task!); } private static async Task> DeleteTask( Guid id, TaskService taskService) { var deleted = await taskService.DeleteTaskAsync(id); if (!deleted) return TypedResults.NotFound(); return TypedResults.NoContent(); } private static async Task, NotFound>> AssignTaskToMe( Guid id, TaskService taskService, HttpContext httpContext) { var externalUserId = httpContext.User.FindFirst("sub")?.Value; if (externalUserId == null) return TypedResults.BadRequest("Invalid user"); var (success, error) = await taskService.AssignToMeAsync(id, externalUserId); if (!success) { if (error == "Task not found") return TypedResults.NotFound(); return TypedResults.BadRequest(error ?? "Failed to assign task"); } return TypedResults.Ok(); } private static async Task, NotFound>> UnassignTaskFromMe( Guid id, TaskService taskService, HttpContext httpContext) { var externalUserId = httpContext.User.FindFirst("sub")?.Value; if (externalUserId == null) return TypedResults.BadRequest("Invalid user"); var (success, error) = await taskService.UnassignFromMeAsync(id, externalUserId); if (!success) { if (error == "Task not found") return TypedResults.NotFound(); return TypedResults.BadRequest(error ?? "Failed to unassign task"); } return TypedResults.Ok(); } }