// Ported from golang/nats-server/server/monitor_test.go
// TestMonitorHealthzStatusOK — verify /healthz returns HTTP 200 with status "ok".

using System.Net;
using System.Net.Sockets;
using Microsoft.Extensions.Logging.Abstractions;

namespace NATS.Server.Tests;

public class HealthzParityTests : IAsyncLifetime
{
    private readonly NatsServer _server;
    private readonly int _monitorPort;
    private readonly CancellationTokenSource _cts = new();
    private readonly HttpClient _http = new();

    public HealthzParityTests()
    {
        _monitorPort = GetFreePort();
        _server = new NatsServer(
            new NatsOptions { Port = 0, MonitorPort = _monitorPort },
            NullLoggerFactory.Instance);
    }

    public async Task InitializeAsync()
    {
        _ = _server.StartAsync(_cts.Token);
        await _server.WaitForReadyAsync();
        for (var i = 0; i < 50; i++)
        {
            try
            {
                var probe = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/healthz");
                if (probe.IsSuccessStatusCode) break;
            }
            catch (HttpRequestException) { }
            await Task.Delay(50);
        }
    }

    public async Task DisposeAsync()
    {
        _http.Dispose();
        await _cts.CancelAsync();
        _server.Dispose();
    }

    /// <summary>
    /// Corresponds to Go TestMonitorHealthzStatusOK.
    /// Verifies GET /healthz returns HTTP 200 OK, indicating the server is healthy.
    /// </summary>
    [Fact]
    public async Task Healthz_returns_ok()
    {
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/healthz");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);
    }

    /// <summary>
    /// Corresponds to Go TestMonitorHealthzStatusOK / checkHealthStatus.
    /// Verifies the /healthz response body contains the "ok" status string,
    /// matching the Go server's HealthStatus.Status = "ok" field.
    /// </summary>
    [Fact]
    public async Task Healthz_returns_status_ok_json()
    {
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/healthz");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);

        var body = await response.Content.ReadAsStringAsync();
        // The .NET monitoring server returns Results.Ok("ok") which serializes as the JSON string "ok".
        // This corresponds to the Go server's HealthStatus.Status = "ok".
        body.ShouldContain("ok");
    }

    private static int GetFreePort()
    {
        using var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        sock.Bind(new IPEndPoint(IPAddress.Loopback, 0));
        return ((IPEndPoint)sock.LocalEndPoint!).Port;
    }
}
