using Shouldly;
using Xunit;

namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.Tests;

/// <summary>
///     Pins the socket-lifecycle surface extracted from <see cref="ModbusTcpTransport"/> into the
///     reusable <see cref="ModbusSocketLifecycle"/> (Task 3). The clamp helper moved with it, and a
///     connect to a dead port must still surface the underlying socket failure.
/// </summary>
[Trait("Category", "Unit")]
public sealed class ModbusSocketLifecycleTests
{
    /// <summary>Verifies the whole-seconds clamp rounds sub-second/negative durations up to a minimum of one.</summary>
    /// <param name="seconds">The input duration in seconds.</param>
    /// <param name="expected">The expected clamped value in whole seconds.</param>
    [Theory]
    [InlineData(0.4, 1)]   // sub-second rounds up to 1 (the int-cast truncation guard)
    [InlineData(2.0, 2)]
    [InlineData(-5.0, 1)]  // negative clamps to 1
    public void ClampToWholeSeconds_rounds_up_min_one(double seconds, int expected)
        => ModbusSocketLifecycle.ClampToWholeSeconds(TimeSpan.FromSeconds(seconds)).ShouldBe(expected);

    /// <summary>Verifies a connect to a dead port surfaces the underlying socket failure.</summary>
    [Fact]
    public async Task Connect_to_dead_port_surfaces_socket_failure()
    {
        var life = new ModbusSocketLifecycle("127.0.0.1", 1, TimeSpan.FromMilliseconds(300),
            autoReconnect: false);
        await Should.ThrowAsync<System.Net.Sockets.SocketException>(
            life.ConnectAsync(TestContext.Current.CancellationToken));
    }
}
