namespace PARR.Core.Common.Interfaces
{
    /// <summary>
    /// Сервис по управлению КЭШ
    /// </summary>
    public interface IRedisCacheService
    {
        ///// <summary>
        ///// Получить кэшированные данные
        ///// </summary>
        ///// <typeparam name="T"></typeparam>
        ///// <param name="key"></param>
        ///// <returns></returns>
        //T? GetCachedData<T>(string key);

        /// <summary>
        /// Получить кэшированные данные асинхронно
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="useCompression">Разрешить сжатие данных</param>
        /// <returns></returns>
        Task<T?> GetCachedDataAsync<T>(string key, bool useCompression = false);

        ///// <summary>
        ///// Добавить в кэш данные
        ///// </summary>
        ///// <typeparam name="T"></typeparam>
        ///// <param name="key"></param>
        ///// <param name="data"></param>
        ///// <param name="cacheDuration"></param>
        //void SetCachedData<T>(string key, T data, TimeSpan cacheDuration);

        /// <summary>
        /// Добавить в кэш данные асинхронно
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="data"></param>
        /// <param name="cacheDuration"></param>
        /// <returns></returns>
        Task SetCachedDataAsync<T>(string key, T data, TimeSpan cacheDuration, bool useCompression = false);

        /// <summary>
        /// Удалить кэшированные данные 
        /// </summary>
        /// <param name="key"></param>
        void DeleteCachedData(string key);

        /// <summary>
        /// Удалить кэшированные данные асинхронно
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task DeleteCachedDataAsync(string key);

        /// <summary>
        /// Сгенерировать уникальный ключ
        /// </summary>
        /// <param name="keyParts"></param>
        /// <param name="keyPartsToHash"></param>
        /// <returns></returns>
        string GetKey(string[] keyParts, string[]? keyPartsToHash = null);


        /// <summary>
        /// Удалить ключи по маске (template*)
        /// </summary>
        /// <param name="pattern"></param>
        /// <param name="batchSize"></param>
        /// <returns></returns>
        Task<int> DeleteKeysByPatternAsync(string pattern, int batchSize = 100);


        #region Работа с Hash

        /// <summary>
        /// Изменить одно поле в Hash
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <param name="value"></param>
        /// <param name="ttl">Если указано, обновится у всего Hash. Если не указано и hash не существовал, создастся Hash с бесокнечным ttl</param>
        /// <param name="useCompression">Сжимать данные</param>
        /// <returns></returns>
        Task SetHashFieldAsync<T>(string hashKey, string field, T value, TimeSpan? ttl = null, bool useCompression = false);

        /// <summary>
        /// Изменить несколько полей в Hash
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="items"></param>
        /// <param name="ttl">Если указано, обновится у всего Hash. Если не указано и hash не существовал, создастся Hash с бесокнечным ttl</param>
        /// <param name="useCompression">Сжимать данные</param>
        /// <returns></returns>
        Task SetHashFieldsAsync<T>(List<(string HashKey, string FieldKey, T Value)> items, TimeSpan? ttl = null, bool useCompression = false);

        /// <summary>
        /// Получить значение поля из Hash
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <returns></returns>
        Task<T?> GetHashFieldAsync<T>(string hashKey, string field, bool useCompression = false);

        /// <summary>
        /// Получить случайную первую запись из Hash
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="hashKey"></param>
        /// <returns></returns>
        Task<(string Field, T? Value)?> GetFirstHashFieldAsync<T>(string hashKey, bool useCompression = false);

        /// <summary>
        /// Получить все значения из Hash
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="hashKey"></param>
        /// <returns></returns>
        Task<Dictionary<string, T>> GetAllHashFieldsAsync<T>(string hashKey, bool useCompression = false);

        /// <summary>
        /// Удалить одну запись из Hash
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <returns></returns>
        Task DeleteHashFieldAsync(string hashKey, string field);

        /// <summary>
        /// Есть ли запись в Hash
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <returns></returns>
        Task<bool> HashFieldExistsAsync(string hashKey, string field);

        /// <summary>
        /// Удалить весь Hash
        /// </summary>
        /// <param name="hashKey"></param>
        /// <returns></returns>
        Task DeleteHashAsync(string hashKey);

        /// <summary>
        /// Получить количество записей в Hash
        /// </summary>
        /// <param name="hashKey"></param>
        /// <returns></returns>
        Task<long> GetHashLengthAsync(string hashKey);

        /// <summary>
        /// Установить TTL для Hash
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="ttl"></param>
        /// <returns></returns>
        Task SetHashTtlAsync(string hashKey, TimeSpan ttl);

        /// <summary>
        /// Получить значения нескольких полей из Hash
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="keys"></param>
        /// <param name="useCompression"></param>
        /// <returns></returns>
        Task<List<T>> GetHashFieldsAsync<T>(List<(string HashKey, string FieldKey)> keys, bool useCompression = false);

        /// <summary>
        /// Удалить список из Hash
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        Task DeleteHashFieldsAsync(List<(string HashKey, string FieldKey)> keys);

        #endregion
    }
}
