using System.Diagnostics.Metrics;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Admin.Services;

namespace ZB.MOM.WW.OtOpcUa.Admin.Tests;

[Trait("Category", "Unit")]
public sealed class RedundancyMetricsTests
{
    [Fact]
    public void RecordRoleTransition_Increments_Counter_WithExpectedTags()
    {
        using var metrics = new RedundancyMetrics();
        using var listener = new MeterListener();
        var observed = new List<(long Value, Dictionary<string, object?> Tags)>();
        listener.InstrumentPublished = (instrument, l) =>
        {
            if (instrument.Meter.Name == RedundancyMetrics.MeterName &&
                instrument.Name == "otopcua.redundancy.role_transition")
            {
                l.EnableMeasurementEvents(instrument);
            }
        };
        listener.SetMeasurementEventCallback<long>((_, value, tags, _) =>
        {
            var dict = new Dictionary<string, object?>();
            foreach (var tag in tags) dict[tag.Key] = tag.Value;
            observed.Add((value, dict));
        });
        listener.Start();

        metrics.RecordRoleTransition("c1", "node-a", "Primary", "Secondary");

        observed.Count.ShouldBe(1);
        observed[0].Value.ShouldBe(1);
        observed[0].Tags["cluster.id"].ShouldBe("c1");
        observed[0].Tags["node.id"].ShouldBe("node-a");
        observed[0].Tags["from_role"].ShouldBe("Primary");
        observed[0].Tags["to_role"].ShouldBe("Secondary");
    }

    [Fact]
    public void SetClusterCounts_Observed_Via_ObservableGauges()
    {
        using var metrics = new RedundancyMetrics();
        metrics.SetClusterCounts("c1", primary: 1, secondary: 2, stale: 0);
        metrics.SetClusterCounts("c2", primary: 0, secondary: 1, stale: 1);

        var observations = new List<(string Name, long Value, string Cluster)>();
        using var listener = new MeterListener();
        listener.InstrumentPublished = (instrument, l) =>
        {
            if (instrument.Meter.Name == RedundancyMetrics.MeterName)
                l.EnableMeasurementEvents(instrument);
        };
        listener.SetMeasurementEventCallback<long>((instrument, value, tags, _) =>
        {
            string? cluster = null;
            foreach (var t in tags) if (t.Key == "cluster.id") cluster = t.Value as string;
            observations.Add((instrument.Name, value, cluster ?? "?"));
        });
        listener.Start();
        listener.RecordObservableInstruments();

        observations.ShouldContain(o => o.Name == "otopcua.redundancy.primary_count" && o.Cluster == "c1" && o.Value == 1);
        observations.ShouldContain(o => o.Name == "otopcua.redundancy.secondary_count" && o.Cluster == "c1" && o.Value == 2);
        observations.ShouldContain(o => o.Name == "otopcua.redundancy.stale_count" && o.Cluster == "c2" && o.Value == 1);
    }
}
