// 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 Revisions API.
#[derive(Debug, Clone)]
pub struct RevisionsClient<'a> {
    pub(crate) client: &'a TofuPilot,
}

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

    /// Get part revision
    ///
    /// Retrieve a single part revision by its part number and revision number, including revision metadata, configuration details, and linked units.
    pub fn get(&self) -> GetBuilder<'a> {
        GetBuilder::new(self.client)
    }

    /// Delete part revision
    ///
    /// Permanently delete a part revision by its part number and revision number. This action removes the revision and all associated data and cannot be undone.
    pub fn delete(&self) -> DeleteBuilder<'a> {
        DeleteBuilder::new(self.client)
    }

    /// Update part revision
    ///
    /// Update a part revision's number or image. Identifies the revision by part number and revision number in the URL.
    pub fn update(&self) -> UpdateBuilder<'a> {
        UpdateBuilder::new(self.client)
    }

    /// Create part revision
    ///
    /// Create a new part revision for an existing part. Revision numbers are matched case-insensitively (e.g., "REV-A" and "rev-a" are considered the same).
    pub fn create(&self) -> CreateBuilder<'a> {
        CreateBuilder::new(self.client)
    }

}

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

/// Builder for [`RevisionsClient::get`].
///
/// # Example
///
/// ```no_run
/// use tofupilot::TofuPilot;
///
/// # #[tokio::main]
/// # async fn main() -> tofupilot::Result<()> {
/// let client = TofuPilot::new("your-api-key");
/// let response = client.revisions().get()
///     .part_number("value")
///     .revision_number("value")
///     .send()
///     .await?;
/// # Ok(())
/// # }
/// ```
#[derive(Debug)]
pub struct GetBuilder<'a> {
    client: &'a TofuPilot,
    part_number: Option<String>,
    revision_number: 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,
            part_number: None,
            revision_number: None,
            server_url: None,
            timeout: None,
        }
    }

    /// Set the `part_number` path parameter.
    ///
    /// Part number that the revision belongs to.
    pub fn part_number(mut self, value: impl Into<String>) -> Self {
        self.part_number = Some(value.into());
        self
    }

    /// Set the `revision_number` path parameter.
    ///
    /// Revision number to retrieve.
    pub fn revision_number(mut self, value: impl Into<String>) -> Self {
        self.revision_number = 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<PartGetRevisionResponse> {
        let part_number = self.part_number
            .ok_or_else(|| Error::Validation(
                "missing required path parameter: part_number".to_string(),
            ))?;
        let revision_number = self.revision_number
            .ok_or_else(|| Error::Validation(
                "missing required path parameter: revision_number".to_string(),
            ))?;
        let part_number_encoded = utf8_percent_encode(&part_number, URI_COMPONENT).to_string();
        let revision_number_encoded = utf8_percent_encode(&revision_number, URI_COMPONENT).to_string();

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

        let url = format!(
            "{}/v2/parts/{part_number}/revisions/{revision_number}",
            base_url,
            part_number = part_number_encoded,
            revision_number = revision_number_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,
            "part-getRevision",
            base_url,
        ).await?;
        let result: PartGetRevisionResponse = response.json().await?;
        Ok(result)
    }
}

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

/// Builder for [`RevisionsClient::delete`].
///
/// # Example
///
/// ```no_run
/// use tofupilot::TofuPilot;
///
/// # #[tokio::main]
/// # async fn main() -> tofupilot::Result<()> {
/// let client = TofuPilot::new("your-api-key");
/// let response = client.revisions().delete()
///     .part_number("value")
///     .revision_number("value")
///     .send()
///     .await?;
/// # Ok(())
/// # }
/// ```
#[derive(Debug)]
pub struct DeleteBuilder<'a> {
    client: &'a TofuPilot,
    part_number: Option<String>,
    revision_number: 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,
            part_number: None,
            revision_number: None,
            server_url: None,
            timeout: None,
        }
    }

    /// Set the `part_number` path parameter.
    ///
    /// Part number that the revision belongs to.
    pub fn part_number(mut self, value: impl Into<String>) -> Self {
        self.part_number = Some(value.into());
        self
    }

    /// Set the `revision_number` path parameter.
    ///
    /// Revision number to delete.
    pub fn revision_number(mut self, value: impl Into<String>) -> Self {
        self.revision_number = 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<PartDeleteRevisionResponse> {
        let part_number = self.part_number
            .ok_or_else(|| Error::Validation(
                "missing required path parameter: part_number".to_string(),
            ))?;
        let revision_number = self.revision_number
            .ok_or_else(|| Error::Validation(
                "missing required path parameter: revision_number".to_string(),
            ))?;
        let part_number_encoded = utf8_percent_encode(&part_number, URI_COMPONENT).to_string();
        let revision_number_encoded = utf8_percent_encode(&revision_number, URI_COMPONENT).to_string();

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

        let url = format!(
            "{}/v2/parts/{part_number}/revisions/{revision_number}",
            base_url,
            part_number = part_number_encoded,
            revision_number = revision_number_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,
            "part-deleteRevision",
            base_url,
        ).await?;
        let result: PartDeleteRevisionResponse = response.json().await?;
        Ok(result)
    }
}

// ---------------------------------------------------------------------------
// UpdateBuilder
// ---------------------------------------------------------------------------

/// Builder for [`RevisionsClient::update`].
///
/// # Example
///
/// ```no_run
/// use tofupilot::TofuPilot;
///
/// # #[tokio::main]
/// # async fn main() -> tofupilot::Result<()> {
/// let client = TofuPilot::new("your-api-key");
/// let response = client.revisions().update()
///     .send()
///     .await?;
/// # Ok(())
/// # }
/// ```
#[derive(Debug)]
pub struct UpdateBuilder<'a> {
    client: &'a TofuPilot,
    part_number: Option<String>,
    revision_number: Option<String>,
    number: Option<String>,
    image_id: Option<String>,
    server_url: Option<String>,
    timeout: Option<std::time::Duration>,
}

impl<'a> UpdateBuilder<'a> {
    pub(crate) fn new(client: &'a TofuPilot) -> Self {
        Self {
            client,
            part_number: None,
            revision_number: None,
            number: None,
            image_id: None,
            server_url: None,
            timeout: None,
        }
    }

    /// Set the `part_number` path parameter.
    ///
    /// Part number that the revision belongs to.
    pub fn part_number(mut self, value: impl Into<String>) -> Self {
        self.part_number = Some(value.into());
        self
    }

    /// Set the `revision_number` path parameter.
    ///
    /// Current revision number to update.
    pub fn revision_number(mut self, value: impl Into<String>) -> Self {
        self.revision_number = Some(value.into());
        self
    }

    /// Set the `number` field.
    ///
    /// New revision number to set.
    pub fn number(mut self, value: impl Into<String>) -> Self {
        self.number = Some(value.into());
        self
    }

    /// Set the `image_id` field.
    ///
    /// Upload ID for the revision image, or empty string to remove image
    pub fn image_id(mut self, value: impl Into<String>) -> Self {
        self.image_id = Some(value.into());
        self
    }

    /// Set the full request body (alternative to setting individual fields).
    pub fn body(mut self, body: PartUpdateRevisionRequestBody) -> Self {
        if body.number.is_some() {
            self.number = body.number;
        }
        if body.image_id.is_some() {
            self.image_id = body.image_id;
        }
        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<PartUpdateRevisionResponse> {
        let part_number = self.part_number
            .ok_or_else(|| Error::Validation(
                "missing required path parameter: part_number".to_string(),
            ))?;
        let revision_number = self.revision_number
            .ok_or_else(|| Error::Validation(
                "missing required path parameter: revision_number".to_string(),
            ))?;
        let part_number_encoded = utf8_percent_encode(&part_number, URI_COMPONENT).to_string();
        let revision_number_encoded = utf8_percent_encode(&revision_number, URI_COMPONENT).to_string();

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

        let url = format!(
            "{}/v2/parts/{part_number}/revisions/{revision_number}",
            base_url,
            part_number = part_number_encoded,
            revision_number = revision_number_encoded,
        );

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

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


        let body = PartUpdateRevisionRequestBody {
            number: self.number,
            image_id: self.image_id,
        };
        request = request.json(&body);

        let response = self.client.execute(
            request,
            "part-updateRevision",
            base_url,
        ).await?;
        let result: PartUpdateRevisionResponse = response.json().await?;
        Ok(result)
    }
}

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

/// Builder for [`RevisionsClient::create`].
///
/// # Example
///
/// ```no_run
/// use tofupilot::TofuPilot;
///
/// # #[tokio::main]
/// # async fn main() -> tofupilot::Result<()> {
/// let client = TofuPilot::new("your-api-key");
/// let response = client.revisions().create()
///     .number("value")
///     .send()
///     .await?;
/// # Ok(())
/// # }
/// ```
#[derive(Debug)]
pub struct CreateBuilder<'a> {
    client: &'a TofuPilot,
    part_number: Option<String>,
    number: 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,
            part_number: None,
            number: None,
            server_url: None,
            timeout: None,
        }
    }

    /// Set the `part_number` path parameter.
    ///
    /// Part number to create a revision for.
    pub fn part_number(mut self, value: impl Into<String>) -> Self {
        self.part_number = Some(value.into());
        self
    }

    /// Set the `number` field.
    ///
    /// Revision number (e.g., version number or code).
    pub fn number(mut self, value: impl Into<String>) -> Self {
        self.number = Some(value.into());
        self
    }

    /// Set the full request body (alternative to setting individual fields).
    pub fn body(mut self, body: PartCreateRevisionRequestBody) -> Self {
        self.number = Some(body.number);
        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<PartCreateRevisionResponse> {
        let part_number = self.part_number
            .ok_or_else(|| Error::Validation(
                "missing required path parameter: part_number".to_string(),
            ))?;
        let part_number_encoded = utf8_percent_encode(&part_number, URI_COMPONENT).to_string();

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

        let url = format!(
            "{}/v2/parts/{part_number}/revisions",
            base_url,
            part_number = part_number_encoded,
        );

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

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


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

        let response = self.client.execute(
            request,
            "part-createRevision",
            base_url,
        ).await?;
        let result: PartCreateRevisionResponse = response.json().await?;
        Ok(result)
    }
}

