using System.Collections.Generic;

namespace StellaOps.Authority.RateLimiting;

/// <summary>
/// Metadata captured for the current request to assist rate limiter partitioning and diagnostics.
/// </summary>
internal sealed class AuthorityRateLimiterMetadata
{
    private static readonly StringComparer OrdinalIgnoreCase = StringComparer.OrdinalIgnoreCase;

    private readonly Dictionary<string, string> tags = new(OrdinalIgnoreCase);

    /// <summary>
    /// Canonical endpoint associated with the request (e.g. "/token").
    /// </summary>
    public string? Endpoint { get; set; }

    /// <summary>
    /// Remote IP address observed for the request (post proxy resolution where available).
    /// </summary>
    public string? RemoteIp { get; set; }

    /// <summary>
    /// Forwarded IP address extracted from proxy headers (if present).
    /// </summary>
    public string? ForwardedFor { get; set; }

    /// <summary>
    /// OAuth client identifier associated with the request, when available.
    /// </summary>
    public string? ClientId { get; set; }

    /// <summary>
    /// Subject identifier (user) associated with the request, when available.
    /// </summary>
    public string? SubjectId { get; set; }

    /// <summary>
    /// Additional metadata tags that can be attached by later handlers.
    /// </summary>
    public IReadOnlyDictionary<string, string> Tags => tags;

    /// <summary>
    /// User agent string associated with the request, if captured.
    /// </summary>
    public string? UserAgent { get; set; }

    /// <summary>
    /// Adds or updates an arbitrary metadata tag for downstream consumers.
    /// </summary>
    /// <param name="name">The tag name.</param>
    /// <param name="value">The tag value (removed when null/whitespace).</param>
    public void SetTag(string name, string? value)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            return;
        }

        if (string.IsNullOrWhiteSpace(value))
        {
            tags.Remove(name);
            return;
        }

        tags[name] = value;
    }
}
