using System;
using MessagePack;

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

/// <summary>
///     Phase 7 Stream D — IPC contracts for routing Part 9 alarm transitions from the
///     main .NET 10 server into Galaxy.Host's already-loaded <c>aahClientManaged</c>
///     DLLs. Reuses the Tier-C isolation + licensing pathway rather than loading 32-bit
///     native historian code into the main server.
/// </summary>
/// <remarks>
///     <para>
///         Batched on the wire to amortize IPC overhead — the main server's SqliteStoreAndForwardSink
///         ships up to 100 events per request per Phase 7 plan Stream D.5.
///     </para>
///     <para>
///         Per-event outcomes (Ack / RetryPlease / PermanentFail) let the drain worker
///         dead-letter malformed events without blocking neighbors in the batch.
///         <see cref="HistorianConnectivityStatusNotification"/> fires proactively from
///         the Host when the SDK session drops so the /hosts + /alarms/historian Admin
///         diagnostics pages flip to red promptly instead of waiting for the next
///         drain cycle.
///     </para>
/// </remarks>
[MessagePackObject]
public sealed class HistorianAlarmEventRequest
{
    [Key(0)] public HistorianAlarmEventDto[] Events { get; set; } = Array.Empty<HistorianAlarmEventDto>();
}

[MessagePackObject]
public sealed class HistorianAlarmEventResponse
{
    /// <summary>Per-event outcome, same order as the request.</summary>
    [Key(0)] public HistorianAlarmEventOutcomeDto[] Outcomes { get; set; } = Array.Empty<HistorianAlarmEventOutcomeDto>();
}

/// <summary>Outcome enum — bytes on the wire so it stays compact.</summary>
public enum HistorianAlarmEventOutcomeDto : byte
{
    /// <summary>Successfully persisted to the historian — remove from queue.</summary>
    Ack = 0,
    /// <summary>Transient failure (historian disconnected, timeout, busy) — retry after backoff.</summary>
    RetryPlease = 1,
    /// <summary>Permanent failure (malformed, unrecoverable SDK error) — move to dead-letter.</summary>
    PermanentFail = 2,
}

/// <summary>One alarm-transition payload. Fields mirror <c>Core.AlarmHistorian.AlarmHistorianEvent</c>.</summary>
[MessagePackObject]
public sealed class HistorianAlarmEventDto
{
    [Key(0)] public string AlarmId { get; set; } = string.Empty;
    [Key(1)] public string EquipmentPath { get; set; } = string.Empty;
    [Key(2)] public string AlarmName { get; set; } = string.Empty;

    /// <summary>Concrete Part 9 subtype name — "LimitAlarm" / "OffNormalAlarm" / "AlarmCondition" / "DiscreteAlarm".</summary>
    [Key(3)] public string AlarmTypeName { get; set; } = string.Empty;

    /// <summary>Numeric severity the Host maps to the historian's priority scale.</summary>
    [Key(4)] public int Severity { get; set; }

    /// <summary>Which transition this event represents — "Activated" / "Cleared" / "Acknowledged" / etc.</summary>
    [Key(5)] public string EventKind { get; set; } = string.Empty;

    /// <summary>Pre-rendered message — template tokens resolved upstream.</summary>
    [Key(6)] public string Message { get; set; } = string.Empty;

    /// <summary>Operator who triggered the transition. "system" for engine-driven events.</summary>
    [Key(7)] public string User { get; set; } = "system";

    /// <summary>Operator-supplied free-form comment, if any.</summary>
    [Key(8)] public string? Comment { get; set; }

    /// <summary>Source timestamp (UTC Unix milliseconds).</summary>
    [Key(9)] public long TimestampUtcUnixMs { get; set; }
}

/// <summary>
///     Proactive notification — Galaxy.Host pushes this when the historian SDK session
///     transitions (connected / disconnected / degraded). The main server reflects this
///     into the historian sink status so Admin UI surfaces the problem without the
///     operator having to scrutinize drain cadence.
/// </summary>
[MessagePackObject]
public sealed class HistorianConnectivityStatusNotification
{
    [Key(0)] public string Status { get; set; } = "unknown"; // connected | disconnected | degraded
    [Key(1)] public string? Detail { get; set; }
    [Key(2)] public long ObservedAtUtcUnixMs { get; set; }
}
