using System.Net.WebSockets;
using Newtonsoft.Json;
using Nostr.Client.Json;

namespace NostrRelay;

public static class Extensions
{
    public static void MapRelay<TRelay>(this WebApplication app, string path,
        RelayDocument? document = null,
        string? landingPage = null)
        where TRelay : INostrRelay, IDisposable
    {
        app.MapGet(path, async ctx =>
        {
            if (ctx.WebSockets.IsWebSocketRequest)
            {
                var logger = app.Services.GetRequiredService<ILogger<NostrRelay<TRelay>>>();
                using var handler = app.Services.GetRequiredService<TRelay>();
                try
                {
                    var ws = await ctx.WebSockets.AcceptWebSocketAsync();
                    var wsCtx = new NostrClientContext(ws, ctx.Connection.RemoteIpAddress!,
                        ctx.Request.Headers.UserAgent.FirstOrDefault() ?? string.Empty);

                    var nostrRelay = new NostrRelay<TRelay>(handler, wsCtx, ctx.RequestAborted, logger);

                    await nostrRelay.Read();

                    await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, null, ctx.RequestAborted);
                }
                catch (Exception ex)
                {
                    logger.LogDebug(ex.Message);
                }
            }
            else
            {
                var isRelayDocRequest = ctx.Request.Headers.Accept.FirstOrDefault()
                    ?.Equals("application/nostr+json", StringComparison.InvariantCultureIgnoreCase) ?? false;

                if (isRelayDocRequest)
                {
                    var doc = document ?? new RelayDocument
                    {
                        Name = typeof(TRelay).Name,
                        Description = "NostrServices C# Relay Framework",
                        Pubkey = "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed",
                        SupportedNips = [1],
                        Software = "NostrServices",
                        Icon = "https://void.cat/d/CtXsF5EvqNLG3K85TgezCt.webp",
                        Limitation = new()
                        {
                            RestrictedWrites = false,
                            AuthRequired = false,
                            PaymentRequired = false
                        }
                    };

                    if (ctx.Response.Headers.AccessControlAllowOrigin.Count == 0)
                    {
                        ctx.Response.Headers.AccessControlAllowOrigin = "*";
                    }

                    ctx.Response.ContentType = "application/json";
                    await ctx.Response.WriteAsync(JsonConvert.SerializeObject(doc, NostrSerializer.Settings));
                }
                else
                {
                    ctx.Response.ContentType = "text/html";
                    await ctx.Response.WriteAsync(landingPage ?? @$"
<html>
<head>
<title>NostrServices Relay</title>
</head>
<body>
<h1>Welcome to {typeof(TRelay).Name}</h1>
</body>
</html>
");
                }
            }
        });
    }
}
