using System;
using System.Diagnostics.Metrics;

namespace StellaOps.Feedser.Source.Vndr.Vmware;

/// <summary>
/// VMware connector metrics (fetch, parse, map).
/// </summary>
public sealed class VmwareDiagnostics : IDisposable
{
    public const string MeterName = "StellaOps.Feedser.Source.Vndr.Vmware";
    private const string MeterVersion = "1.0.0";

    private readonly Meter _meter;
    private readonly Counter<long> _fetchItems;
    private readonly Counter<long> _fetchFailures;
    private readonly Counter<long> _fetchUnchanged;
    private readonly Counter<long> _parseFailures;
    private readonly Histogram<long> _mapAffectedCount;

    public VmwareDiagnostics()
    {
        _meter = new Meter(MeterName, MeterVersion);
        _fetchItems = _meter.CreateCounter<long>(
            name: "vmware.fetch.items",
            unit: "documents",
            description: "Number of VMware advisory documents fetched.");
        _fetchFailures = _meter.CreateCounter<long>(
            name: "vmware.fetch.failures",
            unit: "operations",
            description: "Number of VMware fetch failures.");
        _fetchUnchanged = _meter.CreateCounter<long>(
            name: "vmware.fetch.unchanged",
            unit: "documents",
            description: "Number of VMware advisories skipped due to unchanged content.");
        _parseFailures = _meter.CreateCounter<long>(
            name: "vmware.parse.fail",
            unit: "documents",
            description: "Number of VMware advisory documents that failed to parse.");
        _mapAffectedCount = _meter.CreateHistogram<long>(
            name: "vmware.map.affected_count",
            unit: "packages",
            description: "Distribution of affected-package counts emitted per VMware advisory.");
    }

    public void FetchItem() => _fetchItems.Add(1);

    public void FetchFailure() => _fetchFailures.Add(1);

    public void FetchUnchanged() => _fetchUnchanged.Add(1);

    public void ParseFailure() => _parseFailures.Add(1);

    public void MapAffectedCount(int count)
    {
        if (count < 0)
        {
            return;
        }

        _mapAffectedCount.Record(count);
    }

    public Meter Meter => _meter;

    public void Dispose() => _meter.Dispose();
}
