using System;
using MessagePack;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Shared.Contracts;

namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host.Tests;

[Trait("Category", "Unit")]
public sealed class AlarmDiscoveryTests
{
    /// <summary>
    ///     PR 9 — IsAlarm must survive the MessagePack round-trip at Key=6 position.
    ///     Regression guard: any reorder of keys in GalaxyAttributeInfo would silently corrupt
    ///     the flag in the wire payload since MessagePack encodes by key number, not field name.
    /// </summary>
    [Fact]
    public void GalaxyAttributeInfo_IsAlarm_round_trips_true_through_MessagePack()
    {
        var input = new GalaxyAttributeInfo
        {
            AttributeName = "TankLevel",
            MxDataType = 2,
            IsArray = false,
            ArrayDim = null,
            SecurityClassification = 1,
            IsHistorized = true,
            IsAlarm = true,
        };

        var bytes = MessagePackSerializer.Serialize(input);
        var decoded = MessagePackSerializer.Deserialize<GalaxyAttributeInfo>(bytes);

        decoded.IsAlarm.ShouldBeTrue();
        decoded.IsHistorized.ShouldBeTrue();
        decoded.AttributeName.ShouldBe("TankLevel");
    }

    [Fact]
    public void GalaxyAttributeInfo_IsAlarm_round_trips_false_through_MessagePack()
    {
        var input = new GalaxyAttributeInfo { AttributeName = "ColorRgb", IsAlarm = false };
        var bytes = MessagePackSerializer.Serialize(input);
        var decoded = MessagePackSerializer.Deserialize<GalaxyAttributeInfo>(bytes);
        decoded.IsAlarm.ShouldBeFalse();
    }

    /// <summary>
    ///     Wire-compat guard: payloads serialized before PR 9 (which omit Key=6) must still
    ///     deserialize cleanly — MessagePack treats missing keys as default. This lets a newer
    ///     Proxy talk to an older Host during a rolling upgrade without a crash.
    /// </summary>
    [Fact]
    public void Pre_PR9_payload_without_IsAlarm_key_deserializes_with_default_false()
    {
        // Build a 6-field payload (keys 0..5) matching the pre-PR9 shape by serializing a
        // stand-in class with the same key layout but no Key=6.
        var pre = new PrePR9Shape
        {
            AttributeName = "Legacy",
            MxDataType = 1,
            IsArray = false,
            ArrayDim = null,
            SecurityClassification = 0,
            IsHistorized = false,
        };
        var bytes = MessagePackSerializer.Serialize(pre);

        var decoded = MessagePackSerializer.Deserialize<GalaxyAttributeInfo>(bytes);
        decoded.AttributeName.ShouldBe("Legacy");
        decoded.IsAlarm.ShouldBeFalse();
    }

    [MessagePackObject]
    public sealed class PrePR9Shape
    {
        [Key(0)] public string AttributeName { get; set; } = string.Empty;
        [Key(1)] public int MxDataType { get; set; }
        [Key(2)] public bool IsArray { get; set; }
        [Key(3)] public uint? ArrayDim { get; set; }
        [Key(4)] public int SecurityClassification { get; set; }
        [Key(5)] public bool IsHistorized { get; set; }
    }
}
