using GerbilManagerWebAPI.Models; using GerbilManagerWebAPI.Push; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.EntityFrameworkCore; namespace GerbilManagerWebAPI.Endpoints { /// /// WEB-PUSH: PWA-Benachrichtigungen für die Züchterin. /// GET /push/vapid-public-key -> öffentlicher VAPID-Schlüssel (für das Abonnieren im Browser). /// POST /push/subscribe -> Browser-Abo speichern (idempotent über die Endpoint-URL). /// POST /push/unsubscribe -> Abo entfernen. /// Das eigentliche Senden passiert über (z. B. wenn die KI eine /// Rückfrage stellt oder ein Ticket löst — gesteuert über das notify-Flag auf PUT /feedback). /// public static class PushEndpoints { public record PushSubscriptionInput(string Endpoint, string P256dh, string Auth); public record PushUnsubscribeInput(string Endpoint); public static IEndpointRouteBuilder MapPushEndpoints(this IEndpointRouteBuilder app) { var group = app.MapGroup("/push").WithTags("Push"); group.MapGet("/vapid-public-key", (PushNotifier push) => TypedResults.Ok(new { publicKey = push.PublicKey, enabled = push.Enabled })); group.MapPost("/subscribe", async Task>> ( PushSubscriptionInput input, ApplicationContext db) => { if (string.IsNullOrWhiteSpace(input.Endpoint) || string.IsNullOrWhiteSpace(input.P256dh) || string.IsNullOrWhiteSpace(input.Auth)) return TypedResults.BadRequest("Endpoint, P256dh und Auth sind erforderlich."); var existing = await db.WebPushSubscriptions .FirstOrDefaultAsync(s => s.Endpoint == input.Endpoint); if (existing is null) { db.WebPushSubscriptions.Add(new WebPushSubscription { Id = Guid.NewGuid(), Endpoint = input.Endpoint, P256dh = input.P256dh, Auth = input.Auth, CreatedAt = DateTimeOffset.UtcNow, }); } else { existing.P256dh = input.P256dh; existing.Auth = input.Auth; } await db.SaveChangesAsync(); return TypedResults.Ok(); }); group.MapPost("/unsubscribe", async (PushUnsubscribeInput input, ApplicationContext db) => { var subs = await db.WebPushSubscriptions .Where(s => s.Endpoint == input.Endpoint) .ToListAsync(); if (subs.Count > 0) { db.WebPushSubscriptions.RemoveRange(subs); await db.SaveChangesAsync(); } return TypedResults.NoContent(); }); return app; } } }