package com.ruoyi.common.core.redis;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import com.ruoyi.common.core.cache.InMemoryCacheStore;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;

class RedisCacheTest
{
    @Test
    void shouldSupportSetGetDeleteAndExpireThroughRedisCacheFacade()
    {
        RedisCache cache = new RedisCache(new InMemoryCacheStore());
        cache.setCacheObject("login_tokens:abc", "payload", 1, TimeUnit.SECONDS);
        assertEquals("payload", cache.getCacheObject("login_tokens:abc"));
        assertTrue(cache.hasKey("login_tokens:abc"));
        assertTrue(cache.deleteObject("login_tokens:abc"));
    }

    @Test
    void shouldSupportKeysBulkDeleteAndRemainingTtl()
    {
        RedisCache cache = new RedisCache(new InMemoryCacheStore());
        cache.setCacheObject("login_tokens:a", "A", 5, TimeUnit.SECONDS);
        cache.setCacheObject("login_tokens:b", "B", 5, TimeUnit.SECONDS);
        cache.setCacheObject("sys_dict:x", "X");

        assertNotNull(cache.getExpire("login_tokens:a"));
        assertTrue(cache.getExpire("login_tokens:a") > 0);
        assertEquals(Set.of("login_tokens:a", "login_tokens:b"), Set.copyOf(cache.keys("login_tokens:*")));
        assertTrue(cache.deleteObject(List.of("login_tokens:a", "login_tokens:b")));
        assertFalse(cache.hasKey("login_tokens:a"));
    }

    @Test
    void shouldIncrementCounterWithinTtlWindow() throws Exception
    {
        RedisCache cache = new RedisCache(new InMemoryCacheStore());
        assertEquals(1L, cache.increment("rate_limit:test", 50, TimeUnit.MILLISECONDS));
        assertEquals(2L, cache.increment("rate_limit:test", 50, TimeUnit.MILLISECONDS));
        Thread.sleep(70);
        assertNull(cache.getCacheObject("rate_limit:test"));
        assertEquals(1L, cache.increment("rate_limit:test", 50, TimeUnit.MILLISECONDS));
    }
}
