package com.ecep.contract.util;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;

import java.util.HashSet;
import java.util.Set;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

/**
 * RedisCacheCleaner的测试类，用于验证缓存清理功能
 */
class RedisCacheCleanerTest {

    @Mock
    private RedisTemplate<String, Object> redisTemplate;

    @InjectMocks
    private RedisCacheCleaner cacheCleaner;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this);
    }

    /**
     * 测试cleanCacheByPattern方法，验证按模式清理缓存功能
     */
    @Test
    void testCleanCacheByPattern() {
        // 准备测试数据
        String pattern = "contract:*";
        Set<String> keys = new HashSet<>();
        keys.add("contract:1");
        keys.add("contract:2");
        keys.add("contract:3");

        // 模拟RedisTemplate的scan和delete方法
        when(redisTemplate.keys(anyString())).thenReturn(keys);
        when(redisTemplate.delete(anyCollection())).thenReturn(1L);

        // 执行方法
        int result = cacheCleaner.cleanCacheByPattern(pattern);

        // 验证结果
        assertEquals(3, result);

        // 验证方法调用
        verify(redisTemplate, times(1)).keys(pattern);
        verify(redisTemplate, times(1)).delete(keys);
    }

    /**
     * 测试cleanCacheByPattern方法，验证没有匹配键的情况
     */
    @Test
    void testCleanCacheByPattern_NoKeysFound() {
        // 准备测试数据
        String pattern = "non_existent:*";

        // 模拟RedisTemplate的keys方法返回空集合
        when(redisTemplate.keys(anyString())).thenReturn(new HashSet<>());

        // 执行方法
        int result = cacheCleaner.cleanCacheByPattern(pattern);

        // 验证结果
        assertEquals(0, result);

        // 验证方法调用
        verify(redisTemplate, times(1)).keys(pattern);
        verify(redisTemplate, times(0)).delete(anyCollection());
    }

    /**
     * 测试cleanCacheByPattern方法，验证RedisTemplate返回null的情况
     */
    @Test
    void testCleanCacheByPattern_NullKeys() {
        // 准备测试数据
        String pattern = "test:*";

        // 模拟RedisTemplate的keys方法返回null
        when(redisTemplate.keys(anyString())).thenReturn(null);

        // 执行方法
        int result = cacheCleaner.cleanCacheByPattern(pattern);

        // 验证结果
        assertEquals(0, result);

        // 验证方法调用
        verify(redisTemplate, times(1)).keys(pattern);
        verify(redisTemplate, times(0)).delete(anyCollection());
    }

    /**
     * 测试cleanAllCache方法，验证清理所有缓存功能
     */
    @Test
    void testCleanAllCache() {
        // 准备测试数据
        Set<String> keys = new HashSet<>();
        keys.add("contract:1");
        keys.add("project:1");
        keys.add("user:1");

        // 模拟RedisTemplate的scan和delete方法
        when(redisTemplate.keys("*"))
                .thenReturn(keys)
                .thenReturn(new HashSet<>()); // 第二次调用返回空，结束循环

        when(redisTemplate.delete(anyCollection())).thenReturn(1L);

        // 执行方法
        int result = cacheCleaner.cleanAllCache();

        // 验证结果
        assertEquals(3, result);

        // 验证方法调用
        verify(redisTemplate, atLeastOnce()).keys("*");
        verify(redisTemplate, times(1)).delete(keys);
    }

    /**
     * 测试cleanCache方法，验证清理指定键的缓存功能
     */
    @Test
    void testCleanCache() {
        // 准备测试数据
        String key = "contract:1";

        // 模拟RedisTemplate的delete方法
        when(redisTemplate.delete(anyString())).thenReturn(true);

        // 执行方法
        boolean result = cacheCleaner.cleanCache(key);

        // 验证结果
        assertTrue(result);

        // 验证方法调用
        verify(redisTemplate, times(1)).delete(key);
    }

    /**
     * 测试cleanCache方法，验证清理不存在键的缓存功能
     */
    @Test
    void testCleanCache_KeyNotFound() {
        // 准备测试数据
        String key = "non_existent:1";

        // 模拟RedisTemplate的delete方法返回false
        when(redisTemplate.delete(anyString())).thenReturn(false);

        // 执行方法
        boolean result = cacheCleaner.cleanCache(key);

        // 验证结果
        assertFalse(result);

        // 验证方法调用
        verify(redisTemplate, times(1)).delete(key);
    }

    /**
     * 测试cleanMultipleKeys方法，验证清理多个键的缓存功能
     */
    @Test
    void testCleanMultipleKeys() {
        // 准备测试数据
        String[] keys = {"contract:1", "contract:2", "contract:3"};

        // 模拟RedisTemplate的delete方法
        when(redisTemplate.delete(anyCollection())).thenReturn(3L);

        // 执行方法
        long result = cacheCleaner.cleanMultipleKeys(keys);

        // 验证结果
        assertEquals(3, result);

        // 验证方法调用
        verify(redisTemplate, times(1)).delete(anyCollection());
    }

    /**
     * 测试cleanServiceCache方法，验证清理特定服务的缓存功能
     */
    @Test
    void testCleanServiceCache() {
        // 准备测试数据
        String serviceName = "ContractService";
        Set<String> keys = new HashSet<>();
        keys.add("contract:1");
        keys.add("contract:2");

        // 模拟RedisTemplate的keys和delete方法
        when(redisTemplate.keys("contract:*")).thenReturn(keys);
        when(redisTemplate.delete(anyCollection())).thenReturn(1L);

        // 执行方法
        int result = cacheCleaner.cleanServiceCache(serviceName);

        // 验证结果
        assertEquals(2, result);

        // 验证方法调用
        verify(redisTemplate, times(1)).keys("contract:*");
        verify(redisTemplate, times(1)).delete(keys);
    }

    /**
     * 测试cleanAllServiceCache方法，验证清理所有服务相关缓存功能
     */
    @Test
    void testCleanAllServiceCache() {
        // 准备测试数据
        String[] serviceNames = {"ContractService", "ProjectService", "UserService"};
        Set<String> contractKeys = new HashSet<>();
        contractKeys.add("contract:1");
        Set<String> projectKeys = new HashSet<>();
        projectKeys.add("project:1");
        Set<String> userKeys = new HashSet<>();
        userKeys.add("user:1");

        // 模拟RedisTemplate的keys和delete方法
        when(redisTemplate.keys("contract:*")).thenReturn(contractKeys);
        when(redisTemplate.keys("project:*")).thenReturn(projectKeys);
        when(redisTemplate.keys("user:*")).thenReturn(userKeys);
        when(redisTemplate.delete(anyCollection())).thenReturn(1L);

        // 执行方法
        int result = cacheCleaner.cleanAllServiceCache(serviceNames);

        // 验证结果
        assertEquals(3, result);

        // 验证方法调用
        verify(redisTemplate, times(1)).keys("contract:*");
        verify(redisTemplate, times(1)).keys("project:*");
        verify(redisTemplate, times(1)).keys("user:*");
        verify(redisTemplate, times(3)).delete(anyCollection());
    }
}