// The contents of this file are generated; do not modify them.

//! Allow your regular customers to save their information with the Customers model.
//!
//! This will prevent re-entering payment instrument information for recurring payments on your platform.
//!
//! Depending on the needs you can allow, creating, listing or deactivating payment instruments & creating, retrieving and updating customers.
use super::common::*;
/// Saved customer details.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Customer {
    /// Unique ID of the customer.
    ///
    /// Example: `831ff8d4cd5958ab5670`
    pub customer_id: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub personal_details: Option<PersonalDetails>,
}
/// Payment Instrument Response
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct PaymentInstrumentResponse {
    /// Unique token identifying the saved payment card for a customer.
    ///
    /// Constraints:
    /// - read-only
    #[serde(skip_serializing_if = "Option::is_none")]
    pub token: Option<String>,
    /// Indicates whether the payment instrument is active and can be used for payments. To deactivate it, send a `DELETE` request to the resource endpoint.
    ///
    /// Constraints:
    /// - read-only
    #[serde(skip_serializing_if = "Option::is_none")]
    pub active: Option<bool>,
    /// Type of the payment instrument.
    #[serde(rename = "type")]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub r#type: Option<PaymentInstrumentResponseType>,
    /// Details of the payment card.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub card: Option<PaymentInstrumentResponseCard>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mandate: Option<MandateResponse>,
    /// Creation date of payment instrument. Response format expressed according to [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) code.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub created_at: Option<crate::datetime::DateTime>,
}
/// Type of the payment instrument.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum PaymentInstrumentResponseType {
    #[serde(rename = "card")]
    Card,
    #[serde(untagged)]
    Other(String),
}
/// Details of the payment card.
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct PaymentInstrumentResponseCard {
    /// Last 4 digits of the payment card number.
    ///
    /// Constraints:
    /// - read-only
    /// - min length: 4
    /// - max length: 4
    ///
    /// Example: `3456`
    #[serde(skip_serializing_if = "Option::is_none")]
    pub last_4_digits: Option<String>,
    #[serde(rename = "type")]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub r#type: Option<CardType>,
}
/// Customer fields to update.
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct UpdateBody {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub personal_details: Option<PersonalDetails>,
}
/// Returns the list of saved payment instruments for the customer.
pub type ListPaymentInstrumentsResponse = Vec<PaymentInstrumentResponse>;
use crate::client::Client;
#[derive(Debug)]
pub enum CreateErrorBody {
    BadRequest(crate::error::UnknownApiBody),
    Unauthorized(Problem),
    Forbidden(ErrorForbidden),
    Conflict(Error),
}
#[derive(Debug)]
pub enum GetErrorBody {
    Unauthorized(Problem),
    Forbidden(ErrorForbidden),
    NotFound(Error),
}
#[derive(Debug)]
pub enum UpdateErrorBody {
    Unauthorized(Problem),
    Forbidden(ErrorForbidden),
    NotFound(Error),
}
#[derive(Debug)]
pub enum ListPaymentInstrumentsErrorBody {
    Unauthorized(Problem),
    Forbidden(ErrorForbidden),
    NotFound(Error),
}
#[derive(Debug)]
pub enum DeactivatePaymentInstrumentErrorBody {
    BadRequest(Error),
    Unauthorized(Problem),
    Forbidden(ErrorForbidden),
    NotFound(Error),
}
/// Client for the Customers API endpoints.
#[derive(Debug)]
pub struct CustomersClient<'a> {
    client: &'a Client,
}
impl<'a> CustomersClient<'a> {
    pub(crate) fn new(client: &'a Client) -> Self {
        Self { client }
    }
    /// Returns a reference to the underlying client.
    pub fn client(&self) -> &Client {
        self.client
    }
    /// Create a customer
    ///
    /// Creates a new saved customer resource which you can later manipulate and save payment instruments to.
    ///
    /// Responses:
    /// - 201: Returns the customer resource.
    /// - 400: The request body is invalid.
    /// - 401: The request is not authorized.
    /// - 403: The request is authenticated but not permitted for this operation.
    /// - 409: A customer with the provided identifier already exists.
    pub async fn create(
        &self,
        body: Customer,
    ) -> crate::error::SdkResult<Customer, CreateErrorBody> {
        let path = "/v0.1/customers";
        let url = format!("{}{}", self.client.base_url(), path);
        let mut request = self
            .client
            .http_client()
            .post(&url)
            .header("User-Agent", crate::version::user_agent())
            .timeout(self.client.timeout())
            .json(&body);
        if let Some(authorization) = self.client.authorization() {
            request = request.header("Authorization", format!("Bearer {}", authorization));
        }
        for (header_name, header_value) in self.client.runtime_headers() {
            request = request.header(*header_name, header_value);
        }
        let response = request.send().await?;
        let status = response.status();
        match status {
            reqwest::StatusCode::CREATED => {
                let data: Customer = response.json().await?;
                Ok(data)
            }
            reqwest::StatusCode::BAD_REQUEST => {
                let body_bytes = response.bytes().await?;
                let body = crate::error::UnknownApiBody::from_bytes(body_bytes.as_ref());
                Err(crate::error::SdkError::api(CreateErrorBody::BadRequest(
                    body,
                )))
            }
            reqwest::StatusCode::UNAUTHORIZED => {
                let body: Problem = response.json().await?;
                Err(crate::error::SdkError::api(CreateErrorBody::Unauthorized(
                    body,
                )))
            }
            reqwest::StatusCode::FORBIDDEN => {
                let body: ErrorForbidden = response.json().await?;
                Err(crate::error::SdkError::api(CreateErrorBody::Forbidden(
                    body,
                )))
            }
            reqwest::StatusCode::CONFLICT => {
                let body: Error = response.json().await?;
                Err(crate::error::SdkError::api(CreateErrorBody::Conflict(body)))
            }
            _ => {
                let body_bytes = response.bytes().await?;
                let body = crate::error::UnknownApiBody::from_bytes(body_bytes.as_ref());
                Err(crate::error::SdkError::unexpected(status, body))
            }
        }
    }
    /// Retrieve a customer
    ///
    /// Retrieves an identified saved customer resource through the unique `customer_id` parameter, generated upon customer creation.
    ///
    /// Responses:
    /// - 200: Returns the customer resource.
    /// - 401: The request is not authorized.
    /// - 403: The request is authenticated but not permitted for this operation.
    /// - 404: The requested resource does not exist.
    pub async fn get(
        &self,
        customer_id: impl Into<String>,
    ) -> crate::error::SdkResult<Customer, GetErrorBody> {
        let path = format!("/v0.1/customers/{}", customer_id.into());
        let url = format!("{}{}", self.client.base_url(), path);
        let mut request = self
            .client
            .http_client()
            .get(&url)
            .header("User-Agent", crate::version::user_agent())
            .timeout(self.client.timeout());
        if let Some(authorization) = self.client.authorization() {
            request = request.header("Authorization", format!("Bearer {}", authorization));
        }
        for (header_name, header_value) in self.client.runtime_headers() {
            request = request.header(*header_name, header_value);
        }
        let response = request.send().await?;
        let status = response.status();
        match status {
            reqwest::StatusCode::OK => {
                let data: Customer = response.json().await?;
                Ok(data)
            }
            reqwest::StatusCode::UNAUTHORIZED => {
                let body: Problem = response.json().await?;
                Err(crate::error::SdkError::api(GetErrorBody::Unauthorized(
                    body,
                )))
            }
            reqwest::StatusCode::FORBIDDEN => {
                let body: ErrorForbidden = response.json().await?;
                Err(crate::error::SdkError::api(GetErrorBody::Forbidden(body)))
            }
            reqwest::StatusCode::NOT_FOUND => {
                let body: Error = response.json().await?;
                Err(crate::error::SdkError::api(GetErrorBody::NotFound(body)))
            }
            _ => {
                let body_bytes = response.bytes().await?;
                let body = crate::error::UnknownApiBody::from_bytes(body_bytes.as_ref());
                Err(crate::error::SdkError::unexpected(status, body))
            }
        }
    }
    /// Update a customer
    ///
    /// Updates an identified saved customer resource's personal details.
    ///
    /// The request only overwrites the parameters included in the request, all other parameters will remain with their initially assigned values.
    ///
    /// Responses:
    /// - 200: Returns the customer resource.
    /// - 401: The request is not authorized.
    /// - 403: The request is authenticated but not permitted for this operation.
    /// - 404: The requested resource does not exist.
    pub async fn update(
        &self,
        customer_id: impl Into<String>,
        body: UpdateBody,
    ) -> crate::error::SdkResult<Customer, UpdateErrorBody> {
        let path = format!("/v0.1/customers/{}", customer_id.into());
        let url = format!("{}{}", self.client.base_url(), path);
        let mut request = self
            .client
            .http_client()
            .put(&url)
            .header("User-Agent", crate::version::user_agent())
            .timeout(self.client.timeout())
            .json(&body);
        if let Some(authorization) = self.client.authorization() {
            request = request.header("Authorization", format!("Bearer {}", authorization));
        }
        for (header_name, header_value) in self.client.runtime_headers() {
            request = request.header(*header_name, header_value);
        }
        let response = request.send().await?;
        let status = response.status();
        match status {
            reqwest::StatusCode::OK => {
                let data: Customer = response.json().await?;
                Ok(data)
            }
            reqwest::StatusCode::UNAUTHORIZED => {
                let body: Problem = response.json().await?;
                Err(crate::error::SdkError::api(UpdateErrorBody::Unauthorized(
                    body,
                )))
            }
            reqwest::StatusCode::FORBIDDEN => {
                let body: ErrorForbidden = response.json().await?;
                Err(crate::error::SdkError::api(UpdateErrorBody::Forbidden(
                    body,
                )))
            }
            reqwest::StatusCode::NOT_FOUND => {
                let body: Error = response.json().await?;
                Err(crate::error::SdkError::api(UpdateErrorBody::NotFound(body)))
            }
            _ => {
                let body_bytes = response.bytes().await?;
                let body = crate::error::UnknownApiBody::from_bytes(body_bytes.as_ref());
                Err(crate::error::SdkError::unexpected(status, body))
            }
        }
    }
    /// List payment instruments
    ///
    /// Lists all payment instrument resources that are saved for an identified customer.
    ///
    /// Responses:
    /// - 200: Returns the list of saved payment instruments for the customer.
    /// - 401: The request is not authorized.
    /// - 403: The request is authenticated but not permitted for this operation.
    /// - 404: The requested resource does not exist.
    pub async fn list_payment_instruments(
        &self,
        customer_id: impl Into<String>,
    ) -> crate::error::SdkResult<ListPaymentInstrumentsResponse, ListPaymentInstrumentsErrorBody>
    {
        let path = format!("/v0.1/customers/{}/payment-instruments", customer_id.into());
        let url = format!("{}{}", self.client.base_url(), path);
        let mut request = self
            .client
            .http_client()
            .get(&url)
            .header("User-Agent", crate::version::user_agent())
            .timeout(self.client.timeout());
        if let Some(authorization) = self.client.authorization() {
            request = request.header("Authorization", format!("Bearer {}", authorization));
        }
        for (header_name, header_value) in self.client.runtime_headers() {
            request = request.header(*header_name, header_value);
        }
        let response = request.send().await?;
        let status = response.status();
        match status {
            reqwest::StatusCode::OK => {
                let data: ListPaymentInstrumentsResponse = response.json().await?;
                Ok(data)
            }
            reqwest::StatusCode::UNAUTHORIZED => {
                let body: Problem = response.json().await?;
                Err(crate::error::SdkError::api(
                    ListPaymentInstrumentsErrorBody::Unauthorized(body),
                ))
            }
            reqwest::StatusCode::FORBIDDEN => {
                let body: ErrorForbidden = response.json().await?;
                Err(crate::error::SdkError::api(
                    ListPaymentInstrumentsErrorBody::Forbidden(body),
                ))
            }
            reqwest::StatusCode::NOT_FOUND => {
                let body: Error = response.json().await?;
                Err(crate::error::SdkError::api(
                    ListPaymentInstrumentsErrorBody::NotFound(body),
                ))
            }
            _ => {
                let body_bytes = response.bytes().await?;
                let body = crate::error::UnknownApiBody::from_bytes(body_bytes.as_ref());
                Err(crate::error::SdkError::unexpected(status, body))
            }
        }
    }
    /// Deactivate a payment instrument
    ///
    /// Deactivates an identified card payment instrument resource for a customer.
    ///
    /// Responses:
    /// - 204: Returns an empty response body when the operation succeeds.
    /// - 400: The request is invalid.
    /// - 401: The request is not authorized.
    /// - 403: The request is authenticated but not permitted for this operation.
    /// - 404: The requested resource does not exist.
    pub async fn deactivate_payment_instrument(
        &self,
        customer_id: impl Into<String>,
        token: impl Into<String>,
    ) -> crate::error::SdkResult<(), DeactivatePaymentInstrumentErrorBody> {
        let path = format!(
            "/v0.1/customers/{}/payment-instruments/{}",
            customer_id.into(),
            token.into()
        );
        let url = format!("{}{}", self.client.base_url(), path);
        let mut request = self
            .client
            .http_client()
            .delete(&url)
            .header("User-Agent", crate::version::user_agent())
            .timeout(self.client.timeout());
        if let Some(authorization) = self.client.authorization() {
            request = request.header("Authorization", format!("Bearer {}", authorization));
        }
        for (header_name, header_value) in self.client.runtime_headers() {
            request = request.header(*header_name, header_value);
        }
        let response = request.send().await?;
        let status = response.status();
        match status {
            reqwest::StatusCode::NO_CONTENT => Ok(()),
            reqwest::StatusCode::BAD_REQUEST => {
                let body: Error = response.json().await?;
                Err(crate::error::SdkError::api(
                    DeactivatePaymentInstrumentErrorBody::BadRequest(body),
                ))
            }
            reqwest::StatusCode::UNAUTHORIZED => {
                let body: Problem = response.json().await?;
                Err(crate::error::SdkError::api(
                    DeactivatePaymentInstrumentErrorBody::Unauthorized(body),
                ))
            }
            reqwest::StatusCode::FORBIDDEN => {
                let body: ErrorForbidden = response.json().await?;
                Err(crate::error::SdkError::api(
                    DeactivatePaymentInstrumentErrorBody::Forbidden(body),
                ))
            }
            reqwest::StatusCode::NOT_FOUND => {
                let body: Error = response.json().await?;
                Err(crate::error::SdkError::api(
                    DeactivatePaymentInstrumentErrorBody::NotFound(body),
                ))
            }
            _ => {
                let body_bytes = response.bytes().await?;
                let body = crate::error::UnknownApiBody::from_bytes(body_bytes.as_ref());
                Err(crate::error::SdkError::unexpected(status, body))
            }
        }
    }
}
