using Shouldly;
using Xunit;

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

/// <summary>
///     Verifies the driver's Modbus-exception → OPC UA StatusCode translation end-to-end
///     against the dl205.json pymodbus profile. pymodbus returns exception 02 (Illegal Data
///     Address) for reads outside the configured register ranges, matching real DL205/DL260
///     firmware behavior per <c>docs/v2/dl205.md</c> §exception-codes. The driver must surface
///     that as <c>BadOutOfRange</c> (0x803C0000) — not <c>BadInternalError</c> — so the
///     operator sees a tag-config diagnosis instead of a generic driver-fault message.
/// </summary>
[Collection(ModbusSimulatorCollection.Name)]
[Trait("Category", "Integration")]
[Trait("Device", "DL205")]
public sealed class DL205ExceptionCodeTests(ModbusSimulatorFixture sim)
{
    /// <summary>Verifies that DL205 FC03 reads at unmapped registers return BadOutOfRange status.</summary>
    [Fact]
    public async Task DL205_FC03_at_unmapped_register_returns_BadOutOfRange()
    {
        if (sim.SkipReason is not null) Assert.Skip(sim.SkipReason);
        if (!string.Equals(Environment.GetEnvironmentVariable("MODBUS_SIM_PROFILE"), "dl205",
                StringComparison.OrdinalIgnoreCase))
        {
            Assert.Skip("MODBUS_SIM_PROFILE != dl205 — skipping.");
        }

        // Address 16383 is the last cell of hr-size=16384 in dl205.json; address 16384 is
        // beyond the configured HR range. pymodbus validates and returns exception 02
        // (Illegal Data Address).
        var options = new ModbusDriverOptions
        {
            Host = sim.Host,
            Port = sim.Port,
            UnitId = 1,
            Timeout = TimeSpan.FromSeconds(2),
            RawTags = ModbusRawTags.Entries([
                new ModbusTagDefinition("Unmapped",
                    ModbusRegion.HoldingRegisters, Address: 16383,
                    DataType: ModbusDataType.UInt16, Writable: false),
            ]),
            Probe = new ModbusProbeOptions { Enabled = false },
        };
        await using var driver = new ModbusDriver(options, driverInstanceId: "dl205-exc");
        await driver.InitializeAsync("{}", TestContext.Current.CancellationToken);

        var results = await driver.ReadAsync(["Unmapped"], TestContext.Current.CancellationToken);
        results[0].StatusCode.ShouldBe(0x803C0000u,
            "DL205 returns exception 02 for an FC03 at an unmapped register; driver must translate to BadOutOfRange (not BadInternalError)");
    }
}
