using System.Net;
using System.Text;
using System.Text.Json;
using Inspectron.Epson.PrintServer.Telemetry;
using Microsoft.Extensions.Logging.Abstractions;

namespace Inspectron.Epson.Tests.Telemetry;

public class LoopbackInsinTelemetryTests
{
    private const int TestPort = 47823;

    [Fact]
    public async Task Emit_posts_json_payload_to_loopback()
    {
        using var listener = new HttpListener();
        listener.Prefixes.Add($"http://127.0.0.1:{TestPort}/");
        listener.Start();

        using var http = new HttpClient();
        var telemetry = new LoopbackInsinTelemetry(http, NullLogger.Instance);
        telemetry.Emit("service.started", "version=1.0.14");

        using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(3));
        var ctxTask = listener.GetContextAsync();
        var completed = await Task.WhenAny(ctxTask, Task.Delay(Timeout.Infinite, cts.Token));
        Assert.Same(ctxTask, completed);
        var ctx = ctxTask.Result;

        Assert.Equal("POST", ctx.Request.HttpMethod);
        Assert.Equal("/events", ctx.Request.Url!.AbsolutePath);
        using var sr = new StreamReader(ctx.Request.InputStream, Encoding.UTF8);
        var body = await sr.ReadToEndAsync();
        using var doc = JsonDocument.Parse(body);
        Assert.Equal("service.started", doc.RootElement.GetProperty("kind").GetString());
        Assert.Equal("version=1.0.14",   doc.RootElement.GetProperty("message").GetString());
        var at = doc.RootElement.GetProperty("at").GetString();
        Assert.False(string.IsNullOrEmpty(at));
        Assert.EndsWith("Z", at);

        ctx.Response.StatusCode = 200;
        ctx.Response.Close();
        listener.Stop();
    }

    [Fact]
    public async Task Emit_swallows_connection_refused_and_does_not_throw()
    {
        using var http = new HttpClient();
        var telemetry = new LoopbackInsinTelemetry(http, NullLogger.Instance);
        var ex = Record.Exception(() => telemetry.Emit("service.started", "version=1.0.14"));
        Assert.Null(ex);
        await Task.Delay(200);
    }

    [Fact]
    public async Task Emit_swallows_500_response_and_does_not_throw()
    {
        using var listener = new HttpListener();
        listener.Prefixes.Add($"http://127.0.0.1:{TestPort}/");
        listener.Start();

        using var http = new HttpClient();
        var telemetry = new LoopbackInsinTelemetry(http, NullLogger.Instance);
        telemetry.Emit("service.started", "version=1.0.14");

        var ctx = await listener.GetContextAsync();
        ctx.Response.StatusCode = 500;
        ctx.Response.Close();

        await Task.Delay(200);
        listener.Stop();
    }
}
