using CliFx.Infrastructure;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Commands;

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

/// <summary>
///     Covers Driver.Modbus.Cli-010: <see cref="SubscribeCommand"/> must reject a non-positive
///     <c>--interval-ms</c> before touching the driver so the operator gets a clear
///     <see cref="CliFx.Exceptions.CommandException"/> rather than a downstream failure deep
///     inside <c>PollGroupEngine</c>. Mirrors the <c>ValidateInterval</c> guard in
///     <c>Driver.AbCip.Cli.SubscribeCommand</c>.
/// </summary>
[Trait("Category", "Unit")]
public sealed class SubscribeCommandValidationTests
{
    /// <summary>Verifies that ValidateInterval rejects zero and negative interval values.</summary>
    /// <param name="intervalMs">The invalid interval in milliseconds to test.</param>
    [Theory]
    [InlineData(0)]
    [InlineData(-1)]
    [InlineData(-1000)]
    public void ValidateInterval_rejects_non_positive_interval(int intervalMs)
    {
        Should.Throw<CliFx.Exceptions.CommandException>(
            () => SubscribeCommand.ValidateInterval(intervalMs));
    }

    /// <summary>Verifies that ValidateInterval accepts strictly positive interval values.</summary>
    /// <param name="intervalMs">The valid interval in milliseconds to test.</param>
    [Theory]
    [InlineData(1)]
    [InlineData(250)]
    [InlineData(1000)]
    [InlineData(5000)]
    public void ValidateInterval_accepts_positive_interval(int intervalMs)
    {
        Should.NotThrow(() => SubscribeCommand.ValidateInterval(intervalMs));
    }

    /// <summary>
    ///     Verifies that ExecuteAsync throws <see cref="CliFx.Exceptions.CommandException"/>
    ///     when <c>--interval-ms</c> is non-positive, before any driver I/O.
    /// </summary>
    [Fact]
    public async Task ExecuteAsync_rejects_zero_interval_before_driver_connect()
    {
        var sut = new SubscribeCommand
        {
            Host = "127.0.0.1",
            Region = ModbusRegion.HoldingRegisters,
            Address = 0,
            DataType = ModbusDataType.UInt16,
            IntervalMs = 0,
        };
        using var console = new FakeInMemoryConsole();

        await Should.ThrowAsync<CliFx.Exceptions.CommandException>(
            async () => await sut.ExecuteAsync(console));
    }
}
