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

namespace StellaOps.Feedser.Storage.Mongo.Exporting;

public sealed class ExportStateStore : IExportStateStore
{
    private readonly IMongoCollection<ExportStateDocument> _collection;
    private readonly ILogger<ExportStateStore> _logger;

    public ExportStateStore(IMongoDatabase database, ILogger<ExportStateStore> logger)
    {
        _collection = (database ?? throw new ArgumentNullException(nameof(database)))
            .GetCollection<ExportStateDocument>(MongoStorageDefaults.Collections.ExportState);
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<ExportStateRecord> UpsertAsync(ExportStateRecord record, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(record);

        var document = ExportStateDocumentExtensions.FromRecord(record);
        var options = new FindOneAndReplaceOptions<ExportStateDocument>
        {
            IsUpsert = true,
            ReturnDocument = ReturnDocument.After,
        };

        var replaced = await _collection.FindOneAndReplaceAsync<ExportStateDocument, ExportStateDocument>(
            x => x.Id == record.Id,
            document,
            options,
            cancellationToken).ConfigureAwait(false);
        _logger.LogDebug("Stored export state {StateId}", record.Id);
        return (replaced ?? document).ToRecord();
    }

    public async Task<ExportStateRecord?> FindAsync(string id, CancellationToken cancellationToken)
    {
        var document = await _collection.Find(x => x.Id == id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
        return document?.ToRecord();
    }
}
