using System.Net.Http.Headers;
using Newtonsoft.Json;
using Nostr.Client.Json;
using Nostr.Client.Messages;

namespace NostrServices.Client;

public class NostrServicesClient
{
    private readonly HttpClient _client;

    public NostrServicesClient(HttpClient client)
    {
        _client = client;
        _client.BaseAddress = new Uri("https://nostr.api.v0l.io");
        _client.Timeout = TimeSpan.FromSeconds(60);
    }

    public async Task<CompactProfile?> Profile(string id)
    {
        return await Get<CompactProfile>(HttpMethod.Get, $"https://nostr-rs.api.v0l.io/event/0/{id}");
    }

    public async Task<NostrEvent?> Event(string id)
    {
        return await Get<NostrEvent>(HttpMethod.Get, $"https://nostr-rs.api.v0l.io/event/{id}");
    }

    public async Task<LinkPreviewData?> LinkPreview(string url)
    {
        return await Get<LinkPreviewData>(HttpMethod.Get, $"/api/v1/preview?url={Uri.EscapeDataString(url)}");
    }

    public async Task<List<RelayDistance>?> CloseRelays(double lat, double lon, int count = 5)
    {
        return await Get<List<RelayDistance>>(HttpMethod.Post, $"/api/v1/relays?count={count}", new {lat, lon});
    }

    public async Task<List<RelayDistance>?> TopRelays(int count = 5)
    {
        return await Get<List<RelayDistance>>(HttpMethod.Get, $"/api/v1/relays/top?count={count}");
    }

    public async Task<List<PubKeyStat>?> GetStats()
    {
        return await Get<List<PubKeyStat>>(HttpMethod.Get, "/api/v1/pubkeys");
    }

    private async Task<T?> Get<T>(HttpMethod method, string path, object? body = null)
    {
        var req = new HttpRequestMessage(method, path);
        if (body != null)
        {
            req.Content = new StringContent(JsonConvert.SerializeObject(body, NostrSerializer.Settings),
                new MediaTypeHeaderValue("application/json"));
        }

        var rsp = await _client.SendAsync(req);
        if (rsp.IsSuccessStatusCode)
        {
            var json = await rsp.Content.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<T>(json, NostrSerializer.Settings);
        }

        return default;
    }
}
