// Code generated by TofuPilot SDK Generator. DO NOT EDIT.

use crate::client::TofuPilot;
use crate::error::{Error, Result};
use percent_encoding::{utf8_percent_encode, AsciiSet, NON_ALPHANUMERIC};

/// Percent-encode set matching RFC 3986 unreserved characters.
const URI_COMPONENT: &AsciiSet = &NON_ALPHANUMERIC
    .remove(b'-')
    .remove(b'.')
    .remove(b'_')
    .remove(b'~');
use crate::types::*;

/// Client for the Versions API.
#[derive(Debug, Clone)]
pub struct VersionsClient<'a> {
    pub(crate) client: &'a TofuPilot,
}

impl<'a> VersionsClient<'a> {
    pub(crate) fn new(client: &'a TofuPilot) -> Self {
        Self { client }
    }

    /// Get procedure version
    ///
    /// Retrieve a single procedure version by its tag, including version metadata and configuration details.
    pub fn get(&self) -> GetBuilder<'a> {
        GetBuilder::new(self.client)
    }

    /// Delete procedure version
    ///
    /// Permanently delete a procedure version by its tag. This removes the version record and all associated configuration data and cannot be undone.
    pub fn delete(&self) -> DeleteBuilder<'a> {
        DeleteBuilder::new(self.client)
    }

    /// Create procedure version
    ///
    /// Create a new version for an existing test procedure. Versions let you track procedure changes over time and maintain a history of test configurations.
    pub fn create(&self) -> CreateBuilder<'a> {
        CreateBuilder::new(self.client)
    }

}

// ---------------------------------------------------------------------------
// GetBuilder
// ---------------------------------------------------------------------------

/// Builder for [`VersionsClient::get`].
///
/// # Example
///
/// ```no_run
/// use tofupilot::TofuPilot;
///
/// # #[tokio::main]
/// # async fn main() -> tofupilot::Result<()> {
/// let client = TofuPilot::new("your-api-key");
/// let response = client.versions().get()
///     .procedure_id("value")
///     .tag("value")
///     .send()
///     .await?;
/// # Ok(())
/// # }
/// ```
#[derive(Debug)]
pub struct GetBuilder<'a> {
    client: &'a TofuPilot,
    procedure_id: Option<String>,
    tag: Option<String>,
    server_url: Option<String>,
    timeout: Option<std::time::Duration>,
}

impl<'a> GetBuilder<'a> {
    pub(crate) fn new(client: &'a TofuPilot) -> Self {
        Self {
            client,
            procedure_id: None,
            tag: None,
            server_url: None,
            timeout: None,
        }
    }

    /// Set the `procedure_id` path parameter.
    ///
    /// ID of the procedure that owns this version.
    pub fn procedure_id(mut self, value: impl Into<String>) -> Self {
        self.procedure_id = Some(value.into());
        self
    }

    /// Set the `tag` path parameter.
    ///
    /// Version tag to retrieve.
    pub fn tag(mut self, value: impl Into<String>) -> Self {
        self.tag = Some(value.into());
        self
    }

    /// Override the server URL for this request.
    pub fn server_url(mut self, url: impl Into<String>) -> Self {
        self.server_url = Some(url.into());
        self
    }

    /// Override the timeout for this request.
    pub fn timeout(mut self, timeout: std::time::Duration) -> Self {
        self.timeout = Some(timeout);
        self
    }

    /// Send the request.
    pub async fn send(self) -> Result<ProcedureGetVersionResponse> {
        let procedure_id = self.procedure_id
            .ok_or_else(|| Error::Validation(
                "missing required path parameter: procedure_id".to_string(),
            ))?;
        let tag = self.tag
            .ok_or_else(|| Error::Validation(
                "missing required path parameter: tag".to_string(),
            ))?;
        let procedure_id_encoded = utf8_percent_encode(&procedure_id, URI_COMPONENT).to_string();
        let tag_encoded = utf8_percent_encode(&tag, URI_COMPONENT).to_string();

        let base_url = self.server_url
            .as_deref()
            .unwrap_or(&self.client.config.base_url);

        let url = format!(
            "{}/v2/procedures/{procedure_id}/versions/{tag}",
            base_url,
            procedure_id = procedure_id_encoded,
            tag = tag_encoded,
        );

        let mut request = self.client.http.request(
            reqwest::Method::GET,
            &url,
        );

        if let Some(timeout) = self.timeout {
            request = request.timeout(timeout);
        }



        let response = self.client.execute(
            request,
            "procedure-getVersion",
            base_url,
        ).await?;
        let result: ProcedureGetVersionResponse = response.json().await?;
        Ok(result)
    }
}

// ---------------------------------------------------------------------------
// DeleteBuilder
// ---------------------------------------------------------------------------

/// Builder for [`VersionsClient::delete`].
///
/// # Example
///
/// ```no_run
/// use tofupilot::TofuPilot;
///
/// # #[tokio::main]
/// # async fn main() -> tofupilot::Result<()> {
/// let client = TofuPilot::new("your-api-key");
/// let response = client.versions().delete()
///     .procedure_id("value")
///     .tag("value")
///     .send()
///     .await?;
/// # Ok(())
/// # }
/// ```
#[derive(Debug)]
pub struct DeleteBuilder<'a> {
    client: &'a TofuPilot,
    procedure_id: Option<String>,
    tag: Option<String>,
    server_url: Option<String>,
    timeout: Option<std::time::Duration>,
}

impl<'a> DeleteBuilder<'a> {
    pub(crate) fn new(client: &'a TofuPilot) -> Self {
        Self {
            client,
            procedure_id: None,
            tag: None,
            server_url: None,
            timeout: None,
        }
    }

    /// Set the `procedure_id` path parameter.
    ///
    /// ID of the procedure that owns this version
    pub fn procedure_id(mut self, value: impl Into<String>) -> Self {
        self.procedure_id = Some(value.into());
        self
    }

    /// Set the `tag` path parameter.
    ///
    /// Version tag to delete
    pub fn tag(mut self, value: impl Into<String>) -> Self {
        self.tag = Some(value.into());
        self
    }

    /// Override the server URL for this request.
    pub fn server_url(mut self, url: impl Into<String>) -> Self {
        self.server_url = Some(url.into());
        self
    }

    /// Override the timeout for this request.
    pub fn timeout(mut self, timeout: std::time::Duration) -> Self {
        self.timeout = Some(timeout);
        self
    }

    /// Send the request.
    pub async fn send(self) -> Result<ProcedureDeleteVersionResponse> {
        let procedure_id = self.procedure_id
            .ok_or_else(|| Error::Validation(
                "missing required path parameter: procedure_id".to_string(),
            ))?;
        let tag = self.tag
            .ok_or_else(|| Error::Validation(
                "missing required path parameter: tag".to_string(),
            ))?;
        let procedure_id_encoded = utf8_percent_encode(&procedure_id, URI_COMPONENT).to_string();
        let tag_encoded = utf8_percent_encode(&tag, URI_COMPONENT).to_string();

        let base_url = self.server_url
            .as_deref()
            .unwrap_or(&self.client.config.base_url);

        let url = format!(
            "{}/v2/procedures/{procedure_id}/versions/{tag}",
            base_url,
            procedure_id = procedure_id_encoded,
            tag = tag_encoded,
        );

        let mut request = self.client.http.request(
            reqwest::Method::DELETE,
            &url,
        );

        if let Some(timeout) = self.timeout {
            request = request.timeout(timeout);
        }



        let response = self.client.execute(
            request,
            "procedure-deleteVersion",
            base_url,
        ).await?;
        let result: ProcedureDeleteVersionResponse = response.json().await?;
        Ok(result)
    }
}

// ---------------------------------------------------------------------------
// CreateBuilder
// ---------------------------------------------------------------------------

/// Builder for [`VersionsClient::create`].
///
/// # Example
///
/// ```no_run
/// use tofupilot::TofuPilot;
///
/// # #[tokio::main]
/// # async fn main() -> tofupilot::Result<()> {
/// let client = TofuPilot::new("your-api-key");
/// let response = client.versions().create()
///     .tag("value")
///     .send()
///     .await?;
/// # Ok(())
/// # }
/// ```
#[derive(Debug)]
pub struct CreateBuilder<'a> {
    client: &'a TofuPilot,
    procedure_id: Option<String>,
    tag: Option<String>,
    server_url: Option<String>,
    timeout: Option<std::time::Duration>,
}

impl<'a> CreateBuilder<'a> {
    pub(crate) fn new(client: &'a TofuPilot) -> Self {
        Self {
            client,
            procedure_id: None,
            tag: None,
            server_url: None,
            timeout: None,
        }
    }

    /// Set the `procedure_id` path parameter.
    ///
    /// The ID of the procedure this version belongs to
    pub fn procedure_id(mut self, value: impl Into<String>) -> Self {
        self.procedure_id = Some(value.into());
        self
    }

    /// Set the `tag` field.
    ///
    /// The version tag
    pub fn tag(mut self, value: impl Into<String>) -> Self {
        self.tag = Some(value.into());
        self
    }

    /// Set the full request body (alternative to setting individual fields).
    pub fn body(mut self, body: ProcedureCreateVersionRequestBody) -> Self {
        self.tag = Some(body.tag);
        self
    }

    /// Override the server URL for this request.
    pub fn server_url(mut self, url: impl Into<String>) -> Self {
        self.server_url = Some(url.into());
        self
    }

    /// Override the timeout for this request.
    pub fn timeout(mut self, timeout: std::time::Duration) -> Self {
        self.timeout = Some(timeout);
        self
    }

    /// Send the request.
    pub async fn send(self) -> Result<ProcedureCreateVersionResponse> {
        let procedure_id = self.procedure_id
            .ok_or_else(|| Error::Validation(
                "missing required path parameter: procedure_id".to_string(),
            ))?;
        let procedure_id_encoded = utf8_percent_encode(&procedure_id, URI_COMPONENT).to_string();

        let base_url = self.server_url
            .as_deref()
            .unwrap_or(&self.client.config.base_url);

        let url = format!(
            "{}/v2/procedures/{procedure_id}/versions",
            base_url,
            procedure_id = procedure_id_encoded,
        );

        let mut request = self.client.http.request(
            reqwest::Method::POST,
            &url,
        );

        if let Some(timeout) = self.timeout {
            request = request.timeout(timeout);
        }


        let body = ProcedureCreateVersionRequestBody {
            tag: self.tag
                .ok_or_else(|| Error::Validation(
                    "missing required field: tag".to_string(),
                ))?,
        };
        request = request.json(&body);

        let response = self.client.execute(
            request,
            "procedure-createVersion",
            base_url,
        ).await?;
        let result: ProcedureCreateVersionResponse = response.json().await?;
        Ok(result)
    }
}

