using System.Collections.Generic;
using Opc.Ua;

namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Tests.Adapters;

/// <summary>
/// SCOPE: these tests cover ONLY the SDK-level building block the write path
/// relies on — that <c>new Variant(collection)</c> wraps a CLR array / list as a
/// typed array <see cref="Variant"/> (ValueRank = OneDimension) without throwing.
/// They are NOT an end-to-end test of the runtime write flow: they feed a
/// hand-built collection straight into <see cref="Variant"/>, bypassing the
/// InstanceActor decode step that produces that collection.
///
/// The END-TO-END flow — a script's canonical JSON list string being DECODED to a
/// typed <c>List&lt;T&gt;</c> before the <c>WriteTagRequest</c> reaches the DCL
/// (so OPC UA writes an array node, not a String scalar) — is covered by
/// <c>InstanceActorTests.InstanceActor_DataSourcedListWrite_SendsTypedArrayToDcl_NotJsonString</c>.
/// The runtime hands <see cref="RealOpcUaClient.WriteValueAsync"/> a
/// <c>List&lt;T&gt;</c> (the codec's decode result), which the SDK wraps
/// identically to a CLR array — see the <c>List&lt;int&gt;</c> case below. A full
/// device round-trip needs a live server and is covered by the live OPC UA smoke
/// tests.
/// </summary>
[Trait("Category", "Unit")]
public class RealOpcUaClientArrayWriteTests
{
    [Fact]
    public void Variant_wraps_int_list_as_array_without_throwing()
    {
        // The runtime actually hands WriteValueAsync a List<T> (the decode result),
        // not a raw T[]; assert the SDK wraps it as a typed array all the same.
        var value = new List<int> { 10, 20, 30 };

        var ex = Record.Exception(() => new Variant(value));

        Assert.Null(ex);
        var variant = new Variant(value);
        Assert.Equal(BuiltInType.Int32, variant.TypeInfo.BuiltInType);
        Assert.Equal(ValueRanks.OneDimension, variant.TypeInfo.ValueRank);
    }

    [Fact]
    public void Variant_wraps_int_array_without_throwing()
    {
        var value = new[] { 10, 20, 30 };

        var ex = Record.Exception(() => new Variant(value));

        Assert.Null(ex);
        var variant = new Variant(value);
        Assert.Equal(BuiltInType.Int32, variant.TypeInfo.BuiltInType);
        Assert.Equal(ValueRanks.OneDimension, variant.TypeInfo.ValueRank);
    }

    [Fact]
    public void Variant_wraps_double_array_without_throwing()
    {
        var value = new[] { 1.5, 2.5, 3.5 };

        var ex = Record.Exception(() => new Variant(value));

        Assert.Null(ex);
        var variant = new Variant(value);
        Assert.Equal(BuiltInType.Double, variant.TypeInfo.BuiltInType);
        Assert.Equal(ValueRanks.OneDimension, variant.TypeInfo.ValueRank);
    }

    [Fact]
    public void Variant_wraps_string_array_without_throwing()
    {
        var value = new[] { "a", "b", "c" };

        var ex = Record.Exception(() => new Variant(value));

        Assert.Null(ex);
        var variant = new Variant(value);
        Assert.Equal(BuiltInType.String, variant.TypeInfo.BuiltInType);
        Assert.Equal(ValueRanks.OneDimension, variant.TypeInfo.ValueRank);
    }
}
