// src/queue.rs
use crate::job::Job;
use crate::error::QrushResult;
use crate::utils::rdconfig::get_redis_connection;
use crate::utils::constants::{
    PREFIX_JOB,
    DELAYED_JOBS_KEY,
    PREFIX_QUEUE,
};


use serde::Serialize;
use serde_json::to_string;
use redis::AsyncCommands;
use chrono::Utc;
use nanoid::nanoid;

pub async fn enqueue<J>(job: J) -> QrushResult<String>
where
    J: Job + Serialize,
{
    let mut conn = get_redis_connection().await?;
    let payload = to_string(&job)?;
    let job_id = nanoid!(10);
    let now = Utc::now().to_rfc3339();

    let queue = job.queue();
    let queue_key = format!("{PREFIX_QUEUE}:{}", queue);
    let job_key = format!("{PREFIX_JOB}:{job_id}");

    conn.hset_multiple::<_, _, _, ()>(&job_key, &[
        ("queue", queue),
        ("job_name", job.name()),
        ("status", "pending"),
        ("payload", &payload),
        ("created_at", &now),
    ]).await?;

    conn.rpush::<_, _, ()>(&queue_key, &job_id).await?;
    conn.sadd::<_, _, ()>("snm:queues", queue).await?;

    tracing::info!(job_id = %job_id, queue = %queue, "enqueued job");
    Ok(job_id)
}




pub async fn enqueue_in<J>(job: J, delay_secs: u64) -> QrushResult<String>
where
    J: Job + Serialize,
{
    let mut conn = get_redis_connection().await?;
    let payload = to_string(&job)?;
    let job_id = nanoid!(10);
    let now = Utc::now().to_rfc3339();
    let run_at = Utc::now().timestamp() + delay_secs as i64;

    let queue = job.queue();
    let job_key = format!("{PREFIX_JOB}:{job_id}");

    conn.hset_multiple::<_, _, _, ()>(&job_key, &[
        ("queue", queue),
        ("job_name", job.name()),
        ("status", "delayed"),
        ("payload", &payload),
        ("created_at", &now),
        ("run_at", &run_at.to_string()),
    ]).await?;

    conn.zadd::<_, _, _, ()>(DELAYED_JOBS_KEY, &job_id, run_at).await?;
    conn.sadd::<_, _, ()>("snm:queues", queue).await?;

    tracing::info!(job_id = %job_id, run_at, "scheduled delayed job");
    Ok(job_id)
}
