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

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

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

        m.DeviceHostAddress.ShouldBe("");
        m.SymbolPath.ShouldBe("");
        m.DataType.ShouldBe(TwinCATDataType.DInt);
    }

    [Fact]
    public void Round_trip_preserves_all_fields()
    {
        var m = new TwinCATTagConfigModel
        {
            DeviceHostAddress = "5.1.2.3.1.1:851",
            SymbolPath = "MAIN.bStart",
            DataType = TwinCATDataType.Real,
        };

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

        m2.DeviceHostAddress.ShouldBe("5.1.2.3.1.1:851");
        m2.SymbolPath.ShouldBe("MAIN.bStart");
        m2.DataType.ShouldBe(TwinCATDataType.Real);
    }

    [Fact]
    public void ToJson_emits_camelCase_keys_with_enum_names()
    {
        var m = new TwinCATTagConfigModel
        {
            DeviceHostAddress = "5.1.2.3.1.1:851",
            SymbolPath = "GVL.Counter",
            DataType = TwinCATDataType.DInt,
        };

        var json = m.ToJson();

        json.ShouldContain("\"deviceHostAddress\":\"5.1.2.3.1.1:851\"");
        json.ShouldContain("\"symbolPath\":\"GVL.Counter\"");
        json.ShouldContain("\"dataType\":\"DInt\"");
    }

    [Fact]
    public void FromJson_then_ToJson_preserves_unknown_keys()
    {
        var json = TwinCATTagConfigModel
            .FromJson("""{"symbolPath":"GVL.Counter","extraKey":"keepme"}""")
            .ToJson();

        json.ShouldContain("extraKey");
        json.ShouldContain("keepme");
        json.ShouldContain("\"symbolPath\":\"GVL.Counter\"");
    }

    [Fact]
    public void Validate_returns_error_when_symbolPath_blank()
    {
        new TwinCATTagConfigModel { SymbolPath = "" }.Validate().ShouldNotBeNull();
    }

    [Fact]
    public void Validate_returns_null_when_symbolPath_filled()
    {
        new TwinCATTagConfigModel { SymbolPath = "MAIN.bStart" }.Validate().ShouldBeNull();
    }

    [Fact]
    public void ToJson_omits_blank_deviceHostAddress()
    {
        var m = new TwinCATTagConfigModel { SymbolPath = "MAIN.bStart", DeviceHostAddress = "" };

        var json = m.ToJson();

        json.ShouldNotContain("deviceHostAddress");
    }

    [Fact]
    public void ToJson_includes_deviceHostAddress_when_set()
    {
        var m = new TwinCATTagConfigModel { SymbolPath = "MAIN.bStart", DeviceHostAddress = "ab://host" };

        var json = m.ToJson();

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