using System;
using System.Collections.Generic;
using System.Linq;

namespace EonaCat.LogStack.Telemetry;

public sealed class TelemetrySignal
{
    private readonly object _sync = new();
    private readonly Queue<double> _values = new();

    public string Name { get; }
    public long Count { get; private set; }
    public double Average { get; private set; }
    public double Min { get; private set; }
    public double Max { get; private set; }
    public bool IsAnomaly { get; private set; }

    public TelemetrySignal(string name) => Name = name;

    public void Record(double value, IEnumerable<(string Key, string Value)> tags, int limit)
    {
        lock (_sync)
        {
            Count++;
            Average += (value - Average) / Count;
            Min = Count == 1 ? value : Math.Min(Min, value);
            Max = Count == 1 ? value : Math.Max(Max, value);
            _values.Enqueue(value);
            while (_values.Count > limit)
                _values.Dequeue();
        }
    }

    public void UpdateAnomalyState()
    {
        lock (_sync)
        {
            if (_values.Count < 10) return;
            var avg = _values.Average();
            var variance = _values.Average(v => Math.Pow(v - avg, 2));
            IsAnomaly = Math.Abs(_values.Last() - avg) > Math.Sqrt(variance) * 3;
        }
    }

    public TelemetrySignalSnapshot Snapshot() => new()
    {
        Name = Name,
        Count = Count,
        Average = Average,
        Min = Min,
        Max = Max,
        IsAnomaly = IsAnomaly
    };
}
