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

namespace StellaOps.Authority.Storage.Mongo.Migrations;

/// <summary>
/// Executes registered Authority Mongo migrations sequentially.
/// </summary>
public sealed class AuthorityMongoMigrationRunner
{
    private readonly IEnumerable<IAuthorityMongoMigration> migrations;
    private readonly ILogger<AuthorityMongoMigrationRunner> logger;

    public AuthorityMongoMigrationRunner(
        IEnumerable<IAuthorityMongoMigration> migrations,
        ILogger<AuthorityMongoMigrationRunner> logger)
    {
        this.migrations = migrations ?? throw new ArgumentNullException(nameof(migrations));
        this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

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

        foreach (var migration in migrations)
        {
            try
            {
                logger.LogInformation("Running Authority Mongo migration {MigrationType}.", migration.GetType().FullName);
                await migration.ExecuteAsync(database, cancellationToken).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Authority Mongo migration {MigrationType} failed.", migration.GetType().FullName);
                throw;
            }
        }
    }
}
