using System;
using System.Collections.Generic;
using System.Linq;

namespace StellaOps.Auth.Client;

/// <summary>
/// Represents a cached token entry.
/// </summary>
public sealed record StellaOpsTokenCacheEntry(
    string AccessToken,
    string TokenType,
    DateTimeOffset ExpiresAtUtc,
    IReadOnlyList<string> Scopes,
    string? RefreshToken = null,
    string? IdToken = null,
    IReadOnlyDictionary<string, string>? Metadata = null)
{
    /// <summary>
    /// Determines whether the token is expired given the provided <see cref="TimeProvider"/>.
    /// </summary>
    public bool IsExpired(TimeProvider timeProvider, TimeSpan? skew = null)
    {
        ArgumentNullException.ThrowIfNull(timeProvider);
        var now = timeProvider.GetUtcNow();
        var buffer = skew ?? TimeSpan.Zero;
        return now >= ExpiresAtUtc - buffer;
    }

    /// <summary>
    /// Creates a copy with scopes normalised.
    /// </summary>
    public StellaOpsTokenCacheEntry NormalizeScopes()
    {
        if (Scopes.Count == 0)
        {
            return this;
        }

        var normalized = Scopes
            .Where(scope => !string.IsNullOrWhiteSpace(scope))
            .Select(scope => scope.Trim())
            .Distinct(StringComparer.Ordinal)
            .OrderBy(scope => scope, StringComparer.Ordinal)
            .ToArray();

        return this with { Scopes = normalized };
    }
}
