using System.Diagnostics.Metrics;

namespace StellaOps.Feedser.Source.Vndr.Cisco.Internal;

public sealed class CiscoDiagnostics : IDisposable
{
    public const string MeterName = "StellaOps.Feedser.Source.Vndr.Cisco";
    private const string MeterVersion = "1.0.0";

    private readonly Meter _meter;
    private readonly Counter<long> _fetchDocuments;
    private readonly Counter<long> _fetchFailures;
    private readonly Counter<long> _fetchUnchanged;
    private readonly Counter<long> _parseSuccess;
    private readonly Counter<long> _parseFailures;
    private readonly Counter<long> _mapSuccess;
    private readonly Counter<long> _mapFailures;
    private readonly Histogram<long> _mapAffected;

    public CiscoDiagnostics()
    {
        _meter = new Meter(MeterName, MeterVersion);
        _fetchDocuments = _meter.CreateCounter<long>(
            name: "cisco.fetch.documents",
            unit: "documents",
            description: "Number of Cisco advisories fetched.");
        _fetchFailures = _meter.CreateCounter<long>(
            name: "cisco.fetch.failures",
            unit: "operations",
            description: "Number of Cisco fetch failures.");
        _fetchUnchanged = _meter.CreateCounter<long>(
            name: "cisco.fetch.unchanged",
            unit: "documents",
            description: "Number of Cisco advisories skipped because they were unchanged.");
        _parseSuccess = _meter.CreateCounter<long>(
            name: "cisco.parse.success",
            unit: "documents",
            description: "Number of Cisco documents parsed successfully.");
        _parseFailures = _meter.CreateCounter<long>(
            name: "cisco.parse.failures",
            unit: "documents",
            description: "Number of Cisco documents that failed to parse.");
        _mapSuccess = _meter.CreateCounter<long>(
            name: "cisco.map.success",
            unit: "documents",
            description: "Number of Cisco advisories mapped successfully.");
        _mapFailures = _meter.CreateCounter<long>(
            name: "cisco.map.failures",
            unit: "documents",
            description: "Number of Cisco advisories that failed to map to canonical form.");
        _mapAffected = _meter.CreateHistogram<long>(
            name: "cisco.map.affected.packages",
            unit: "packages",
            description: "Distribution of affected package counts emitted per Cisco advisory.");
    }

    public Meter Meter => _meter;

    public void FetchDocument() => _fetchDocuments.Add(1);

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

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

    public void ParseSuccess() => _parseSuccess.Add(1);

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

    public void MapSuccess() => _mapSuccess.Add(1);

    public void MapFailure() => _mapFailures.Add(1);

    public void MapAffected(int count)
    {
        if (count >= 0)
        {
            _mapAffected.Record(count);
        }
    }

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