using System.Collections.Concurrent;
using ZB.MOM.WW.CBDD.Bson.Schema;
using ZB.MOM.WW.CBDD.Core.CDC;
using ZB.MOM.WW.CBDD.Core.Collections;
using ZB.MOM.WW.CBDD.Core.Compression;
using ZB.MOM.WW.CBDD.Core.Transactions;

namespace ZB.MOM.WW.CBDD.Core.Storage;

/// <summary>
///     Storage port used by collection/index orchestration to avoid concrete engine coupling.
/// </summary>
internal interface IStorageEngine : IIndexStorage, IDisposable
{
    /// <summary>
    ///     Gets the current page count.
    /// </summary>
    uint PageCount { get; }

    /// <summary>
    ///     Gets the active change stream dispatcher.
    /// </summary>
    ChangeStreamDispatcher? Cdc { get; }

    /// <summary>
    ///     Gets compression options used by the storage engine.
    /// </summary>
    CompressionOptions CompressionOptions { get; }

    /// <summary>
    ///     Gets the compression service.
    /// </summary>
    CompressionService CompressionService { get; }

    /// <summary>
    ///     Gets compression telemetry for the storage engine.
    /// </summary>
    CompressionTelemetry CompressionTelemetry { get; }

    /// <summary>
    ///     Determines whether a page is locked.
    /// </summary>
    /// <param name="pageId">The page identifier to inspect.</param>
    /// <param name="excludingTxId">A transaction identifier to exclude from lock checks.</param>
    bool IsPageLocked(uint pageId, ulong excludingTxId);

    /// <summary>
    ///     Registers the change stream dispatcher.
    /// </summary>
    /// <param name="cdc">The change stream dispatcher instance.</param>
    void RegisterCdc(ChangeStreamDispatcher cdc);

    /// <summary>
    ///     Begins a transaction.
    /// </summary>
    /// <param name="isolationLevel">The transaction isolation level.</param>
    Transaction BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted);

    /// <summary>
    ///     Begins a transaction asynchronously.
    /// </summary>
    /// <param name="isolationLevel">The transaction isolation level.</param>
    /// <param name="ct">A cancellation token.</param>
    Task<Transaction> BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted,
        CancellationToken ct = default);

    /// <summary>
    ///     Gets collection metadata by name.
    /// </summary>
    /// <param name="name">The collection name.</param>
    CollectionMetadata? GetCollectionMetadata(string name);

    /// <summary>
    ///     Saves collection metadata.
    /// </summary>
    /// <param name="metadata">The metadata to persist.</param>
    void SaveCollectionMetadata(CollectionMetadata metadata);

    /// <summary>
    ///     Registers document mappers.
    /// </summary>
    /// <param name="mappers">The mapper instances to register.</param>
    void RegisterMappers(IEnumerable<IDocumentMapper> mappers);

    /// <summary>
    ///     Gets schema chain entries for the specified root page.
    /// </summary>
    /// <param name="rootPageId">The schema root page identifier.</param>
    List<BsonSchema> GetSchemas(uint rootPageId);

    /// <summary>
    ///     Appends a schema to the specified schema chain.
    /// </summary>
    /// <param name="rootPageId">The schema root page identifier.</param>
    /// <param name="schema">The schema to append.</param>
    uint AppendSchema(uint rootPageId, BsonSchema schema);

    /// <summary>
    ///     Gets the key-to-token mapping.
    /// </summary>
    ConcurrentDictionary<string, ushort> GetKeyMap();

    /// <summary>
    ///     Gets the token-to-key mapping.
    /// </summary>
    ConcurrentDictionary<ushort, string> GetKeyReverseMap();

    /// <summary>
    ///     Gets or creates a dictionary token for the specified key.
    /// </summary>
    /// <param name="key">The key value.</param>
    ushort GetOrAddDictionaryEntry(string key);

    /// <summary>
    ///     Registers key values in the dictionary mapping.
    /// </summary>
    /// <param name="keys">The keys to register.</param>
    void RegisterKeys(IEnumerable<string> keys);
}