#!/usr/bin/env rust-script
//! ```cargo
//! [dependencies]
//! redis = { version = "0.24", features = ["tokio-comp", "connection-manager"] }
//! tokio = { version = "1", features = ["full"] }
//! serde = { version = "1.0", features = ["derive"] }
//! serde_json = "1.0"
//! ```

use redis::aio::ConnectionManager;
use redis::{AsyncCommands, Client};
use std::time::Instant;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Redis Validation Test ===\n");

    // Test 1: Connection
    println!("Test 1: Connecting to Redis...");
    let client = Client::open("redis://localhost:6379")?;
    let mut conn = ConnectionManager::new(client).await?;
    println!("✓ Connection successful\n");

    // Test 2: PING
    println!("Test 2: Testing PING...");
    let pong: String = redis::cmd("PING").query_async(&mut conn).await?;
    println!("✓ PING response: {}\n", pong);

    // Test 3: SET/GET operations
    println!("Test 3: Testing SET/GET operations...");
    let start = Instant::now();
    conn.set::<&str, &str, ()>("test:key1", "test_value_1").await?;
    let set_duration = start.elapsed();
    println!("✓ SET completed in {:?}", set_duration);

    let start = Instant::now();
    let value: String = conn.get("test:key1").await?;
    let get_duration = start.elapsed();
    println!("✓ GET completed in {:?}, value: {}\n", get_duration, value);

    // Test 4: SET with TTL
    println!("Test 4: Testing SET with TTL...");
    conn.set_ex::<&str, &str, ()>("test:key2", "test_value_2", 300).await?;
    let ttl: i32 = conn.ttl("test:key2").await?;
    println!("✓ SET with TTL successful, TTL: {} seconds\n", ttl);

    // Test 5: DELETE
    println!("Test 5: Testing DELETE...");
    let deleted: i32 = conn.del("test:key1").await?;
    println!("✓ DELETE successful, keys deleted: {}\n", deleted);

    // Test 6: EXISTS
    println!("Test 6: Testing EXISTS...");
    let exists1: bool = conn.exists("test:key2").await?;
    let exists2: bool = conn.exists("test:key1").await?;
    println!("✓ test:key2 exists: {}", exists1);
    println!("✓ test:key1 exists: {}\n", exists2);

    // Test 7: Batch operations
    println!("Test 7: Testing MSET/MGET (batch operations)...");
    let start = Instant::now();
    redis::cmd("MSET")
        .arg("test:batch1").arg("value1")
        .arg("test:batch2").arg("value2")
        .arg("test:batch3").arg("value3")
        .query_async::<()>(&mut conn)
        .await?;
    let mset_duration = start.elapsed();
    println!("✓ MSET completed in {:?}", mset_duration);

    let start = Instant::now();
    let values: Vec<String> = redis::cmd("MGET")
        .arg("test:batch1")
        .arg("test:batch2")
        .arg("test:batch3")
        .query_async(&mut conn)
        .await?;
    let mget_duration = start.elapsed();
    println!("✓ MGET completed in {:?}, values: {:?}\n", mget_duration, values);

    // Test 8: Latency measurements
    println!("Test 8: Latency measurements (10 iterations)...");
    let mut latencies = Vec::new();
    for i in 1..=10 {
        let start = Instant::now();
        let _: () = conn.set(format!("test:latency{}", i), format!("value{}", i)).await?;
        let duration = start.elapsed();
        latencies.push(duration.as_micros());
    }

    let avg_latency = latencies.iter().sum::<u128>() / latencies.len() as u128;
    let min_latency = latencies.iter().min().unwrap();
    let max_latency = latencies.iter().max().unwrap();

    println!("✓ Average latency: {}μs", avg_latency);
    println!("✓ Min latency: {}μs", min_latency);
    println!("✓ Max latency: {}μs\n", max_latency);

    // Test 9: Check server info
    println!("Test 9: Redis server info...");
    let info: String = redis::cmd("INFO").arg("server").query_async(&mut conn).await?;
    for line in info.lines() {
        if line.contains("redis_version") || line.contains("uptime_in_seconds") {
            println!("✓ {}", line);
        }
    }
    println!();

    // Test 10: Check stats
    println!("Test 10: Redis stats...");
    let info: String = redis::cmd("INFO").arg("stats").query_async(&mut conn).await?;
    for line in info.lines() {
        if line.contains("keyspace_hits") || line.contains("keyspace_misses") ||
           line.contains("total_commands_processed") || line.contains("instantaneous_ops_per_sec") {
            println!("✓ {}", line);
        }
    }
    println!();

    // Test 11: Memory usage
    println!("Test 11: Memory usage...");
    let info: String = redis::cmd("INFO").arg("memory").query_async(&mut conn).await?;
    for line in info.lines() {
        if line.contains("used_memory_human") || line.contains("used_memory_peak_human") {
            println!("✓ {}", line);
        }
    }
    println!();

    // Test 12: Cleanup
    println!("Test 12: Cleanup...");
    let keys: Vec<String> = redis::cmd("KEYS").arg("test:*").query_async(&mut conn).await?;
    if !keys.is_empty() {
        let deleted: i32 = conn.del(&keys).await?;
        println!("✓ Cleaned up {} test keys\n", deleted);
    }

    println!("=== All Redis validation tests completed successfully ===");

    Ok(())
}
