using System.Diagnostics.Metrics;
using ZB.MOM.WW.ScadaBridge.Commons.Observability;

namespace ZB.MOM.WW.ScadaBridge.Communication.Tests;

/// <summary>
/// Telemetry guards for the aggregated live alarm cache (plan #10, Task 6): the
/// active-aggregator observable gauge reflects Started/Stopped, and the reconnect
/// counter increments on each recorded reconnect. Mirrors the MeterListener read
/// pattern used by <c>SiteStreamGrpcServerTests.SiteConnectionUpGauge_*</c>; reads are
/// relative to a baseline so the process-wide static instruments are robust to any
/// parallel test interleaving.
/// </summary>
public class SiteAlarmLiveCacheTelemetryTests
{
    private static long ReadGauge(string instrumentName)
    {
        long observed = 0;
        using var listener = new MeterListener();
        listener.InstrumentPublished = (instrument, l) =>
        {
            if (instrument.Meter.Name == ScadaBridgeTelemetry.MeterName &&
                instrument.Name == instrumentName)
            {
                l.EnableMeasurementEvents(instrument);
            }
        };
        listener.SetMeasurementEventCallback<long>((_, measurement, _, _) => observed = measurement);
        listener.Start();
        listener.RecordObservableInstruments();
        return observed;
    }

    private static long ReadCounter(string instrumentName, Action act)
    {
        long delta = 0;
        using var listener = new MeterListener();
        listener.InstrumentPublished = (instrument, l) =>
        {
            if (instrument.Meter.Name == ScadaBridgeTelemetry.MeterName &&
                instrument.Name == instrumentName)
            {
                l.EnableMeasurementEvents(instrument);
            }
        };
        listener.SetMeasurementEventCallback<long>((_, measurement, _, _) => delta += measurement);
        listener.Start();
        act();
        return delta;
    }

    [Fact]
    public void ActiveAggregatorGauge_ReflectsStartAndStop()
    {
        const string gauge = "scadabridge.site.alarm_cache.aggregators.active";
        var baseline = ReadGauge(gauge);

        ScadaBridgeTelemetry.LiveAlarmAggregatorStarted();
        try
        {
            Assert.Equal(baseline + 1, ReadGauge(gauge));

            ScadaBridgeTelemetry.LiveAlarmAggregatorStarted();
            try
            {
                Assert.Equal(baseline + 2, ReadGauge(gauge));
            }
            finally
            {
                ScadaBridgeTelemetry.LiveAlarmAggregatorStopped();
            }

            Assert.Equal(baseline + 1, ReadGauge(gauge));
        }
        finally
        {
            ScadaBridgeTelemetry.LiveAlarmAggregatorStopped();
        }

        Assert.Equal(baseline, ReadGauge(gauge));
    }

    [Fact]
    public void ReconnectCounter_IncrementsOnEachRecordedReconnect()
    {
        var delta = ReadCounter("scadabridge.site.alarm_cache.reconnects", () =>
        {
            ScadaBridgeTelemetry.RecordLiveAlarmStreamReconnect();
            ScadaBridgeTelemetry.RecordLiveAlarmStreamReconnect();
        });

        Assert.Equal(2, delta);
    }
}
