using Serilog;
using Serilog.Events;
using Serilog.Sinks.InMemory;
using ZB.MOM.WW.Telemetry;
using ZB.MOM.WW.Telemetry.Serilog;

namespace ZB.MOM.WW.Telemetry.Serilog.Tests;

public sealed class EnricherTests
{
    private static string ScalarValue(LogEvent logEvent, string propertyName)
    {
        Assert.True(
            logEvent.Properties.TryGetValue(propertyName, out var value),
            $"expected property '{propertyName}' to be present");
        var scalar = Assert.IsType<ScalarValue>(value);
        return scalar.Value?.ToString() ?? "";
    }

    [Fact]
    public void Identity_enrichers_stamp_SiteId_NodeRole_and_NodeHostname()
    {
        var sink = new InMemorySink();
        var options = new ZbTelemetryOptions
        {
            ServiceName = "otopcua",
            SiteId = "s1",
            NodeRole = "Central",
        };

        var loggerConfig = new LoggerConfiguration();
        ZbSerilogConfig.Apply(loggerConfig, options);
        using var logger = loggerConfig
            .WriteTo.Sink(sink)
            .CreateLogger();

        logger.Information("hello");

        var logEvent = Assert.Single(sink.LogEvents);
        Assert.Equal("s1", ScalarValue(logEvent, ZbLogEnricherNames.SiteId));
        Assert.Equal("Central", ScalarValue(logEvent, ZbLogEnricherNames.NodeRole));
        Assert.Equal(
            Environment.MachineName,
            ScalarValue(logEvent, ZbLogEnricherNames.NodeHostname));
    }

    [Fact]
    public void Null_SiteId_and_NodeRole_are_suppressed_but_NodeHostname_is_always_present()
    {
        var sink = new InMemorySink();
        var options = new ZbTelemetryOptions
        {
            ServiceName = "otopcua",
            SiteId = null,
            NodeRole = null,
        };

        var loggerConfig = new LoggerConfiguration();
        ZbSerilogConfig.Apply(loggerConfig, options);
        using var logger = loggerConfig
            .WriteTo.Sink(sink)
            .CreateLogger();

        logger.Information("hello");

        var logEvent = Assert.Single(sink.LogEvents);
        Assert.False(logEvent.Properties.ContainsKey(ZbLogEnricherNames.SiteId),
            "SiteId should be absent when null");
        Assert.False(logEvent.Properties.ContainsKey(ZbLogEnricherNames.NodeRole),
            "NodeRole should be absent when null");
        Assert.Equal(
            Environment.MachineName,
            ScalarValue(logEvent, ZbLogEnricherNames.NodeHostname));
    }
}
