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

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

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

        m.Address.ShouldBe("");
        m.DataType.ShouldBe(S7DataType.Int16);
        m.StringLength.ShouldBe(0);
    }

    [Fact]
    public void Round_trip_preserves_all_fields()
    {
        var m = new S7TagConfigModel
        {
            Address = "DB1.DBW0",
            DataType = S7DataType.Float32,
            StringLength = 32,
        };

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

        m2.Address.ShouldBe("DB1.DBW0");
        m2.DataType.ShouldBe(S7DataType.Float32);
        m2.StringLength.ShouldBe(32);
    }

    [Fact]
    public void ToJson_emits_camelCase_keys_with_enum_names()
    {
        var m = new S7TagConfigModel
        {
            Address = "M0.0",
            DataType = S7DataType.Bool,
            StringLength = 0,
        };

        var json = m.ToJson();

        json.ShouldContain("\"address\":\"M0.0\"");
        json.ShouldContain("\"dataType\":\"Bool\"");
        json.ShouldContain("\"stringLength\":0");
    }

    [Fact]
    public void FromJson_then_ToJson_preserves_unknown_keys()
    {
        var json = S7TagConfigModel
            .FromJson("""{"address":"DB1.DBW0","extraKey":"keepme"}""")
            .ToJson();

        json.ShouldContain("extraKey");
        json.ShouldContain("keepme");
        json.ShouldContain("\"address\":\"DB1.DBW0\"");
    }

    [Fact]
    public void Validate_returns_error_when_address_blank()
    {
        new S7TagConfigModel { Address = "" }.Validate().ShouldNotBeNull();
    }

    [Fact]
    public void Validate_returns_null_when_address_filled()
    {
        new S7TagConfigModel { Address = "DB1.DBW0" }.Validate().ShouldBeNull();
    }
}
