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

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

    /// Initialize upload
    ///
    /// Get a temporary pre-signed URL to upload a file. Returns the upload ID and URL. Upload the file to the URL with a PUT request, then call Finalize upload.
    pub fn initialize(&self) -> InitializeBuilder<'a> {
        InitializeBuilder::new(self.client)
    }

    /// Finalize upload
    ///
    /// Finalize a file upload after uploading to the pre-signed URL. Validates the file and records its metadata.
    pub fn finalize(&self) -> FinalizeBuilder<'a> {
        FinalizeBuilder::new(self.client)
    }

}

// ---------------------------------------------------------------------------
// InitializeBuilder
// ---------------------------------------------------------------------------

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

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

    /// Set the `name` field.
    ///
    /// File name including extension (e.g. "report.pdf")
    pub fn name(mut self, value: impl Into<String>) -> Self {
        self.name = Some(value.into());
        self
    }

    /// Set the full request body (alternative to setting individual fields).
    pub fn body(mut self, body: AttachmentInitializeRequest) -> Self {
        self.name = Some(body.name);
        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<AttachmentInitializeResponse> {

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

        let url = format!("{}{}", base_url, "/v2/attachments");

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

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


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

        let response = self.client.execute(
            request,
            "attachment-initialize",
            base_url,
        ).await?;
        let result: AttachmentInitializeResponse = response.json().await?;
        Ok(result)
    }
}

// ---------------------------------------------------------------------------
// FinalizeBuilder
// ---------------------------------------------------------------------------

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

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

    /// Set the `id` path parameter.
    ///
    /// ID of the upload to finalize
    pub fn id(mut self, value: impl Into<String>) -> Self {
        self.id = 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<AttachmentFinalizeResponse> {
        let id = self.id
            .ok_or_else(|| Error::Validation(
                "missing required path parameter: id".to_string(),
            ))?;
        let id_encoded = utf8_percent_encode(&id, URI_COMPONENT).to_string();

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

        let url = format!(
            "{}/v2/attachments/{id}/finalize",
            base_url,
            id = id_encoded,
        );

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

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



        let response = self.client.execute(
            request,
            "attachment-finalize",
            base_url,
        ).await?;
        let result: AttachmentFinalizeResponse = response.json().await?;
        Ok(result)
    }
}

