using Google.Protobuf.WellKnownTypes;
using ZB.MOM.WW.HistorianGateway.Contracts.Grpc;
using ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian;

namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Mapping;

/// <summary>
/// Maps a driver-agnostic <see cref="AlarmHistorianEvent"/> onto a gateway wire
/// <see cref="HistorianEvent"/> for the <c>SendEvent</c> write path.
/// </summary>
internal static class AlarmEventMapper
{
    /// <summary>Maps an alarm historian event to a gateway event.</summary>
    /// <param name="alarm">The driver-agnostic alarm event.</param>
    /// <returns>The gateway wire event ready for <c>SendEvent</c>.</returns>
    public static HistorianEvent ToHistorianEvent(AlarmHistorianEvent alarm)
    {
        // Timestamp.FromDateTime requires a Utc-kind DateTime; coerce defensively (TimestampUtc is
        // already Utc by contract, but a caller could pass Unspecified).
        var eventTime = Timestamp.FromDateTime(DateTime.SpecifyKind(alarm.TimestampUtc, DateTimeKind.Utc));

        var historianEvent = new HistorianEvent
        {
            // Deliberately DO NOT set HistorianEvent.Id: the gateway's SendEvent path rejects a
            // client-supplied event id (the server handler throws and the call fails permanently —
            // confirmed live). The historian assigns event identity server-side; the alarm's own id
            // is preserved below as a property for read-back correlation/traceability.
            SourceName = alarm.EquipmentPath,
            Type = alarm.AlarmTypeName,
            EventTime = eventTime,
            ReceivedTime = eventTime, // the server re-stamps the received time on the SQL path
        };

        // Proto map<string,string> values must be non-null — only insert non-null properties.
        if (!string.IsNullOrWhiteSpace(alarm.AlarmId))
            historianEvent.Properties["AlarmId"] = alarm.AlarmId;
        historianEvent.Properties["AlarmName"] = alarm.AlarmName;
        historianEvent.Properties["EventKind"] = alarm.EventKind;
        historianEvent.Properties["Severity"] = alarm.Severity.ToString();
        historianEvent.Properties["User"] = alarm.User;
        historianEvent.Properties["Message"] = alarm.Message;
        if (alarm.Comment is not null)
            historianEvent.Properties["Comment"] = alarm.Comment;

        return historianEvent;
    }
}
