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

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

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

        m.DeviceHostAddress.ShouldBe("");
        m.Address.ShouldBe("");
        m.DataType.ShouldBe(FocasDataType.Int32);
    }

    [Fact]
    public void Round_trip_preserves_all_fields()
    {
        var m = new FocasTagConfigModel
        {
            DeviceHostAddress = "192.168.0.1:8193",
            Address = "MACRO:500",
            DataType = FocasDataType.Float64,
        };

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

        m2.DeviceHostAddress.ShouldBe("192.168.0.1:8193");
        m2.Address.ShouldBe("MACRO:500");
        m2.DataType.ShouldBe(FocasDataType.Float64);
    }

    [Fact]
    public void ToJson_emits_camelCase_keys_with_enum_names()
    {
        var m = new FocasTagConfigModel
        {
            DeviceHostAddress = "192.168.0.1:8193",
            Address = "R100",
            DataType = FocasDataType.Int32,
        };

        var json = m.ToJson();

        json.ShouldContain("\"deviceHostAddress\":\"192.168.0.1:8193\"");
        json.ShouldContain("\"address\":\"R100\"");
        json.ShouldContain("\"dataType\":\"Int32\"");
    }

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

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

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

    [Fact]
    public void Validate_returns_null_when_address_filled()
    {
        new FocasTagConfigModel { Address = "R100" }.Validate().ShouldBeNull();
    }

    [Fact]
    public void ToJson_omits_blank_deviceHostAddress()
    {
        var m = new FocasTagConfigModel { Address = "R100", DeviceHostAddress = "" };

        var json = m.ToJson();

        json.ShouldNotContain("deviceHostAddress");
    }

    [Fact]
    public void ToJson_includes_deviceHostAddress_when_set()
    {
        var m = new FocasTagConfigModel { Address = "R100", DeviceHostAddress = "ab://host" };

        var json = m.ToJson();

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