using StackExchange.Redis;

public static class TrendCalculator
{
    // NEWS2-relevant codes that support trend detection.
    public static readonly IReadOnlyList<string> TrendCodes = new[]
    {
        "HEART_RATE", "RESP_RATE", "SYSTOLIC_BP", "TEMP_C", "SPO2"
    };

    public static bool IsTrendCode(string observationCode) =>
        TrendCodes.Contains(observationCode);

    public static string HistoryKey(Guid encounterId, string code) =>
        $"trend:{encounterId}:{code}";

    public static RedisKey[] AllHistoryKeys(Guid encounterId) =>
        TrendCodes.Select(c => (RedisKey)HistoryKey(encounterId, c)).ToArray();

    /// <summary>
    /// Computes rate of change (units per minute) between the oldest and newest
    /// entries within the window. Returns null if fewer than 2 entries or window exceeded.
    /// </summary>
    public static decimal? ComputeRatePerMinute(
        IReadOnlyList<TrendHistoryEntry> entries,
        int windowMinutes)
    {
        if (entries.Count < 2) return null;

        var newest = entries[^1];
        var oldest = entries[0];

        var deltaMinutes = (newest.RecordedAt - oldest.RecordedAt).TotalMinutes;
        if (deltaMinutes <= 0 || deltaMinutes > windowMinutes) return null;

        return (newest.Value - oldest.Value) / (decimal)deltaMinutes;
    }

    /// <summary>
    /// Returns true if the rate exceeds the configured threshold.
    /// For SPO2 and SYSTOLIC_BP, checks negative rate (decline) as clinically significant.
    /// </summary>
    public static bool ExceedsThreshold(
        string observationCode,
        decimal ratePerMinute,
        decimal thresholdPerMinute) =>
        observationCode switch
        {
            "SPO2" or "SYSTOLIC_BP" => ratePerMinute <= -thresholdPerMinute,
            _ => ratePerMinute >= thresholdPerMinute
        };

    public static string DescribeTrend(
        string observationCode, decimal ratePerMinute, decimal currentValue) =>
        observationCode switch
        {
            "SPO2" or "SYSTOLIC_BP" =>
                $"Rapid decline: {observationCode} falling at {Math.Abs(ratePerMinute):F2}/min (current {currentValue})",
            _ =>
                $"Rapid rise: {observationCode} rising at {ratePerMinute:F2}/min (current {currentValue})"
        };

    public static string DisplayName(string observationCode) => observationCode switch
    {
        "HEART_RATE"  => "Heart Rate",
        "RESP_RATE"   => "Respiratory Rate",
        "SYSTOLIC_BP" => "Systolic BP",
        "TEMP_C"      => "Temperature",
        "SPO2"        => "SpO2",
        _             => observationCode
    };
}