using FluentAssertions;
using Xunit;
using ZB.MOM.WW.LmxProxy.Client.Domain;

namespace ZB.MOM.WW.LmxProxy.Client.Tests.Domain;

public class ScadaContractsTests
{
    [Fact]
    public void TypedValue_GetValueCase_Bool()
    {
        var tv = new TypedValue { BoolValue = true };
        tv.GetValueCase().Should().Be(TypedValueCase.BoolValue);
    }

    [Fact]
    public void TypedValue_GetValueCase_Int32()
    {
        var tv = new TypedValue { Int32Value = 42 };
        tv.GetValueCase().Should().Be(TypedValueCase.Int32Value);
    }

    [Fact]
    public void TypedValue_GetValueCase_Double()
    {
        var tv = new TypedValue { DoubleValue = 3.14 };
        tv.GetValueCase().Should().Be(TypedValueCase.DoubleValue);
    }

    [Fact]
    public void TypedValue_GetValueCase_String()
    {
        var tv = new TypedValue { StringValue = "hello" };
        tv.GetValueCase().Should().Be(TypedValueCase.StringValue);
    }

    [Fact]
    public void TypedValue_GetValueCase_None_WhenDefault()
    {
        var tv = new TypedValue();
        tv.GetValueCase().Should().Be(TypedValueCase.None);
    }

    [Fact]
    public void TypedValue_GetValueCase_Datetime()
    {
        var tv = new TypedValue { DatetimeValue = DateTime.UtcNow.Ticks };
        tv.GetValueCase().Should().Be(TypedValueCase.DatetimeValue);
    }

    [Fact]
    public void TypedValue_GetValueCase_BytesValue()
    {
        var tv = new TypedValue { BytesValue = new byte[] { 1, 2, 3 } };
        tv.GetValueCase().Should().Be(TypedValueCase.BytesValue);
    }

    [Fact]
    public void TypedValue_GetValueCase_ArrayValue()
    {
        var tv = new TypedValue
        {
            ArrayValue = new ArrayValue
            {
                FloatValues = new FloatArray { Values = { 1.0f, 2.0f } }
            }
        };
        tv.GetValueCase().Should().Be(TypedValueCase.ArrayValue);
    }

    [Fact]
    public void QualityCode_IsGood()
    {
        var qc = new QualityCode { StatusCode = 0x00000000, SymbolicName = "Good" };
        qc.IsGood.Should().BeTrue();
        qc.IsBad.Should().BeFalse();
        qc.IsUncertain.Should().BeFalse();
    }

    [Fact]
    public void QualityCode_IsBad()
    {
        var qc = new QualityCode { StatusCode = 0x80000000, SymbolicName = "Bad" };
        qc.IsGood.Should().BeFalse();
        qc.IsBad.Should().BeTrue();
        qc.IsUncertain.Should().BeFalse();
    }

    [Fact]
    public void QualityCode_IsUncertain()
    {
        var qc = new QualityCode { StatusCode = 0x40900000, SymbolicName = "UncertainLastUsableValue" };
        qc.IsGood.Should().BeFalse();
        qc.IsBad.Should().BeFalse();
        qc.IsUncertain.Should().BeTrue();
    }

    [Fact]
    public void VtqMessage_DefaultProperties()
    {
        var vtq = new VtqMessage();
        vtq.Tag.Should().BeEmpty();
        vtq.Value.Should().BeNull();
        vtq.TimestampUtcTicks.Should().Be(0);
        vtq.Quality.Should().BeNull();
    }

    [Fact]
    public void WriteBatchAndWaitRequest_FlagValue_IsTypedValue()
    {
        var req = new WriteBatchAndWaitRequest
        {
            SessionId = "abc",
            FlagTag = "Motor.Done",
            FlagValue = new TypedValue { BoolValue = true },
            TimeoutMs = 5000,
            PollIntervalMs = 100
        };
        req.FlagValue.Should().NotBeNull();
        req.FlagValue!.GetValueCase().Should().Be(TypedValueCase.BoolValue);
    }

    [Fact]
    public void WriteItem_Value_IsTypedValue()
    {
        var item = new WriteItem
        {
            Tag = "Motor.Speed",
            Value = new TypedValue { DoubleValue = 42.5 }
        };
        item.Value.Should().NotBeNull();
        item.Value!.GetValueCase().Should().Be(TypedValueCase.DoubleValue);
    }
}
