using System;
using System.Diagnostics.Metrics;

namespace StellaOps.Cli.Telemetry;

internal static class CliMetrics
{
    private static readonly Meter Meter = new("StellaOps.Cli", "1.0.0");

    private static readonly Counter<long> ScannerDownloadCounter = Meter.CreateCounter<long>("stellaops.cli.scanner.download.count");
    private static readonly Counter<long> ScannerInstallCounter = Meter.CreateCounter<long>("stellaops.cli.scanner.install.count");
    private static readonly Counter<long> ScanRunCounter = Meter.CreateCounter<long>("stellaops.cli.scan.run.count");
    private static readonly Histogram<double> CommandDurationHistogram = Meter.CreateHistogram<double>("stellaops.cli.command.duration.ms");

    public static void RecordScannerDownload(string channel, bool fromCache)
        => ScannerDownloadCounter.Add(1, new KeyValuePair<string, object?>[]
        {
            new("channel", channel),
            new("cache", fromCache ? "hit" : "miss")
        });

    public static void RecordScannerInstall(string channel)
        => ScannerInstallCounter.Add(1, new KeyValuePair<string, object?>[] { new("channel", channel) });

    public static void RecordScanRun(string runner, int exitCode)
        => ScanRunCounter.Add(1, new KeyValuePair<string, object?>[]
        {
            new("runner", runner),
            new("exit_code", exitCode)
        });

    public static IDisposable MeasureCommandDuration(string command)
    {
        var start = DateTime.UtcNow;
        return new DurationScope(command, start);
    }

    private sealed class DurationScope : IDisposable
    {
        private readonly string _command;
        private readonly DateTime _start;
        private bool _disposed;

        public DurationScope(string command, DateTime start)
        {
            _command = command;
            _start = start;
        }

        public void Dispose()
        {
            if (_disposed)
            {
                return;
            }

            _disposed = true;
            var elapsed = (DateTime.UtcNow - _start).TotalMilliseconds;
            CommandDurationHistogram.Record(elapsed, new KeyValuePair<string, object?>[] { new("command", _command) });
        }
    }
}
