using FASTER.core;

namespace FASTERlay;

public class NostrStore : IDisposable
{
    private readonly ILogger<NostrStore> _logger;
    private readonly CancellationTokenSource _cts = new();
    private readonly FasterKVSettings<byte[], byte[]> _storeSettings;
    private readonly FasterKV<byte[], byte[]> _store;
    private readonly FasterKVSettings<string, byte[]> _tagStoreSettings;
    private readonly FasterKV<string, byte[]> _tagStore;

    private readonly Task _checkpointer;

    public NostrStore(string dir, ILogger<NostrStore> logger)
    {
        _logger = logger;
        _storeSettings = new FasterKVSettings<byte[], byte[]>(Path.Combine(dir, "main"), false, _logger);
        _store = new(_storeSettings);
        var version = _store.GetLatestCheckpointVersion();
        if (version != -1)
        {
            _store.Recover();
        }

        _tagStoreSettings = new FasterKVSettings<string, byte[]>(Path.Combine(dir, "tags"), false, _logger);
        _tagStore = new(_tagStoreSettings);
        var keyVersion = _tagStore.GetLatestCheckpointVersion();
        if (keyVersion != -1)
        {
            _tagStore.Recover();
        }

        _checkpointer = Task.Factory.StartNew(async () =>
        {
            while (!_cts.IsCancellationRequested)
            {
                await Task.Delay(10_000);
                await _store.TakeHybridLogCheckpointAsync(CheckpointType.Snapshot, true);
                await _tagStore.TakeHybridLogCheckpointAsync(CheckpointType.Snapshot, true);
            }
        });
    }
    public FasterKV<byte[], byte[]> MainStore => _store;
    public FasterKV<string, byte[]> TagStore => _tagStore;

    public void Dispose()
    {
        _cts.Cancel();
        _checkpointer.ConfigureAwait(false).GetAwaiter().GetResult();

        _store.Dispose();
        _storeSettings.Dispose();
        _tagStore.Dispose();
        _tagStoreSettings.Dispose();
    }
}
