using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors;
using ZB.MOM.WW.OtOpcUa.Driver.Modbus;

namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Uns;

public sealed class ModbusTagConfigModelTests
{
    [Theory]
    [InlineData(null)]
    [InlineData("")]
    [InlineData("   ")]
    [InlineData("{}")]
    public void FromJson_returns_defaults_for_empty_input(string? json)
    {
        var m = ModbusTagConfigModel.FromJson(json);

        m.Region.ShouldBe(ModbusRegion.HoldingRegisters);
        m.Address.ShouldBe(0);
        m.DataType.ShouldBe(ModbusDataType.Int16);
        m.ByteOrder.ShouldBe(ModbusByteOrder.BigEndian);
        m.BitIndex.ShouldBe(0);
        m.StringLength.ShouldBe(0);
    }

    [Fact]
    public void Round_trip_preserves_all_six_fields()
    {
        var m = new ModbusTagConfigModel
        {
            Region = ModbusRegion.InputRegisters,
            Address = 40001,
            DataType = ModbusDataType.Float32,
            ByteOrder = ModbusByteOrder.WordSwap,
            BitIndex = 3,
            StringLength = 16,
        };

        var json = m.ToJson();
        var m2 = ModbusTagConfigModel.FromJson(json);

        m2.Region.ShouldBe(ModbusRegion.InputRegisters);
        m2.Address.ShouldBe(40001);
        m2.DataType.ShouldBe(ModbusDataType.Float32);
        m2.ByteOrder.ShouldBe(ModbusByteOrder.WordSwap);
        m2.BitIndex.ShouldBe(3);
        m2.StringLength.ShouldBe(16);
    }

    [Fact]
    public void ToJson_emits_camelCase_keys_with_enum_names()
    {
        var m = new ModbusTagConfigModel
        {
            Region = ModbusRegion.HoldingRegisters,
            Address = 100,
            DataType = ModbusDataType.Int16,
            ByteOrder = ModbusByteOrder.BigEndian,
            BitIndex = 0,
            StringLength = 0,
        };

        var json = m.ToJson();

        json.ShouldContain("\"region\":\"HoldingRegisters\"");
        json.ShouldContain("\"dataType\":\"Int16\"");
        json.ShouldContain("\"byteOrder\":\"BigEndian\"");
        json.ShouldContain("\"address\":100");
        json.ShouldContain("\"bitIndex\":0");
        json.ShouldContain("\"stringLength\":0");
    }

    [Fact]
    public void FromJson_then_ToJson_preserves_unknown_keys()
    {
        var json = ModbusTagConfigModel
            .FromJson("""{"region":"InputRegisters","addressString":"40001:F"}""")
            .ToJson();

        json.ShouldContain("addressString");
        json.ShouldContain("40001:F");
        // and the exposed field still round-trips
        json.ShouldContain("\"region\":\"InputRegisters\"");
    }

    [Fact]
    public void Validate_returns_null_for_default_model()
    {
        new ModbusTagConfigModel().Validate().ShouldBeNull();
    }
}
