using MessagePack;

namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Shared.Contracts;

/// <summary>
///     Subscribe the Host to polling a set of tags on behalf of the Proxy. FOCAS is
///     poll-only — there are no CNC-initiated callbacks — so the Host runs the poll loop and
///     pushes <see cref="OnDataChangeNotification"/> frames whenever a value differs from
///     the last observation. Delta-only + per-group interval keeps the wire quiet.
/// </summary>
[MessagePackObject]
public sealed class SubscribeRequest
{
    [Key(0)] public long SessionId { get; set; }
    [Key(1)] public long SubscriptionId { get; set; }
    [Key(2)] public int IntervalMs { get; set; } = 1000;
    [Key(3)] public SubscribeItem[] Items { get; set; } = System.Array.Empty<SubscribeItem>();
}

[MessagePackObject]
public sealed class SubscribeItem
{
    /// <summary>Opaque correlation id the Proxy uses to route notifications back to the right OPC UA MonitoredItem.</summary>
    [Key(0)] public long MonitoredItemId { get; set; }

    [Key(1)] public FocasAddressDto Address { get; set; } = new();
    [Key(2)] public int DataType { get; set; }
}

[MessagePackObject]
public sealed class SubscribeResponse
{
    [Key(0)] public bool Success { get; set; }
    [Key(1)] public string? Error { get; set; }

    /// <summary>Items the Host refused (address mismatch, unsupported type). Empty on full success.</summary>
    [Key(2)] public long[] RejectedMonitoredItemIds { get; set; } = System.Array.Empty<long>();
}

[MessagePackObject]
public sealed class UnsubscribeRequest
{
    [Key(0)] public long SubscriptionId { get; set; }
}

[MessagePackObject]
public sealed class OnDataChangeNotification
{
    [Key(0)] public long SubscriptionId { get; set; }
    [Key(1)] public DataChange[] Changes { get; set; } = System.Array.Empty<DataChange>();
}

[MessagePackObject]
public sealed class DataChange
{
    [Key(0)] public long MonitoredItemId { get; set; }
    [Key(1)] public uint StatusCode { get; set; }
    [Key(2)] public byte[]? ValueBytes { get; set; }
    [Key(3)] public int ValueTypeCode { get; set; }
    [Key(4)] public long SourceTimestampUtcUnixMs { get; set; }
}
