using Shouldly;
using Xunit;

namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests.S7;

/// <summary>
///     End-to-end smoke against the S7-1500 <c>MB_SERVER</c> pymodbus profile (or a real
///     S7-1500 + MB_SERVER deployment when <c>MODBUS_SIM_ENDPOINT</c> points at one). Drives
///     the full <see cref="ModbusDriver"/> + real <see cref="ModbusTcpTransport"/> stack —
///     no fake transport. Success proves the driver initializes against the S7 simulator,
///     writes a known value, and reads it back with the correct status and value, which is
///     the baseline every S7-specific test (PR 57+) builds on.
/// </summary>
/// <remarks>
///     S7-specific quirk tests (MB_SERVER requires non-optimized DBs, ABCD word order
///     default, port-per-connection, FC23 Illegal Function, STOP-mode behaviour, etc.) land
///     as separate test classes in this directory as each quirk is validated in pymodbus.
///     Keep this smoke test deliberately narrow — filtering by device class
///     (<c>--filter DisplayName~S7</c>) should surface the quirk-specific failure mode when
///     something goes wrong, not a blanket smoke failure that could mean anything.
/// </remarks>
[Collection(ModbusSimulatorCollection.Name)]
[Trait("Category", "Integration")]
[Trait("Device", "S7")]
public sealed class S7_1500SmokeTests(ModbusSimulatorFixture sim)
{
    /// <summary>Verifies that an S7-1500 roundtrip write then read of a holding register succeeds.</summary>
    [Fact]
    public async Task S7_1500_roundtrip_write_then_read_of_holding_register()
    {
        if (sim.SkipReason is not null) Assert.Skip(sim.SkipReason);
        if (!string.Equals(Environment.GetEnvironmentVariable("MODBUS_SIM_PROFILE"), "s7_1500",
                StringComparison.OrdinalIgnoreCase))
        {
            Assert.Skip("MODBUS_SIM_PROFILE != s7_1500 — skipping (other profiles don't seed the S7 scratch range identically).");
        }

        var options = S7_1500Profile.BuildOptions(sim.Host, sim.Port);
        await using var driver = new ModbusDriver(options, driverInstanceId: "s7-smoke");
        await driver.InitializeAsync(driverConfigJson: "{}", TestContext.Current.CancellationToken);

        var writeResults = await driver.WriteAsync(
            [new(FullReference: "Smoke_HReg200", Value: (short)S7_1500Profile.SmokeHoldingValue)],
            TestContext.Current.CancellationToken);
        writeResults.Count.ShouldBe(1);
        writeResults[0].StatusCode.ShouldBe(0u, "write must succeed against the S7-1500 MB_SERVER profile");

        var readResults = await driver.ReadAsync(
            ["Smoke_HReg200"],
            TestContext.Current.CancellationToken);
        readResults.Count.ShouldBe(1);
        readResults[0].StatusCode.ShouldBe(0u);
        readResults[0].Value.ShouldBe((short)S7_1500Profile.SmokeHoldingValue);
    }
}
