using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using NSubstitute;
using ScadaLink.Communication;
using ScadaLink.Communication.Grpc;

namespace ScadaLink.Communication.Tests.Grpc;

/// <summary>
/// Regression tests for Communication-005 — the gRPC keepalive and
/// max-stream-lifetime / max-concurrent-stream options defined on
/// <see cref="CommunicationOptions"/> must actually be applied to the
/// gRPC client and server rather than hard-coded.
/// </summary>
public class GrpcOptionsWiringTests
{
    [Fact]
    public void SiteStreamGrpcClient_AppliesKeepAliveFromOptions()
    {
        var options = new CommunicationOptions
        {
            GrpcKeepAlivePingDelay = TimeSpan.FromSeconds(42),
            GrpcKeepAlivePingTimeout = TimeSpan.FromSeconds(7)
        };

        var client = new SiteStreamGrpcClient(
            "http://localhost:9999", NullLogger<SiteStreamGrpcClient>.Instance, options);

        Assert.Equal(TimeSpan.FromSeconds(42), client.KeepAlivePingDelay);
        Assert.Equal(TimeSpan.FromSeconds(7), client.KeepAlivePingTimeout);
    }

    [Fact]
    public void SiteStreamGrpcClientFactory_FlowsOptionsToCreatedClients()
    {
        var options = new CommunicationOptions
        {
            GrpcKeepAlivePingDelay = TimeSpan.FromSeconds(33),
            GrpcKeepAlivePingTimeout = TimeSpan.FromSeconds(11)
        };

        using var factory = new SiteStreamGrpcClientFactory(
            NullLoggerFactory.Instance, Options.Create(options));

        var client = factory.GetOrCreate("site1", "http://localhost:9999");

        Assert.Equal(TimeSpan.FromSeconds(33), client.KeepAlivePingDelay);
        Assert.Equal(TimeSpan.FromSeconds(11), client.KeepAlivePingTimeout);
    }

    [Fact]
    public void SiteStreamGrpcServer_BindsMaxConcurrentStreamsAndLifetimeFromOptions()
    {
        var options = new CommunicationOptions
        {
            GrpcMaxConcurrentStreams = 250,
            GrpcMaxStreamLifetime = TimeSpan.FromHours(2)
        };

        var subscriber = Substitute.For<ISiteStreamSubscriber>();
        var server = new SiteStreamGrpcServer(
            subscriber, NullLogger<SiteStreamGrpcServer>.Instance, Options.Create(options));

        Assert.Equal(250, server.MaxConcurrentStreams);
        Assert.Equal(TimeSpan.FromHours(2), server.MaxStreamLifetime);
    }
}
