using System.Net;
using System.Text;
using ZB.MOM.WW.ScadaBridge.DelmiaNotifier;

namespace ZB.MOM.WW.ScadaBridge.DelmiaNotifier.Tests;

public class HttpRecipeSenderTests
{
    private sealed class StubHandler(Func<HttpRequestMessage, HttpResponseMessage> responder) : HttpMessageHandler
    {
        public HttpRequestMessage? LastRequest { get; private set; }

        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            LastRequest = request;
            return Task.FromResult(responder(request));
        }
    }

    private static readonly RecipeDownload Payload =
        new() { MachineCode = "Z", DownloadPath = "x", WorkOrderNumber = "W", PartNumber = "P" };

    [Fact]
    public async Task ConnectFailure_maps_to_ConnectFailed()
    {
        var handler = new StubHandler(_ => throw new HttpRequestException("refused"));
        using var http = new HttpClient(handler);
        var sender = new HttpRecipeSender(http, "sbk_x");
        var outcome = await sender.SendAsync("http://a", Payload, CancellationToken.None);
        Assert.Equal(AttemptKind.ConnectFailed, outcome.Kind);
        Assert.Equal(0, outcome.StatusCode);
    }

    [Fact]
    public async Task Success_200_parses_body_and_sends_header_and_path()
    {
        var handler = new StubHandler(_ => new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new StringContent("{\"Result\":true,\"ResultText\":\"\"}", Encoding.UTF8, "application/json"),
        });
        using var http = new HttpClient(handler);
        var sender = new HttpRecipeSender(http, "sbk_x");
        var outcome = await sender.SendAsync("http://a/", Payload, CancellationToken.None);
        Assert.Equal(AttemptKind.Connected, outcome.Kind);
        Assert.Equal(200, outcome.StatusCode);
        Assert.NotNull(outcome.Body);
        Assert.True(outcome.Body!.Result);
        Assert.Equal("sbk_x", handler.LastRequest!.Headers.GetValues("X-API-Key").Single());
        Assert.Equal("http://a/api/DelmiaRecipeDownload", handler.LastRequest.RequestUri!.ToString());
    }

    [Fact]
    public async Task Non2xx_is_Connected_with_status()
    {
        var handler = new StubHandler(_ => new HttpResponseMessage(HttpStatusCode.InternalServerError));
        using var http = new HttpClient(handler);
        var sender = new HttpRecipeSender(http, "sbk_x");
        var outcome = await sender.SendAsync("http://a", Payload, CancellationToken.None);
        Assert.Equal(AttemptKind.Connected, outcome.Kind);
        Assert.Equal(500, outcome.StatusCode);
    }
}
