using Microsoft.Extensions.Logging;
using MongoDB.Bson;
using MongoDB.Driver;

namespace StellaOps.Authority.Storage.Mongo.Migrations;

/// <summary>
/// Ensures base Authority collections exist prior to applying indexes.
/// </summary>
internal sealed class EnsureAuthorityCollectionsMigration : IAuthorityMongoMigration
{
    private static readonly string[] RequiredCollections =
    {
        AuthorityMongoDefaults.Collections.Users,
        AuthorityMongoDefaults.Collections.Clients,
        AuthorityMongoDefaults.Collections.Scopes,
        AuthorityMongoDefaults.Collections.Tokens,
        AuthorityMongoDefaults.Collections.LoginAttempts
    };

    private readonly ILogger<EnsureAuthorityCollectionsMigration> logger;

    public EnsureAuthorityCollectionsMigration(ILogger<EnsureAuthorityCollectionsMigration> logger)
        => this.logger = logger ?? throw new ArgumentNullException(nameof(logger));

    public async ValueTask ExecuteAsync(IMongoDatabase database, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(database);

        var existing = await database.ListCollectionNamesAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
        var existingNames = await existing.ToListAsync(cancellationToken).ConfigureAwait(false);

        foreach (var collection in RequiredCollections)
        {
            if (existingNames.Contains(collection, StringComparer.OrdinalIgnoreCase))
            {
                continue;
            }

            logger.LogInformation("Creating Authority Mongo collection '{CollectionName}'.", collection);
            await database.CreateCollectionAsync(collection, cancellationToken: cancellationToken).ConfigureAwait(false);
        }
    }
}
