using OpenTelemetry.Resources;
using ZB.MOM.WW.Telemetry;

namespace ZB.MOM.WW.Telemetry.Tests;

public sealed class ZbResourceTests
{
    [Fact]
    public void Build_PopulatesAllResourceAttributes()
    {
        var options = new ZbTelemetryOptions
        {
            ServiceName = "otopcua",
            ServiceNamespace = "ZB.MOM.WW",
            ServiceVersion = "1.2.3",
            SiteId = "site-7",
            NodeRole = "central",
        };

        var resource = ZbResource.Build(options).Build();
        var attributes = resource.Attributes.ToDictionary(a => a.Key, a => a.Value);

        Assert.Equal("otopcua", attributes["service.name"]);
        Assert.Equal("ZB.MOM.WW", attributes["service.namespace"]);
        Assert.Equal("1.2.3", attributes["service.version"]);
        Assert.Equal("site-7", attributes["site.id"]);
        Assert.Equal("central", attributes["node.role"]);
        Assert.Equal(Environment.MachineName, attributes["host.name"]);
        // service.instance.id must be the deterministic MachineName:ProcessId — NOT a random GUID.
        Assert.Equal(ZbResource.InstanceId, attributes["service.instance.id"]);
    }

    [Fact]
    public void Build_OmitsOptionalAttributes_WhenNull()
    {
        var options = new ZbTelemetryOptions
        {
            ServiceName = "mxgateway",
            // ServiceVersion / SiteId / NodeRole left null
        };

        var resource = ZbResource.Build(options).Build();
        var keys = resource.Attributes.Select(a => a.Key).ToHashSet();

        Assert.Contains("service.name", keys);
        Assert.Contains("service.namespace", keys);
        Assert.Contains("host.name", keys);
        // service.instance.id is always present (deterministic, not optional).
        Assert.Contains("service.instance.id", keys);
        Assert.DoesNotContain("service.version", keys);
        Assert.DoesNotContain("site.id", keys);
        Assert.DoesNotContain("node.role", keys);
    }

    [Fact]
    public void InstanceId_is_deterministic_MachineName_colon_ProcessId()
    {
        // InstanceId must be stable within the process and follow the MachineName:ProcessId format.
        var expected = $"{Environment.MachineName}:{Environment.ProcessId}";
        Assert.Equal(expected, ZbResource.InstanceId);
        // Calling it twice returns the same value (no random component).
        Assert.Equal(ZbResource.InstanceId, ZbResource.InstanceId);
    }

    [Fact]
    public void InstanceId_does_not_contain_a_random_guid()
    {
        // The old OTel SDK default was a random GUID; the deterministic id must NOT be a GUID.
        Assert.False(
            Guid.TryParse(ZbResource.InstanceId, out _),
            $"service.instance.id must not be a GUID; got '{ZbResource.InstanceId}'");
    }
}
