using System.Security.Claims; using System.Text.Json; using api.Data; using api.Features.Auth.Common; using api.Features.QRCodes.Common; using api.Features.QRCodes.Services; using FastEndpoints; using Microsoft.EntityFrameworkCore; namespace api.Features.QRCodes.Endpoints; public class PreviewQRCodeRequest { public Guid WorkspaceId { get; set; } public Guid Id { get; set; } public int? Size { get; set; } } public class PreviewQRCodeEndpoint(AppDbContext db, IQRCodeGeneratorService qrGenerator) : Endpoint { public override void Configure() { Get("/workspaces/{WorkspaceId}/qrcodes/{Id}/preview"); } public override async Task HandleAsync(PreviewQRCodeRequest req, CancellationToken ct) { var userId = Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!); var qrCode = await db.QrCodeDesigns .Include(q => q.ShortLink) .Where(q => q.Id == req.Id && q.WorkspaceId == req.WorkspaceId && q.Workspace.OwnerUserId == userId) .FirstOrDefaultAsync(ct); if (qrCode is null) { await HttpContext.Response.SendAsync(new MessageResponse("QR code not found"), 404, cancellation: ct); return; } if (qrCode.ShortLink is null) { await HttpContext.Response.SendAsync(new MessageResponse("QR code has no associated link"), 400, cancellation: ct); return; } var style = JsonSerializer.Deserialize(qrCode.StyleJson) ?? new QRCodeStyle(); var size = req.Size ?? 256; // Build the short link URL // TODO: Use actual domain configuration var baseUrl = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}"; var linkUrl = $"{baseUrl}/{qrCode.ShortLink.Slug}"; var dataUrl = qrGenerator.GenerateDataUrl(linkUrl, style, size); var response = new QRCodePreviewResponse( DataUrl: dataUrl, Format: "png", Width: size, Height: size ); await HttpContext.Response.SendAsync(response, 200, cancellation: ct); } }