using System.Net;
using System.Text;
using Moq;
using Moq.Protected;
using NUnit.Framework;

namespace MicCheck.Client.Tests.Unit;

[TestFixture]
public class FeatureClientTests
{
    [Test]
    public async Task WhenFeatureIsEnabled_ThenIsEnabledAsyncReturnsTrue()
    {
        var client = CreateClient(HttpStatusCode.OK, """
            [{"id":1,"feature":{"id":1,"name":"my-feature","type":"STANDARD"},"enabled":true,"featureStateValue":null}]
            """);

        var result = await client.IsEnabledAsync("my-feature");

        Assert.That(result, Is.True);
    }

    [Test]
    public async Task WhenFeatureIsDisabled_ThenIsEnabledAsyncReturnsFalse()
    {
        var client = CreateClient(HttpStatusCode.OK, """
            [{"id":1,"feature":{"id":1,"name":"my-feature","type":"STANDARD"},"enabled":false,"featureStateValue":null}]
            """);

        var result = await client.IsEnabledAsync("my-feature");

        Assert.That(result, Is.False);
    }

    [Test]
    public async Task WhenFeatureNameDiffersOnlyByCase_ThenIsEnabledAsyncStillMatches()
    {
        var client = CreateClient(HttpStatusCode.OK, """
            [{"id":1,"feature":{"id":1,"name":"My-Feature","type":"STANDARD"},"enabled":true,"featureStateValue":null}]
            """);

        var result = await client.IsEnabledAsync("my-feature");

        Assert.That(result, Is.True);
    }

    [Test]
    public async Task WhenFeatureIsNotFound_ThenIsEnabledAsyncReturnsProvidedDefaultValue()
    {
        var client = CreateClient(HttpStatusCode.OK, "[]");

        var result = await client.IsEnabledAsync("missing-feature", defaultValue: true);

        Assert.That(result, Is.True);
    }

    [Test]
    public void WhenFeatureNameIsEmpty_ThenIsEnabledAsyncThrowsArgumentException()
    {
        var client = CreateClient(HttpStatusCode.OK, "[]");

        Assert.That(async () => await client.IsEnabledAsync(" "), Throws.ArgumentException);
    }

    private static FeatureClient CreateClient(HttpStatusCode responseStatus, string responseBody)
    {
        var handler = new Mock<HttpMessageHandler>();
        handler.Protected()
            .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
            .ReturnsAsync(new HttpResponseMessage(responseStatus)
            {
                Content = new StringContent(responseBody, Encoding.UTF8, "application/json")
            });

        var httpClient = new HttpClient(handler.Object) { BaseAddress = new Uri("https://example.com") };
        return new FeatureClient(httpClient);
    }
}
