//! Macros for Redis operation boilerplate reduction.

/// Macro for Redis operations that handles all connection and async boilerplate.
#[macro_export]
macro_rules! redis_operation {
    ($conn:ident => $operation:block) => {{
        use $crate::redis;
        use $crate::{CONNECTION_STATE, ConnectionState, REDIS_POOL, RUNTIME};

        // Get the Redis connection pool (initialized at startup)
        let pool = match REDIS_POOL.get() {
            Some(pool) => pool,
            None => {
                // Attempt lazy initialization if not already initialized
                let rt = &RUNTIME;
                let init_result = rt.block_on(async move {
                    let cfg = redis::config::load();
                    match redis::client::create_redis_pool(&cfg.redis).await {
                        Ok(pool) => {
                            let _ = REDIS_POOL.set(pool);
                            Ok(())
                        }
                        Err(_e) => {
                            let default_cfg = redis::RedisConfig::default();
                            match redis::client::create_redis_pool(&default_cfg).await {
                                Ok(pool) => {
                                    let _ = REDIS_POOL.set(pool);
                                    Ok(())
                                }
                                Err(e) => Err(format!("{}", e)),
                            }
                        }
                    }
                });

                match init_result {
                    Ok(()) => {
                        *CONNECTION_STATE.write().unwrap() = ConnectionState::Connected;
                        match REDIS_POOL.get() {
                            Some(pool) => pool,
                            None => return "Error: Redis pool not initialized".to_string(),
                        }
                    }
                    Err(err) => {
                        *CONNECTION_STATE.write().unwrap() = ConnectionState::Failed;
                        return format!("Error: {}", err);
                    }
                }
            }
        };

        // Use the global tokio runtime to execute async operations
        let rt = &RUNTIME;
        rt.block_on(async move {
            // Acquire a connection from the pool
            let mut $conn = match pool.get().await {
                Ok(conn) => conn,
                Err(e) => return format!("Error: {}", e),
            };

            // Execute the user-provided Redis operation
            $operation
        })
    }};
}
