using System.Linq;
using Microsoft.Extensions.Logging;
using StellaOps.Excititor.Core;

namespace StellaOps.Excititor.Connectors.Abstractions;

/// <summary>
/// Helper to establish deterministic logging scopes for connector operations.
/// </summary>
public static class VexConnectorLogScope
{
    public static IDisposable Begin(ILogger logger, VexConnectorDescriptor descriptor, string operation, IReadOnlyDictionary<string, object?>? metadata = null)
    {
        ArgumentNullException.ThrowIfNull(logger);
        ArgumentNullException.ThrowIfNull(descriptor);
        ArgumentException.ThrowIfNullOrEmpty(operation);

        var scopeValues = new List<KeyValuePair<string, object?>>
        {
            new("vex.connector.id", descriptor.Id),
            new("vex.connector.kind", descriptor.Kind.ToString()),
            new("vex.connector.operation", operation),
        };

        if (!string.Equals(descriptor.DisplayName, descriptor.Id, StringComparison.Ordinal))
        {
            scopeValues.Add(new KeyValuePair<string, object?>("vex.connector.displayName", descriptor.DisplayName));
        }

        if (!string.IsNullOrWhiteSpace(descriptor.Description))
        {
            scopeValues.Add(new KeyValuePair<string, object?>("vex.connector.description", descriptor.Description));
        }

        if (!descriptor.Tags.IsDefaultOrEmpty)
        {
            scopeValues.Add(new KeyValuePair<string, object?>("vex.connector.tags", string.Join(",", descriptor.Tags)));
        }

        if (metadata is not null)
        {
            foreach (var kvp in metadata.OrderBy(static pair => pair.Key, StringComparer.Ordinal))
            {
                scopeValues.Add(new KeyValuePair<string, object?>($"vex.{kvp.Key}", kvp.Value));
            }
        }

        return logger.BeginScope(scopeValues)!;
    }
}
