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

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

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

        m.DeviceHostAddress.ShouldBe("");
        m.TagPath.ShouldBe("");
        m.DataType.ShouldBe(AbCipDataType.DInt);
    }

    [Fact]
    public void Round_trip_preserves_all_fields()
    {
        var m = new AbCipTagConfigModel
        {
            DeviceHostAddress = "ab://gw/1,0",
            TagPath = "Program:Main.Speed",
            DataType = AbCipDataType.Real,
        };

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

        m2.DeviceHostAddress.ShouldBe("ab://gw/1,0");
        m2.TagPath.ShouldBe("Program:Main.Speed");
        m2.DataType.ShouldBe(AbCipDataType.Real);
    }

    [Fact]
    public void ToJson_emits_camelCase_keys_with_enum_names()
    {
        var m = new AbCipTagConfigModel
        {
            DeviceHostAddress = "ab://gw/1,0",
            TagPath = "Motor1.Status",
            DataType = AbCipDataType.DInt,
        };

        var json = m.ToJson();

        json.ShouldContain("\"deviceHostAddress\":\"ab://gw/1,0\"");
        json.ShouldContain("\"tagPath\":\"Motor1.Status\"");
        json.ShouldContain("\"dataType\":\"DInt\"");
    }

    [Fact]
    public void FromJson_then_ToJson_preserves_unknown_keys()
    {
        var json = AbCipTagConfigModel
            .FromJson("""{"tagPath":"Motor1.Status","extraKey":"keepme"}""")
            .ToJson();

        json.ShouldContain("extraKey");
        json.ShouldContain("keepme");
        json.ShouldContain("\"tagPath\":\"Motor1.Status\"");
    }

    [Fact]
    public void Validate_returns_error_when_tagPath_blank()
    {
        new AbCipTagConfigModel { TagPath = "" }.Validate().ShouldNotBeNull();
    }

    [Fact]
    public void Validate_returns_null_when_tagPath_filled()
    {
        new AbCipTagConfigModel { TagPath = "Motor1.Status" }.Validate().ShouldBeNull();
    }

    [Fact]
    public void ToJson_omits_blank_deviceHostAddress()
    {
        var m = new AbCipTagConfigModel { TagPath = "Motor1.Status", DeviceHostAddress = "" };

        var json = m.ToJson();

        json.ShouldNotContain("deviceHostAddress");
    }

    [Fact]
    public void ToJson_includes_deviceHostAddress_when_set()
    {
        var m = new AbCipTagConfigModel { TagPath = "Motor1.Status", DeviceHostAddress = "ab://host" };

        var json = m.ToJson();

        json.ShouldContain("\"deviceHostAddress\":\"ab://host\"");
    }
}
