// Copyright (c) 2026 Kirky.X
//
// Licensed under the MIT License
// See LICENSE file in the project root for full license information.

//! 缓存集成测试
//!
//! 测试缓存模块与数据库操作的完整集成功能，包括：
//! - 缓存与 Session 集成
//! - 缓存命中/未命中场景
//! - 缓存失效机制
//! - 缓存穿透防护
//! - 缓存击穿保护
//! - 批量缓存操作
//! - 缓存预热
//! - 缓存统计

use dbnexus::DbPool;
use dbnexus::cache::{CacheConfig, CacheKey, CacheManager};
use std::time::Duration;

#[path = "../../common/mod.rs"]
mod common;

/// TEST-CACHE-001: 缓存基本操作测试
///
/// 验证缓存的基本 get/set/delete 操作
#[tokio::test]
async fn test_cache_basic_operations() {
    let config = CacheConfig {
        max_capacity: 100,
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    let key = CacheKey::new("users", "1");

    // 初始状态：缓存为空
    assert!(cache.get(&key).await.is_none());

    // 设置缓存值
    cache.set(key.clone(), "Alice".to_string()).await;

    // 获取缓存值
    let value = cache.get(&key).await;
    assert_eq!(value, Some("Alice".to_string()));

    // 删除缓存值
    cache.delete(&key).await;

    // 删除后获取应该失败
    assert!(cache.get(&key).await.is_none());
}

/// TEST-CACHE-002: 缓存 TTL 过期测试
///
/// 验证缓存的 TTL 过期机制
#[tokio::test]
async fn test_cache_ttl_expiration() {
    let config = CacheConfig {
        max_capacity: 100,
        default_ttl: 1, // 1 秒 TTL
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    let key = CacheKey::new("users", "1");

    // 设置缓存值
    cache.set(key.clone(), "Alice".to_string()).await;

    // 立即获取应该成功
    let value = cache.get(&key).await;
    assert_eq!(value, Some("Alice".to_string()));

    // 等待过期
    tokio::time::sleep(Duration::from_secs(2)).await;

    // 过期后获取应该失败
    let value = cache.get(&key).await;
    assert!(value.is_none());
}

/// TEST-CACHE-003: 缓存 LRU 淘汰测试
///
/// 验证缓存的 LRU 淘汰机制
#[tokio::test]
async fn test_cache_lru_eviction() {
    let config = CacheConfig {
        max_capacity: 3, // 最大容量 3
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    // 添加 3 个条目
    for i in 0..3 {
        let key = CacheKey::new("users", &i.to_string());
        cache.set(key, format!("User{}", i)).await;
    }

    assert_eq!(cache.len().await, 3);

    // 访问第一个条目（提升其优先级）
    let key0 = CacheKey::new("users", "0");
    let _ = cache.get(&key0).await;

    // 添加第 4 个条目，应该淘汰最久未使用的（第 1 个）
    let key3 = CacheKey::new("users", "3");
    cache.set(key3.clone(), "User3".to_string()).await;

    // 验证缓存大小仍为 3
    assert_eq!(cache.len().await, 3);

    // 验证第 0 个条目仍在（刚访问过）
    assert!(cache.get(&key0).await.is_some());

    // 验证第 3 个条目存在
    assert!(cache.get(&key3).await.is_some());

    // 验证第 1 个条目已被淘汰
    let key1 = CacheKey::new("users", "1");
    assert!(cache.get(&key1).await.is_none());
}

/// TEST-CACHE-004: 自定义 TTL 测试
///
/// 验证使用自定义 TTL 设置缓存
#[tokio::test]
async fn test_cache_custom_ttl() {
    let config = CacheConfig {
        max_capacity: 100,
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    let key1 = CacheKey::new("users", "1");
    let key2 = CacheKey::new("users", "2");

    // 设置短 TTL（1 秒）
    cache
        .set_with_ttl(key1.clone(), "Short TTL".to_string(), Duration::from_secs(1))
        .await;

    // 设置长 TTL（10 秒）
    cache
        .set_with_ttl(key2.clone(), "Long TTL".to_string(), Duration::from_secs(10))
        .await;

    // 立即获取都应该成功
    assert!(cache.get(&key1).await.is_some());
    assert!(cache.get(&key2).await.is_some());

    // 等待 2 秒
    tokio::time::sleep(Duration::from_secs(2)).await;

    // 短 TTL 的应该过期
    assert!(cache.get(&key1).await.is_none());

    // 长 TTL 的应该仍有效
    assert!(cache.get(&key2).await.is_some());
}

/// TEST-CACHE-005: 缓存统计测试
///
/// 验证缓存的统计信息收集
#[tokio::test]
async fn test_cache_statistics() {
    let config = CacheConfig {
        max_capacity: 100,
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    let key1 = CacheKey::new("users", "1");
    let key2 = CacheKey::new("users", "2");

    // 未命中
    cache.get(&key1).await;
    cache.get(&key2).await;

    // 设置
    cache.set(key1.clone(), "User1".to_string()).await;
    cache.set(key2.clone(), "User2".to_string()).await;

    // 命中
    cache.get(&key1).await;
    cache.get(&key2).await;

    // 删除
    cache.delete(&key1).await;

    // 命中率应该是 50%（2 命中 / 4 总请求）
    let hit_rate = cache.stats().hit_rate();
    assert!((hit_rate - 0.5).abs() < 0.01);
}

/// TEST-CACHE-006: 缓存清理测试
///
/// 验证缓存的过期条目清理功能
#[tokio::test]
async fn test_cache_cleanup() {
    let config = CacheConfig {
        max_capacity: 1000,
        default_ttl: 3600,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    // 添加一些已过期的条目
    for i in 0..5 {
        let key = CacheKey::new("expired", &i.to_string());
        cache
            .set_with_ttl(key, format!("Expired{}", i), Duration::from_millis(0))
            .await;
    }

    // 添加一些未过期的条目
    for i in 0..5 {
        let key = CacheKey::new("valid", &i.to_string());
        cache
            .set_with_ttl(key, format!("Valid{}", i), Duration::from_secs(60))
            .await;
    }

    assert_eq!(cache.len().await, 10);

    // 执行清理
    let removed = cache.cleanup().await;

    // 应该清理掉 5 个过期条目
    assert_eq!(removed, 5);
    assert_eq!(cache.len().await, 5);
}

/// TEST-CACHE-007: 缓存预热测试
///
/// 验证缓存的预热功能
#[tokio::test]
async fn test_cache_warmup() {
    let config = CacheConfig {
        max_capacity: 5,
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    // 预热数据（超过容量）
    let data = vec![
        (
            CacheKey::new("warm", "1"),
            "Value1".to_string(),
            Duration::from_secs(60),
        ),
        (
            CacheKey::new("warm", "2"),
            "Value2".to_string(),
            Duration::from_secs(60),
        ),
        (
            CacheKey::new("warm", "3"),
            "Value3".to_string(),
            Duration::from_secs(60),
        ),
        (
            CacheKey::new("warm", "4"),
            "Value4".to_string(),
            Duration::from_secs(60),
        ),
        (
            CacheKey::new("warm", "5"),
            "Value5".to_string(),
            Duration::from_secs(60),
        ),
        (
            CacheKey::new("warm", "6"),
            "Value6".to_string(),
            Duration::from_secs(60),
        ),
    ];

    let loaded = cache.warmup(data).await;

    // 应该只加载 5 个（容量限制）
    assert_eq!(loaded, 5);
    assert_eq!(cache.len().await, 5);
}

/// TEST-CACHE-008: 批量获取测试
///
/// 验证缓存的批量获取功能
#[tokio::test]
async fn test_cache_batch_get() {
    let config = CacheConfig {
        max_capacity: 100,
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    let key1 = CacheKey::new("users", "1");
    let key2 = CacheKey::new("users", "2");
    let key3 = CacheKey::new("users", "3");

    // 设置部分缓存
    cache.set(key1.clone(), "User1".to_string()).await;
    cache.set(key2.clone(), "User2".to_string()).await;

    // 批量获取
    let keys = vec![key1.clone(), key2.clone(), key3.clone()];
    let results = cache.batch_get(&keys).await;

    // 验证结果
    assert_eq!(results.len(), 3);
    assert_eq!(results[0], Some("User1".to_string()));
    assert_eq!(results[1], Some("User2".to_string()));
    assert_eq!(results[2], None);
}

/// TEST-CACHE-009: 批量设置测试
///
/// 验证缓存的批量设置功能
#[tokio::test]
async fn test_cache_batch_set() {
    let config = CacheConfig {
        max_capacity: 100,
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    // 批量设置
    let items = vec![
        (CacheKey::new("batch", "1"), "Value1".to_string()),
        (CacheKey::new("batch", "2"), "Value2".to_string()),
        (CacheKey::new("batch", "3"), "Value3".to_string()),
    ];

    cache.batch_set(items).await;

    // 验证所有值都已设置
    for i in 1..=3 {
        let key = CacheKey::new("batch", &i.to_string());
        assert!(cache.get(&key).await.is_some());
    }

    assert_eq!(cache.len().await, 3);
}

/// TEST-CACHE-010: 批量删除测试
///
/// 验证缓存的批量删除功能
#[tokio::test]
async fn test_cache_batch_delete() {
    let config = CacheConfig {
        max_capacity: 100,
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    // 设置多个值
    for i in 1..=5 {
        let key = CacheKey::new("batch", &i.to_string());
        cache.set(key, format!("Value{}", i)).await;
    }

    assert_eq!(cache.len().await, 5);

    // 批量删除
    let keys = vec![
        CacheKey::new("batch", "1"),
        CacheKey::new("batch", "2"),
        CacheKey::new("batch", "99"), // 不存在的键
    ];

    let removed = cache.batch_delete(&keys).await;

    // 应该删除 2 个存在的键
    assert_eq!(removed, 2);
    assert_eq!(cache.len().await, 3);
}

/// TEST-CACHE-011: 缓存失效测试
///
/// 验证缓存的失效功能
#[tokio::test]
async fn test_cache_invalidation() {
    let config = CacheConfig {
        max_capacity: 100,
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    let key = CacheKey::new("users", "1");
    cache.set(key.clone(), "Alice".to_string()).await;

    // 验证缓存存在
    assert!(cache.get(&key).await.is_some());

    // 失效缓存
    cache.invalidate(&key).await;

    // 验证缓存已失效
    assert!(cache.get(&key).await.is_none());
}

/// TEST-CACHE-012: 模式失效测试
///
/// 验证缓存的模式失效功能
#[tokio::test]
async fn test_cache_invalidation_pattern() {
    let config = CacheConfig {
        max_capacity: 100,
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    // 设置不同表的缓存
    cache.set(CacheKey::new("users", "1"), "User1".to_string()).await;
    cache.set(CacheKey::new("users", "2"), "User2".to_string()).await;
    cache.set(CacheKey::new("orders", "1"), "Order1".to_string()).await;

    assert_eq!(cache.len().await, 3);

    // 失效所有 users 表的缓存
    let removed = cache.invalidate_pattern("users").await;

    // 应该失效 2 个 users 表的缓存
    assert_eq!(removed, 2);
    assert_eq!(cache.len().await, 1);

    // 验证 orders 表的缓存仍在
    assert!(cache.get(&CacheKey::new("orders", "1")).await.is_some());
}

/// TEST-CACHE-013: 缓存清空测试
///
/// 验证缓存的清空功能
#[tokio::test]
async fn test_cache_clear() {
    let config = CacheConfig {
        max_capacity: 100,
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let mut cache = CacheManager::<String>::new(config);

    // 设置多个值
    for i in 1..=10 {
        let key = CacheKey::new("test", &i.to_string());
        cache.set(key, format!("Value{}", i)).await;
    }

    assert_eq!(cache.len().await, 10);
    assert!(!cache.is_empty().await);

    // 清空缓存
    cache.clear().await;

    // 验证缓存已清空
    assert_eq!(cache.len().await, 0);
    assert!(cache.is_empty().await);
}

/// TEST-CACHE-014: 缓存键哈希测试
///
/// 验证缓存键的哈希功能
#[tokio::test]
async fn test_cache_key_hashing() {
    let config = CacheConfig::default();
    let cache = CacheManager::<String>::new(config);

    // 使用相同值创建的键应该相等
    let key1 = CacheKey::from_value("users", &"test_value");
    let key2 = CacheKey::from_value("users", &"test_value");
    let key3 = CacheKey::from_value("users", &"different_value");

    assert_eq!(key1, key2);
    assert_ne!(key1, key3);

    // 设置并验证
    cache.set(key1.clone(), "Value1".to_string()).await;
    assert!(cache.get(&key2).await.is_some()); // 相同的键应该命中
    assert!(cache.get(&key3).await.is_none()); // 不同的键应该未命中
}

/// TEST-CACHE-015: 缓存与数据库集成测试
///
/// 验证缓存与数据库操作的集成
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_cache_with_database_integration() {
    let config = common::get_test_config();
    let pool = DbPool::with_config(config).await.expect("Failed to create pool");

    // 创建缓存
    let cache_config = CacheConfig {
        max_capacity: 100,
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(cache_config);

    // 获取会话并创建表
    let session = pool.get_session("admin").await.expect("Failed to get session");

    session
        .execute_raw_ddl(
            "CREATE TABLE cache_test (
                id INTEGER PRIMARY KEY,
                value TEXT NOT NULL
            )",
        )
        .await
        .expect("Failed to create table");

    // 从数据库获取数据并缓存
    let key = CacheKey::new("cache_test", "1");

    // 第一次获取：缓存未命中
    let cached = cache.get(&key).await;
    assert!(cached.is_none());

    // 模拟从数据库获取
    let db_value = "From Database".to_string();
    cache.set(key.clone(), db_value.clone()).await;

    // 第二次获取：缓存命中
    let cached = cache.get(&key).await;
    assert_eq!(cached, Some(db_value));

    // 验证统计信息
    let hit_rate = cache.stats().hit_rate();
    assert!((hit_rate - 0.5).abs() < 0.01);
}

/// TEST-CACHE-016: 缓存并发访问测试
///
/// 验证缓存的并发访问安全性
#[tokio::test]
async fn test_cache_concurrent_access() {
    let config = CacheConfig {
        max_capacity: 100,
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = std::sync::Arc::new(CacheManager::<String>::new(config));

    // 创建多个并发任务
    let mut handles = vec![];

    for i in 0..10 {
        let cache_clone = cache.clone();
        let handle = tokio::spawn(async move {
            let key = CacheKey::new("concurrent", &i.to_string());
            cache_clone.set(key.clone(), format!("Value{}", i)).await;
            let value = cache_clone.get(&key).await;
            value
        });
        handles.push(handle);
    }

    // 等待所有任务完成
    let results: Vec<_> = futures::future::join_all(handles).await;

    // 验证所有操作都成功
    assert_eq!(results.len(), 10);
    for result in results {
        assert!(result.is_ok());
        assert!(result.unwrap().is_some());
    }

    // 验证缓存大小
    assert_eq!(cache.len().await, 10);
}

/// TEST-CACHE-017: 缓存容量限制测试
///
/// 验证缓存的容量限制功能
#[tokio::test]
async fn test_cache_capacity_limit() {
    let config = CacheConfig {
        max_capacity: 5,
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    // 添加超过容量的条目
    for i in 0..10 {
        let key = CacheKey::new("capacity", &i.to_string());
        cache.set(key, format!("Value{}", i)).await;
    }

    // 验证缓存大小不超过容量限制
    assert!(cache.len().await <= 5);
}

/// TEST-CACHE-018: 缓存命中率计算测试
///
/// 验证缓存命中率的计算准确性
#[tokio::test]
async fn test_cache_hit_rate_calculation() {
    let config = CacheConfig {
        max_capacity: 100,
        default_ttl: 60,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    let key = CacheKey::new("hitrate", "1");

    // 10 次未命中
    for _ in 0..10 {
        cache.get(&key).await;
    }

    // 设置缓存
    cache.set(key.clone(), "Value".to_string()).await;

    // 10 次命中
    for _ in 0..10 {
        cache.get(&key).await;
    }

    // 命中率应该是 50%
    let hit_rate = cache.stats().hit_rate();
    assert!((hit_rate - 0.5).abs() < 0.01);
}

/// TEST-CACHE-019: 缓存键模式匹配测试
///
/// 验证缓存键的模式匹配功能
#[tokio::test]
async fn test_cache_key_pattern_matching() {
    let key1 = CacheKey::new("users", "1");
    let key2 = CacheKey::new("orders", "1");
    let key3 = CacheKey::new("users", "2");

    // 精确匹配
    assert!(key1.matches_pattern("users:1"));
    assert!(!key1.matches_pattern("users:2"));

    // 前缀匹配
    assert!(key1.matches_pattern("users"));
    assert!(!key2.matches_pattern("users"));

    // 通配符匹配
    assert!(key1.matches_pattern("users:*"));
    assert!(key3.matches_pattern("users:*"));
    assert!(!key2.matches_pattern("users:*"));
}

/// TEST-CACHE-020: 缓存预热默认 TTL 测试
///
/// 验证使用默认 TTL 的缓存预热
#[tokio::test]
async fn test_cache_warmup_with_default_ttl() {
    let config = CacheConfig {
        max_capacity: 10,
        default_ttl: 30,
        cleanup_interval: 10,
        enable_stats: true,
    };
    let cache = CacheManager::<String>::new(config);

    // 使用默认 TTL 预热
    let data = vec![
        (CacheKey::new("warm", "1"), "Value1".to_string()),
        (CacheKey::new("warm", "2"), "Value2".to_string()),
    ];

    let loaded = cache.warmup_with_default_ttl(data).await;

    assert_eq!(loaded, 2);
    assert_eq!(cache.len().await, 2);

    // 验证值可以获取
    let key1 = CacheKey::new("warm", "1");
    assert!(cache.get(&key1).await.is_some());
}
