using ZB.MOM.WW.OtOpcUa.Core.Abstractions;

namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Runtime;

/// <summary>
///     Maps a raw MXAccess alarm severity (0-999, MXAccess scale) onto the
///     <see cref="AlarmSeverity"/> ladder + an OPC UA Part 9 numeric severity (1-1000).
/// </summary>
/// <remarks>
///     <para>
///     The four-bucket OPC UA ladder (250 / 500 / 750 / 1000 — Low / Medium / High /
///     Critical) is the same ladder v1's <c>GalaxyAlarmTracker</c> exposed (per
///     <c>docs/v1/AlarmTracking.md</c>). Galaxy templates assign severity values
///     0-999; the bucket boundaries below match v1 so customers see no
///     surprise re-classification when the v2 path takes over.
///     </para>
///     <para>
///     Out-of-range inputs (negative or &gt;= 1000) are clamped into the nearest
///     bucket rather than rejected. MXAccess occasionally surfaces slightly
///     out-of-range severities for legacy alarm types and we want them to flow
///     through the alarm path rather than disappear at the mapper.
///     </para>
/// </remarks>
internal static class MxAccessSeverityMapper
{
    /// <summary>OPC UA Part 9 numeric severity for the Low bucket (0-249 MxAccess).</summary>
    public const int OpcUaSeverityLow = 250;
    /// <summary>OPC UA Part 9 numeric severity for the Medium bucket (250-499 MxAccess).</summary>
    public const int OpcUaSeverityMedium = 500;
    /// <summary>OPC UA Part 9 numeric severity for the High bucket (500-749 MxAccess).</summary>
    public const int OpcUaSeverityHigh = 750;
    /// <summary>OPC UA Part 9 numeric severity for the Critical bucket (750+ MxAccess).</summary>
    public const int OpcUaSeverityCritical = 1000;

    /// <summary>
    ///     Translate a raw MXAccess severity into the four-bucket
    ///     <see cref="AlarmSeverity"/> + OPC UA Part 9 numeric severity tuple.
    /// </summary>
    /// <param name="rawMxAccessSeverity">The raw MXAccess severity value (0-999 range, clamped if out of range).</param>
    /// <returns>The mapped four-bucket <see cref="AlarmSeverity"/> and its OPC UA Part 9 numeric severity.</returns>
    public static (AlarmSeverity Bucket, int OpcUaSeverity) Map(int rawMxAccessSeverity)
    {
        if (rawMxAccessSeverity < 250)
        {
            return (AlarmSeverity.Low, OpcUaSeverityLow);
        }
        if (rawMxAccessSeverity < 500)
        {
            return (AlarmSeverity.Medium, OpcUaSeverityMedium);
        }
        if (rawMxAccessSeverity < 750)
        {
            return (AlarmSeverity.High, OpcUaSeverityHigh);
        }
        return (AlarmSeverity.Critical, OpcUaSeverityCritical);
    }
}
