/*
 * Binance Convert REST API
 *
 * OpenAPI Specification for the Binance Convert REST API
 *
 * The version of the OpenAPI document: 1.0.0
 *
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

#![allow(unused_imports)]
use http::Method;
use serde::de::DeserializeOwned;
use serde_json::Value;
use std::collections::BTreeMap;

use crate::common::{config::ConfigurationRestApi, models::RestApiResponse, utils::send_request};

mod apis;
mod models;

pub use apis::*;
pub use models::*;

#[derive(Debug, Clone)]
pub struct RestApi {
    configuration: ConfigurationRestApi,
    market_data_api_client: MarketDataApiClient,
    trade_api_client: TradeApiClient,
}

impl RestApi {
    pub fn new(configuration: ConfigurationRestApi) -> Self {
        let market_data_api_client = MarketDataApiClient::new(configuration.clone());
        let trade_api_client = TradeApiClient::new(configuration.clone());

        Self {
            configuration,
            market_data_api_client,
            trade_api_client,
        }
    }

    /// Send an unsigned request to the API
    ///
    /// # Arguments
    ///
    /// * `endpoint` - The API endpoint to send the request to
    /// * `method` - The HTTP method to use for the request
    /// * `query_params` - A map of query parameters to send with the request
    /// * `body_params` - A map of body parameters to send with the request
    ///
    /// # Returns
    ///
    /// A `RestApiResponse` containing the deserialized response data on success, or an error if the request fails
    ///
    /// # Errors
    ///
    /// Returns an `anyhow::Error` if the HTTP request fails or if parsing the response fails
    pub async fn send_request<R: DeserializeOwned + Send + 'static>(
        &self,
        endpoint: &str,
        method: Method,
        query_params: BTreeMap<String, Value>,
        body_params: BTreeMap<String, Value>,
    ) -> anyhow::Result<RestApiResponse<R>> {
        send_request::<R>(
            &self.configuration,
            endpoint,
            method,
            query_params,
            body_params,
            None,
            false,
        )
        .await
    }

    /// Send a signed request to the API
    ///
    /// # Arguments
    ///
    /// * `endpoint` - The API endpoint to send the request to
    /// * `method` - The HTTP method to use for the request
    /// * `query_params` - A map of query parameters to send with the request
    /// * `body_params` - A map of body parameters to send with the request
    ///
    /// # Returns
    ///
    /// A `RestApiResponse` containing the deserialized response data on success, or an error if the request fails
    ///
    /// # Errors
    ///
    /// Returns an `anyhow::Error` if the HTTP request fails or if parsing the response fails
    pub async fn send_signed_request<R: DeserializeOwned + Send + 'static>(
        &self,
        endpoint: &str,
        method: Method,
        query_params: BTreeMap<String, Value>,
        body_params: BTreeMap<String, Value>,
    ) -> anyhow::Result<RestApiResponse<R>> {
        send_request::<R>(
            &self.configuration,
            endpoint,
            method,
            query_params,
            body_params,
            None,
            true,
        )
        .await
    }

    /// List All Convert Pairs
    ///
    /// Query for all convertible token pairs and the tokens’ respective upper/lower limits
    ///
    /// * User needs to supply either or both of the input parameter
    /// * If not defined for both fromAsset and toAsset, only partial token pairs will be returned
    ///
    /// Weight: 3000(IP)
    ///
    /// # Arguments
    ///
    /// - `params`: [`ListAllConvertPairsParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<Vec<models::ListAllConvertPairsResponseInner>>`] on success.
    ///
    /// # Errors
    ///
    /// This function will return an [`anyhow::Error`] if:
    /// - the HTTP request fails
    /// - any parameter is invalid
    /// - the response cannot be parsed
    /// - or one of the following occurs:
    ///   - `RequiredError`
    ///   - `ConnectorClientError`
    ///   - `UnauthorizedError`
    ///   - `ForbiddenError`
    ///   - `TooManyRequestsError`
    ///   - `RateLimitBanError`
    ///   - `ServerError`
    ///   - `NotFoundError`
    ///   - `NetworkError`
    ///   - `BadRequestError`
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/convert/market-data/).
    ///
    pub async fn list_all_convert_pairs(
        &self,
        params: ListAllConvertPairsParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::ListAllConvertPairsResponseInner>>> {
        self.market_data_api_client
            .list_all_convert_pairs(params)
            .await
    }

    /// Query order quantity precision per `asset(USER_DATA)`
    ///
    /// Query for supported asset’s precision information
    ///
    /// Weight: 100(IP)
    ///
    /// # Arguments
    ///
    /// - `params`: [`QueryOrderQuantityPrecisionPerAssetParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<Vec<models::QueryOrderQuantityPrecisionPerAssetResponseInner>>`] on success.
    ///
    /// # Errors
    ///
    /// This function will return an [`anyhow::Error`] if:
    /// - the HTTP request fails
    /// - any parameter is invalid
    /// - the response cannot be parsed
    /// - or one of the following occurs:
    ///   - `RequiredError`
    ///   - `ConnectorClientError`
    ///   - `UnauthorizedError`
    ///   - `ForbiddenError`
    ///   - `TooManyRequestsError`
    ///   - `RateLimitBanError`
    ///   - `ServerError`
    ///   - `NotFoundError`
    ///   - `NetworkError`
    ///   - `BadRequestError`
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/convert/market-data/Query-order-quantity-precision-per-asset).
    ///
    pub async fn query_order_quantity_precision_per_asset(
        &self,
        params: QueryOrderQuantityPrecisionPerAssetParams,
    ) -> anyhow::Result<
        RestApiResponse<Vec<models::QueryOrderQuantityPrecisionPerAssetResponseInner>>,
    > {
        self.market_data_api_client
            .query_order_quantity_precision_per_asset(params)
            .await
    }

    /// Accept Quote (TRADE)
    ///
    /// Accept the offered quote by quote ID.
    ///
    /// Weight: 500(UID)
    ///
    /// # Arguments
    ///
    /// - `params`: [`AcceptQuoteParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::AcceptQuoteResponse>`] on success.
    ///
    /// # Errors
    ///
    /// This function will return an [`anyhow::Error`] if:
    /// - the HTTP request fails
    /// - any parameter is invalid
    /// - the response cannot be parsed
    /// - or one of the following occurs:
    ///   - `RequiredError`
    ///   - `ConnectorClientError`
    ///   - `UnauthorizedError`
    ///   - `ForbiddenError`
    ///   - `TooManyRequestsError`
    ///   - `RateLimitBanError`
    ///   - `ServerError`
    ///   - `NotFoundError`
    ///   - `NetworkError`
    ///   - `BadRequestError`
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/convert/trade/Accept-Quote).
    ///
    pub async fn accept_quote(
        &self,
        params: AcceptQuoteParams,
    ) -> anyhow::Result<RestApiResponse<models::AcceptQuoteResponse>> {
        self.trade_api_client.accept_quote(params).await
    }

    /// Cancel limit order (`USER_DATA`)
    ///
    /// Enable users to cancel a limit order
    ///
    /// Weight: 200(UID)
    ///
    /// # Arguments
    ///
    /// - `params`: [`CancelLimitOrderParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::CancelLimitOrderResponse>`] on success.
    ///
    /// # Errors
    ///
    /// This function will return an [`anyhow::Error`] if:
    /// - the HTTP request fails
    /// - any parameter is invalid
    /// - the response cannot be parsed
    /// - or one of the following occurs:
    ///   - `RequiredError`
    ///   - `ConnectorClientError`
    ///   - `UnauthorizedError`
    ///   - `ForbiddenError`
    ///   - `TooManyRequestsError`
    ///   - `RateLimitBanError`
    ///   - `ServerError`
    ///   - `NotFoundError`
    ///   - `NetworkError`
    ///   - `BadRequestError`
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/convert/trade/Cancel-Order).
    ///
    pub async fn cancel_limit_order(
        &self,
        params: CancelLimitOrderParams,
    ) -> anyhow::Result<RestApiResponse<models::CancelLimitOrderResponse>> {
        self.trade_api_client.cancel_limit_order(params).await
    }

    /// Get Convert Trade `History(USER_DATA)`
    ///
    /// Get Convert Trade History
    ///
    /// * The max interval between startTime and endTime is 30 days.
    ///
    /// Weight: 3000
    ///
    /// # Arguments
    ///
    /// - `params`: [`GetConvertTradeHistoryParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::GetConvertTradeHistoryResponse>`] on success.
    ///
    /// # Errors
    ///
    /// This function will return an [`anyhow::Error`] if:
    /// - the HTTP request fails
    /// - any parameter is invalid
    /// - the response cannot be parsed
    /// - or one of the following occurs:
    ///   - `RequiredError`
    ///   - `ConnectorClientError`
    ///   - `UnauthorizedError`
    ///   - `ForbiddenError`
    ///   - `TooManyRequestsError`
    ///   - `RateLimitBanError`
    ///   - `ServerError`
    ///   - `NotFoundError`
    ///   - `NetworkError`
    ///   - `BadRequestError`
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/convert/trade/Get-Convert-Trade-History).
    ///
    pub async fn get_convert_trade_history(
        &self,
        params: GetConvertTradeHistoryParams,
    ) -> anyhow::Result<RestApiResponse<models::GetConvertTradeHistoryResponse>> {
        self.trade_api_client
            .get_convert_trade_history(params)
            .await
    }

    /// Order `status(USER_DATA)`
    ///
    /// Query order status by order ID.
    ///
    /// Weight: 100(UID)
    ///
    /// # Arguments
    ///
    /// - `params`: [`OrderStatusParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::OrderStatusResponse>`] on success.
    ///
    /// # Errors
    ///
    /// This function will return an [`anyhow::Error`] if:
    /// - the HTTP request fails
    /// - any parameter is invalid
    /// - the response cannot be parsed
    /// - or one of the following occurs:
    ///   - `RequiredError`
    ///   - `ConnectorClientError`
    ///   - `UnauthorizedError`
    ///   - `ForbiddenError`
    ///   - `TooManyRequestsError`
    ///   - `RateLimitBanError`
    ///   - `ServerError`
    ///   - `NotFoundError`
    ///   - `NetworkError`
    ///   - `BadRequestError`
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/convert/trade/Order-Status).
    ///
    pub async fn order_status(
        &self,
        params: OrderStatusParams,
    ) -> anyhow::Result<RestApiResponse<models::OrderStatusResponse>> {
        self.trade_api_client.order_status(params).await
    }

    /// Place limit order (`USER_DATA`)
    ///
    /// Enable users to place a limit order
    ///
    /// * `baseAsset` or `quoteAsset` can be determined via `exchangeInfo` endpoint.
    /// * Limit price is defined from `baseAsset` to `quoteAsset`.
    /// * Either `baseAmount` or `quoteAmount` is used.
    ///
    /// Weight: 500(UID)
    ///
    /// # Arguments
    ///
    /// - `params`: [`PlaceLimitOrderParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::PlaceLimitOrderResponse>`] on success.
    ///
    /// # Errors
    ///
    /// This function will return an [`anyhow::Error`] if:
    /// - the HTTP request fails
    /// - any parameter is invalid
    /// - the response cannot be parsed
    /// - or one of the following occurs:
    ///   - `RequiredError`
    ///   - `ConnectorClientError`
    ///   - `UnauthorizedError`
    ///   - `ForbiddenError`
    ///   - `TooManyRequestsError`
    ///   - `RateLimitBanError`
    ///   - `ServerError`
    ///   - `NotFoundError`
    ///   - `NetworkError`
    ///   - `BadRequestError`
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/convert/trade/Place-Order).
    ///
    pub async fn place_limit_order(
        &self,
        params: PlaceLimitOrderParams,
    ) -> anyhow::Result<RestApiResponse<models::PlaceLimitOrderResponse>> {
        self.trade_api_client.place_limit_order(params).await
    }

    /// Query limit open orders (`USER_DATA`)
    ///
    /// Request a quote for the requested token pairs
    ///
    /// Weight: 3000(UID)
    ///
    /// # Arguments
    ///
    /// - `params`: [`QueryLimitOpenOrdersParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::QueryLimitOpenOrdersResponse>`] on success.
    ///
    /// # Errors
    ///
    /// This function will return an [`anyhow::Error`] if:
    /// - the HTTP request fails
    /// - any parameter is invalid
    /// - the response cannot be parsed
    /// - or one of the following occurs:
    ///   - `RequiredError`
    ///   - `ConnectorClientError`
    ///   - `UnauthorizedError`
    ///   - `ForbiddenError`
    ///   - `TooManyRequestsError`
    ///   - `RateLimitBanError`
    ///   - `ServerError`
    ///   - `NotFoundError`
    ///   - `NetworkError`
    ///   - `BadRequestError`
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/convert/trade/Query-Order).
    ///
    pub async fn query_limit_open_orders(
        &self,
        params: QueryLimitOpenOrdersParams,
    ) -> anyhow::Result<RestApiResponse<models::QueryLimitOpenOrdersResponse>> {
        self.trade_api_client.query_limit_open_orders(params).await
    }

    /// Send Quote `Request(USER_DATA)`
    ///
    /// Request a quote for the requested token pairs
    ///
    /// * Either fromAmount or toAmount should be sent
    /// * `quoteId` will be returned only if you have enough funds to convert
    ///
    /// Weight: 200(UID)
    ///
    /// # Arguments
    ///
    /// - `params`: [`SendQuoteRequestParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::SendQuoteRequestResponse>`] on success.
    ///
    /// # Errors
    ///
    /// This function will return an [`anyhow::Error`] if:
    /// - the HTTP request fails
    /// - any parameter is invalid
    /// - the response cannot be parsed
    /// - or one of the following occurs:
    ///   - `RequiredError`
    ///   - `ConnectorClientError`
    ///   - `UnauthorizedError`
    ///   - `ForbiddenError`
    ///   - `TooManyRequestsError`
    ///   - `RateLimitBanError`
    ///   - `ServerError`
    ///   - `NotFoundError`
    ///   - `NetworkError`
    ///   - `BadRequestError`
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/convert/trade/Send-quote-request).
    ///
    pub async fn send_quote_request(
        &self,
        params: SendQuoteRequestParams,
    ) -> anyhow::Result<RestApiResponse<models::SendQuoteRequestResponse>> {
        self.trade_api_client.send_quote_request(params).await
    }
}
