using Knot.Shared.Kernel; using Knot.Modules.Profiles.Application.Profiles.Avatar; using Knot.Modules.Profiles.Application.Profiles.GetProfile; using Knot.Modules.Profiles.Application.Profiles.Search; using Knot.Modules.Profiles.Application.Profiles.UpdateProfile; using Knot.Modules.Profiles.Application.Profiles.UpdateSettings; using MediatR; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Mvc; namespace Knot.Modules.Profiles.Presentation.Endpoints; public static class ProfilesEndpoints { public static void MapProfilesEndpoints(this WebApplication app) { var group = app.MapGroup("api/profiles").RequireAuthorization(); group.MapGet("search", async ([FromQuery] string q, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new SearchProfilesQuery(q, userContext.UserId), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.BadRequest(result.Error); }); group.MapPut("settings", async ([FromBody] Knot.Modules.Profiles.Application.Profiles.DTOs.UpdateSettingsRequest request, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new UpdateSettingsCommand(userContext.UserId, request.HideStoryViews), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(result.Error); }); group.MapPost("avatar", async (HttpRequest req, ISender sender, IUserContext userContext, CancellationToken ct) => { if (!req.HasFormContentType) return Results.BadRequest("No file uploaded"); var form = await req.ReadFormAsync(ct); var file = form.Files.FirstOrDefault(); if (file == null || file.Length == 0) return Results.BadRequest("No file uploaded"); using var stream = file.OpenReadStream(); var result = await sender.Send(new UploadAvatarCommand(userContext.UserId, stream, file.FileName, file.ContentType), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(result.Error); }).DisableAntiforgery(); group.MapPost("avatar/crop", async (HttpRequest req, ISender sender, IUserContext userContext, CancellationToken ct) => { if (!req.HasFormContentType) return Results.BadRequest("No file uploaded"); var form = await req.ReadFormAsync(ct); var file = form.Files.FirstOrDefault(); if (file == null || file.Length == 0) return Results.BadRequest("No file uploaded"); int.TryParse(form["x"], out int x); int.TryParse(form["y"], out int y); int.TryParse(form["width"], out int width); int.TryParse(form["height"], out int height); int.TryParse(form["sw"], out int sw); int.TryParse(form["sh"], out int sh); using var stream = file.OpenReadStream(); var result = await sender.Send(new CropAvatarCommand(userContext.UserId, stream, file.FileName ?? "avatar.jpg", file.ContentType, x, y, width, height, sw, sh), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(result.Error); }).DisableAntiforgery(); group.MapDelete("avatar", async (ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new DeleteAvatarCommand(userContext.UserId), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(result.Error); }); group.MapPut("profile", async ([FromBody] Knot.Modules.Profiles.Application.Profiles.DTOs.UpdateProfileRequest request, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new UpdateProfileCommand(userContext.UserId, request.DisplayName, request.Bio, request.Birthday), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(result.Error); }); group.MapGet("{id:guid}", async (Guid id, ISender sender, CancellationToken ct) => { var result = await sender.Send(new GetProfileQuery(id), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(result.Error); }); } }