using System.Text.Json;
using FastEndpoints;

namespace SpaceGame.Api.Universe.Api;

public sealed class StreamWorldHandler(WorldService worldService) : EndpointWithoutRequest
{
    private static readonly JsonSerializerOptions SseJsonOptions = new(JsonSerializerDefaults.Web);

    public override void Configure()
    {
        Get("/api/world/stream");
        AllowAnonymous();
    }

    public override async Task HandleAsync(CancellationToken cancellationToken)
    {
        HttpContext.Response.Headers.Append("Cache-Control", "no-cache");
        HttpContext.Response.Headers.Append("Content-Type", "text/event-stream");

        var afterSequenceRaw = HttpContext.Request.Query["afterSequence"].ToString();
        _ = long.TryParse(afterSequenceRaw, out var afterSequence);

        var scopeKind = HttpContext.Request.Query["scopeKind"].ToString();
        if (string.IsNullOrWhiteSpace(scopeKind))
        {
            scopeKind = HttpContext.Request.Query["scope"].ToString();
        }

        if (string.IsNullOrWhiteSpace(scopeKind))
        {
            scopeKind = "universe";
        }

        var systemId = HttpContext.Request.Query["systemId"].ToString();
        var bubbleId = HttpContext.Request.Query["bubbleId"].ToString();
        var scope = new ObserverScope(
          scopeKind,
          string.IsNullOrWhiteSpace(systemId) ? null : systemId,
          string.IsNullOrWhiteSpace(bubbleId) ? null : bubbleId);
        var stream = worldService.Subscribe(scope, afterSequence, cancellationToken);

        await HttpContext.Response.WriteAsync(": connected\n\n", cancellationToken);
        await HttpContext.Response.Body.FlushAsync(cancellationToken);

        await foreach (var delta in stream.ReadAllAsync(cancellationToken))
        {
            var payload = JsonSerializer.Serialize(delta, SseJsonOptions);
            await HttpContext.Response.WriteAsync($"event: world-delta\ndata: {payload}\n\n", cancellationToken);
            await HttpContext.Response.Body.FlushAsync(cancellationToken);
        }
    }
}
