using Shouldly;
using Xunit;

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

/// <summary>
///     End-to-end smoke against the MELSEC <c>mitsubishi.json</c> pymodbus profile (or a real
///     MELSEC QJ71MT91 / iQ-R / FX5U when <c>MODBUS_SIM_ENDPOINT</c> points at one). Drives
///     the full <see cref="ModbusDriver"/> + real <see cref="ModbusTcpTransport"/> stack.
///     Success proves the driver initializes against the MELSEC sim, writes a known value,
///     and reads it back — the baseline every Mitsubishi-specific test (PR 59+) builds on.
/// </summary>
[Collection(ModbusSimulatorCollection.Name)]
[Trait("Category", "Integration")]
[Trait("Device", "Mitsubishi")]
public sealed class MitsubishiSmokeTests(ModbusSimulatorFixture sim)
{
    /// <summary>Verifies end-to-end write and read of a Mitsubishi holding register via the Modbus driver.</summary>
    [Fact]
    public async Task Mitsubishi_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"), "mitsubishi",
                StringComparison.OrdinalIgnoreCase))
        {
            Assert.Skip("MODBUS_SIM_PROFILE != mitsubishi — skipping.");
        }

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

        var writeResults = await driver.WriteAsync(
            [new(FullReference: "Smoke_HReg200", Value: (short)MitsubishiProfile.SmokeHoldingValue)],
            TestContext.Current.CancellationToken);
        writeResults.Count.ShouldBe(1);
        writeResults[0].StatusCode.ShouldBe(0u, "write must succeed against the MELSEC pymodbus 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)MitsubishiProfile.SmokeHoldingValue);
    }
}
