use deadpool_redis::cluster::Pool as RedisPool;
pub async fn acquire_repo_lock(
    pool: &RedisPool,
    repo_id: uuid::Uuid,
    lock_value: &str,
    ttl_secs: usize,
) -> redis::RedisResult<bool> {
    let lock_key = format!("git:repo:lock:{}", repo_id);
    let redis = pool.get().await.map_err(|e| {
        redis::RedisError::from((
            redis::ErrorKind::Io,
            "failed to get Redis connection",
            e.to_string(),
        ))
    })?;
    let mut conn: deadpool_redis::cluster::Connection = redis;
    let acquired: Option<String> = redis::cmd("SET")
        .arg(&lock_key)
        .arg(lock_value)
        .arg("NX")
        .arg("EX")
        .arg(ttl_secs)
        .query_async(&mut conn)
        .await?;
    Ok(acquired.is_some())
}
pub async fn release_repo_lock(
    pool: &RedisPool,
    repo_id: uuid::Uuid,
    lock_value: &str,
) {
    let lock_key = format!("git:repo:lock:{}", repo_id);
    let redis = match pool.get().await {
        Ok(c) => c,
        Err(e) => {
            tracing::warn!(error = %e, repo_id = %repo_id, "lock_release_redis_connection_failed");
            return;
        }
    };
    let mut conn: deadpool_redis::cluster::Connection = redis;
    let script = redis::Script::new(
        r#"
        if redis.call("GET", KEYS[1]) == ARGV[1] then
            redis.call("DEL", KEYS[1])
            return 1
        end
        return 0
        "#,
    );
    if let Err(e) = script
        .key(&lock_key)
        .arg(lock_value)
        .invoke_async::<i32>(&mut conn)
        .await
    {
        tracing::warn!(error = %e, repo_id = %repo_id, "lock_release_failed");
    }
}
