using MessagePack;

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

[MessagePackObject]
public sealed class HistoryReadRequest
{
    [Key(0)] public long SessionId { get; set; }
    [Key(1)] public string[] TagReferences { get; set; } = System.Array.Empty<string>();
    [Key(2)] public long StartUtcUnixMs { get; set; }
    [Key(3)] public long EndUtcUnixMs { get; set; }
    [Key(4)] public uint MaxValuesPerTag { get; set; } = 1000;
}

[MessagePackObject]
public sealed class HistoryTagValues
{
    [Key(0)] public string TagReference { get; set; } = string.Empty;
    [Key(1)] public GalaxyDataValue[] Values { get; set; } = System.Array.Empty<GalaxyDataValue>();
}

[MessagePackObject]
public sealed class HistoryReadResponse
{
    [Key(0)] public bool Success { get; set; }
    [Key(1)] public string? Error { get; set; }
    [Key(2)] public HistoryTagValues[] Tags { get; set; } = System.Array.Empty<HistoryTagValues>();
}

/// <summary>
///     Processed (aggregated) historian read — OPC UA HistoryReadProcessed service. The
///     aggregate column is a string (e.g. "Average", "Minimum") mapped by the Proxy from the
///     OPC UA HistoryAggregateType enum so Galaxy.Host stays OPC-UA-free.
/// </summary>
[MessagePackObject]
public sealed class HistoryReadProcessedRequest
{
    [Key(0)] public long SessionId { get; set; }
    [Key(1)] public string TagReference { get; set; } = string.Empty;
    [Key(2)] public long StartUtcUnixMs { get; set; }
    [Key(3)] public long EndUtcUnixMs { get; set; }
    [Key(4)] public long IntervalMs { get; set; }
    [Key(5)] public string AggregateColumn { get; set; } = "Average";
}

[MessagePackObject]
public sealed class HistoryReadProcessedResponse
{
    [Key(0)] public bool Success { get; set; }
    [Key(1)] public string? Error { get; set; }
    [Key(2)] public GalaxyDataValue[] Values { get; set; } = System.Array.Empty<GalaxyDataValue>();
}

/// <summary>
///     At-time historian read — OPC UA HistoryReadAtTime service. Returns one sample per
///     requested timestamp (interpolated when no exact match exists). The per-timestamp array
///     is flow-encoded as Unix milliseconds to avoid MessagePack DateTime quirks.
/// </summary>
[MessagePackObject]
public sealed class HistoryReadAtTimeRequest
{
    [Key(0)] public long SessionId { get; set; }
    [Key(1)] public string TagReference { get; set; } = string.Empty;
    [Key(2)] public long[] TimestampsUtcUnixMs { get; set; } = System.Array.Empty<long>();
}

[MessagePackObject]
public sealed class HistoryReadAtTimeResponse
{
    [Key(0)] public bool Success { get; set; }
    [Key(1)] public string? Error { get; set; }
    [Key(2)] public GalaxyDataValue[] Values { get; set; } = System.Array.Empty<GalaxyDataValue>();
}

/// <summary>
///     Historical events read — OPC UA HistoryReadEvents service and Alarm &amp; Condition
///     history. <c>SourceName</c> null means "all sources". Distinct from the live
///     <see cref="GalaxyAlarmEvent"/> stream because historical rows carry both
///     <c>EventTime</c> (when the event occurred in the process) and <c>ReceivedTime</c>
///     (when the Historian persisted it) and have no StateTransition — the Historian logs
///     the instantaneous event, not the OPC UA alarm lifecycle.
/// </summary>
[MessagePackObject]
public sealed class HistoryReadEventsRequest
{
    [Key(0)] public long SessionId { get; set; }
    [Key(1)] public string? SourceName { get; set; }
    [Key(2)] public long StartUtcUnixMs { get; set; }
    [Key(3)] public long EndUtcUnixMs { get; set; }
    [Key(4)] public int MaxEvents { get; set; } = 1000;
}

[MessagePackObject]
public sealed class GalaxyHistoricalEvent
{
    [Key(0)] public string EventId { get; set; } = string.Empty;
    [Key(1)] public string? SourceName { get; set; }
    [Key(2)] public long EventTimeUtcUnixMs { get; set; }
    [Key(3)] public long ReceivedTimeUtcUnixMs { get; set; }
    [Key(4)] public string? DisplayText { get; set; }
    [Key(5)] public ushort Severity { get; set; }
}

[MessagePackObject]
public sealed class HistoryReadEventsResponse
{
    [Key(0)] public bool Success { get; set; }
    [Key(1)] public string? Error { get; set; }
    [Key(2)] public GalaxyHistoricalEvent[] Events { get; set; } = System.Array.Empty<GalaxyHistoricalEvent>();
}
