// Code generated by ndpgen. DO NOT EDIT.
//
// This file contains client wrappers for the Task host service.
// It is intended for use in Navidrome plugins built with extism-pdk.

use extism_pdk::*;
use serde::{Deserialize, Serialize};
use base64::Engine as _;
use base64::engine::general_purpose::STANDARD as BASE64;

mod base64_bytes {
    use serde::{self, Deserialize, Deserializer, Serializer};
    use base64::Engine as _;
    use base64::engine::general_purpose::STANDARD as BASE64;

    pub fn serialize<S>(bytes: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&BASE64.encode(bytes))
    }

    pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        BASE64.decode(&s).map_err(serde::de::Error::custom)
    }
}

/// QueueConfig holds configuration for a task queue.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct QueueConfig {
    pub concurrency: i32,
    pub max_retries: i32,
    pub backoff_ms: i64,
    pub delay_ms: i64,
    pub retention_ms: i64,
}

/// TaskInfo holds the current state of a task.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TaskInfo {
    pub status: String,
    pub message: String,
    pub attempt: i32,
}

#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct TaskCreateQueueRequest {
    name: String,
    config: QueueConfig,
}

#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct TaskCreateQueueResponse {
    #[serde(default)]
    error: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct TaskEnqueueRequest {
    queue_name: String,
    #[serde(with = "base64_bytes")]
    payload: Vec<u8>,
}

#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct TaskEnqueueResponse {
    #[serde(default)]
    result: String,
    #[serde(default)]
    error: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct TaskGetRequest {
    task_id: String,
}

#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct TaskGetResponse {
    #[serde(default)]
    result: Option<TaskInfo>,
    #[serde(default)]
    error: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct TaskCancelRequest {
    task_id: String,
}

#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct TaskCancelResponse {
    #[serde(default)]
    error: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct TaskClearQueueRequest {
    queue_name: String,
}

#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct TaskClearQueueResponse {
    #[serde(default)]
    result: i64,
    #[serde(default)]
    error: Option<String>,
}

#[host_fn]
extern "ExtismHost" {
    fn task_createqueue(input: Json<TaskCreateQueueRequest>) -> Json<TaskCreateQueueResponse>;
    fn task_enqueue(input: Json<TaskEnqueueRequest>) -> Json<TaskEnqueueResponse>;
    fn task_get(input: Json<TaskGetRequest>) -> Json<TaskGetResponse>;
    fn task_cancel(input: Json<TaskCancelRequest>) -> Json<TaskCancelResponse>;
    fn task_clearqueue(input: Json<TaskClearQueueRequest>) -> Json<TaskClearQueueResponse>;
}

/// CreateQueue creates a named task queue with the given configuration.
/// Zero-value fields in config use sensible defaults.
/// If a queue with the same name already exists, returns an error.
/// On startup, this also recovers any stale "running" tasks from a previous crash.
///
/// # Arguments
/// * `name` - String parameter.
/// * `config` - QueueConfig parameter.
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn create_queue(name: &str, config: QueueConfig) -> Result<(), Error> {
    let response = unsafe {
        task_createqueue(Json(TaskCreateQueueRequest {
            name: name.to_owned(),
            config: config,
        }))?
    };

    if let Some(err) = response.0.error {
        return Err(Error::msg(err));
    }

    Ok(())
}

/// Enqueue adds a task to the named queue. Returns the task ID.
/// payload is opaque bytes passed back to the plugin on execution.
///
/// # Arguments
/// * `queue_name` - String parameter.
/// * `payload` - Vec<u8> parameter.
///
/// # Returns
/// The result value.
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn enqueue(queue_name: &str, payload: Vec<u8>) -> Result<String, Error> {
    let response = unsafe {
        task_enqueue(Json(TaskEnqueueRequest {
            queue_name: queue_name.to_owned(),
            payload: payload,
        }))?
    };

    if let Some(err) = response.0.error {
        return Err(Error::msg(err));
    }

    Ok(response.0.result)
}

/// Get returns the current state of a task including its status,
/// message, and attempt count.
///
/// # Arguments
/// * `task_id` - String parameter.
///
/// # Returns
/// The result value.
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn get(task_id: &str) -> Result<Option<TaskInfo>, Error> {
    let response = unsafe {
        task_get(Json(TaskGetRequest {
            task_id: task_id.to_owned(),
        }))?
    };

    if let Some(err) = response.0.error {
        return Err(Error::msg(err));
    }

    Ok(response.0.result)
}

/// Cancel cancels a pending task. Returns error if already
/// running, completed, or failed.
///
/// # Arguments
/// * `task_id` - String parameter.
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn cancel(task_id: &str) -> Result<(), Error> {
    let response = unsafe {
        task_cancel(Json(TaskCancelRequest {
            task_id: task_id.to_owned(),
        }))?
    };

    if let Some(err) = response.0.error {
        return Err(Error::msg(err));
    }

    Ok(())
}

/// ClearQueue removes all pending tasks from the named queue.
/// Running tasks are not affected. Returns the number of tasks removed.
///
/// # Arguments
/// * `queue_name` - String parameter.
///
/// # Returns
/// The result value.
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn clear_queue(queue_name: &str) -> Result<i64, Error> {
    let response = unsafe {
        task_clearqueue(Json(TaskClearQueueRequest {
            queue_name: queue_name.to_owned(),
        }))?
    };

    if let Some(err) = response.0.error {
        return Err(Error::msg(err));
    }

    Ok(response.0.result)
}
