/*
 * Binance Algo REST API
 *
 * OpenAPI Specification for the Binance Algo 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,
    future_algo_api_client: FutureAlgoApiClient,
    spot_algo_api_client: SpotAlgoApiClient,
}

impl RestApi {
    pub fn new(configuration: ConfigurationRestApi) -> Self {
        let future_algo_api_client = FutureAlgoApiClient::new(configuration.clone());
        let spot_algo_api_client = SpotAlgoApiClient::new(configuration.clone());

        Self {
            configuration,
            future_algo_api_client,
            spot_algo_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
    }

    /// Cancel Algo Order(TRADE)
    ///
    /// Cancel an active order.
    ///
    /// * You need to enable `Futures Trading Permission` for the api key which requests this endpoint.
    /// * Base URL: <https://api.binance.com>
    ///
    /// Weight: 1
    ///
    /// # Arguments
    ///
    /// - `params`: [`CancelAlgoOrderFutureAlgoParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::CancelAlgoOrderFutureAlgoResponse>`] 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/algo/future-algo/Cancel-Algo-Order).
    ///
    pub async fn cancel_algo_order_future_algo(
        &self,
        params: CancelAlgoOrderFutureAlgoParams,
    ) -> anyhow::Result<RestApiResponse<models::CancelAlgoOrderFutureAlgoResponse>> {
        self.future_algo_api_client
            .cancel_algo_order_future_algo(params)
            .await
    }

    /// Query Current Algo Open `Orders(USER_DATA)`
    ///
    /// Query Current Algo Open Orders
    ///
    /// * You need to enable `Futures Trading Permission` for the api key which requests this endpoint.
    /// * Base URL: <https://api.binance.com>
    ///
    /// Weight: 1
    ///
    /// # Arguments
    ///
    /// - `params`: [`QueryCurrentAlgoOpenOrdersFutureAlgoParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::QueryCurrentAlgoOpenOrdersFutureAlgoResponse>`] 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/algo/future-algo/Query-Current-Algo-Open-Orders).
    ///
    pub async fn query_current_algo_open_orders_future_algo(
        &self,
        params: QueryCurrentAlgoOpenOrdersFutureAlgoParams,
    ) -> anyhow::Result<RestApiResponse<models::QueryCurrentAlgoOpenOrdersFutureAlgoResponse>> {
        self.future_algo_api_client
            .query_current_algo_open_orders_future_algo(params)
            .await
    }

    /// Query Historical Algo `Orders(USER_DATA)`
    ///
    /// Query Historical Algo Order
    ///
    /// * You need to enable `Futures Trading Permission` for the api key which requests this endpoint.
    /// * Base URL: <https://api.binance.com>
    ///
    /// Weight: 1
    ///
    /// # Arguments
    ///
    /// - `params`: [`QueryHistoricalAlgoOrdersFutureAlgoParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::QueryHistoricalAlgoOrdersFutureAlgoResponse>`] 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/algo/future-algo/Query-Historical-Algo-Orders).
    ///
    pub async fn query_historical_algo_orders_future_algo(
        &self,
        params: QueryHistoricalAlgoOrdersFutureAlgoParams,
    ) -> anyhow::Result<RestApiResponse<models::QueryHistoricalAlgoOrdersFutureAlgoResponse>> {
        self.future_algo_api_client
            .query_historical_algo_orders_future_algo(params)
            .await
    }

    /// Query Sub `Orders(USER_DATA)`
    ///
    /// Get respective sub orders for a specified algoId
    ///
    /// * You need to enable `Futures Trading Permission` for the api key which requests this endpoint.
    /// * Base URL: <https://api.binance.com>
    ///
    /// Weight: 1
    ///
    /// # Arguments
    ///
    /// - `params`: [`QuerySubOrdersFutureAlgoParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::QuerySubOrdersFutureAlgoResponse>`] 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/algo/future-algo/Query-Sub-Orders).
    ///
    pub async fn query_sub_orders_future_algo(
        &self,
        params: QuerySubOrdersFutureAlgoParams,
    ) -> anyhow::Result<RestApiResponse<models::QuerySubOrdersFutureAlgoResponse>> {
        self.future_algo_api_client
            .query_sub_orders_future_algo(params)
            .await
    }

    /// Time-Weighted Average Price(Twap) New Order(TRADE)
    ///
    /// Send in a Twap new order.
    /// Only support on USDⓈ-M Contracts.
    ///
    /// * Total Algo open orders max allowed: `30` orders.
    /// * Leverage of symbols and position mode will be the same as your futures account settings. You can set up through the trading page or fapi.
    /// * Receiving `"success": true` does not mean that your order will be executed. Please use the query order endpoints（`GET sapi/v1/algo/futures/openOrders` or `GET sapi/v1/algo/futures/historicalOrders`） to check the order status.
    /// For example: Your futures balance is insufficient, or open position with reduce only or position side is inconsistent with your own setting. In these cases you will receive `"success": true`, but the order status will be `expired` after we check it.
    /// * `quantity` * 60 / `duration` should be larger than minQty
    /// * `duration` cannot be less than 5 mins or more than 24 hours.
    /// * For delivery contracts, TWAP end time should be one hour earlier than the delivery time of the symbol.
    /// * You need to enable `Futures Trading Permission` for the api key which requests this endpoint.
    /// * Base URL: <https://api.binance.com>
    ///
    /// Weight: 3000
    ///
    /// # Arguments
    ///
    /// - `params`: [`TimeWeightedAveragePriceFutureAlgoParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::TimeWeightedAveragePriceFutureAlgoResponse>`] 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/algo/future-algo/Time-Weighted-Average-Price-New-Order).
    ///
    pub async fn time_weighted_average_price_future_algo(
        &self,
        params: TimeWeightedAveragePriceFutureAlgoParams,
    ) -> anyhow::Result<RestApiResponse<models::TimeWeightedAveragePriceFutureAlgoResponse>> {
        self.future_algo_api_client
            .time_weighted_average_price_future_algo(params)
            .await
    }

    /// Volume Participation(VP) New Order (TRADE)
    ///
    /// Send in a VP new order.
    /// Only support on USDⓈ-M Contracts.
    ///
    /// * Total Algo open orders max allowed: `10` orders.
    /// * Leverage of symbols and position mode will be the same as your futures account settings. You can set up through the trading page or fapi.
    /// * Receiving `"success": true` does not mean that your order will be executed. Please use the query order endpoints（`GET sapi/v1/algo/futures/openOrders` or `GET sapi/v1/algo/futures/historicalOrders`） to check the order status.
    /// For example: Your futures balance is insufficient, or open position with reduce only or position side is inconsistent with your own setting. In these cases you will receive `"success": true`, but the order status will be `expired` after we check it.
    /// * You need to enable `Futures Trading Permission` for the api key which requests this endpoint.
    /// * Base URL: <https://api.binance.com>
    ///
    /// Weight: 300
    ///
    /// # Arguments
    ///
    /// - `params`: [`VolumeParticipationFutureAlgoParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::VolumeParticipationFutureAlgoResponse>`] 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/algo/future-algo/Volume-Participation-New-Order).
    ///
    pub async fn volume_participation_future_algo(
        &self,
        params: VolumeParticipationFutureAlgoParams,
    ) -> anyhow::Result<RestApiResponse<models::VolumeParticipationFutureAlgoResponse>> {
        self.future_algo_api_client
            .volume_participation_future_algo(params)
            .await
    }

    /// Cancel Algo Order(TRADE)
    ///
    /// Cancel an open TWAP order
    ///
    /// Weight: 1
    ///
    /// # Arguments
    ///
    /// - `params`: [`CancelAlgoOrderSpotAlgoParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::CancelAlgoOrderSpotAlgoResponse>`] 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/algo/spot-algo/Cancel-Algo-Order).
    ///
    pub async fn cancel_algo_order_spot_algo(
        &self,
        params: CancelAlgoOrderSpotAlgoParams,
    ) -> anyhow::Result<RestApiResponse<models::CancelAlgoOrderSpotAlgoResponse>> {
        self.spot_algo_api_client
            .cancel_algo_order_spot_algo(params)
            .await
    }

    /// Query Current Algo Open `Orders(USER_DATA)`
    ///
    /// Get all open SPOT TWAP orders
    ///
    /// Weight: 1
    ///
    /// # Arguments
    ///
    /// - `params`: [`QueryCurrentAlgoOpenOrdersSpotAlgoParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::QueryCurrentAlgoOpenOrdersSpotAlgoResponse>`] 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/algo/spot-algo/Query-Current-Algo-Open-Orders).
    ///
    pub async fn query_current_algo_open_orders_spot_algo(
        &self,
        params: QueryCurrentAlgoOpenOrdersSpotAlgoParams,
    ) -> anyhow::Result<RestApiResponse<models::QueryCurrentAlgoOpenOrdersSpotAlgoResponse>> {
        self.spot_algo_api_client
            .query_current_algo_open_orders_spot_algo(params)
            .await
    }

    /// Query Historical Algo `Orders(USER_DATA)`
    ///
    /// Get all historical SPOT TWAP orders
    ///
    /// Weight: 1
    ///
    /// # Arguments
    ///
    /// - `params`: [`QueryHistoricalAlgoOrdersSpotAlgoParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::QueryHistoricalAlgoOrdersSpotAlgoResponse>`] 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/algo/spot-algo/Query-Historical-Algo-Orders).
    ///
    pub async fn query_historical_algo_orders_spot_algo(
        &self,
        params: QueryHistoricalAlgoOrdersSpotAlgoParams,
    ) -> anyhow::Result<RestApiResponse<models::QueryHistoricalAlgoOrdersSpotAlgoResponse>> {
        self.spot_algo_api_client
            .query_historical_algo_orders_spot_algo(params)
            .await
    }

    /// Query Sub `Orders(USER_DATA)`
    ///
    /// Get respective sub orders for a specified algoId
    ///
    /// Weight: 1
    ///
    /// # Arguments
    ///
    /// - `params`: [`QuerySubOrdersSpotAlgoParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::QuerySubOrdersSpotAlgoResponse>`] 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/algo/spot-algo/Query-Sub-Orders).
    ///
    pub async fn query_sub_orders_spot_algo(
        &self,
        params: QuerySubOrdersSpotAlgoParams,
    ) -> anyhow::Result<RestApiResponse<models::QuerySubOrdersSpotAlgoResponse>> {
        self.spot_algo_api_client
            .query_sub_orders_spot_algo(params)
            .await
    }

    /// Time-Weighted Average Price(Twap) New Order(TRADE)
    ///
    /// Place a new spot TWAP order with Algo service.
    ///
    /// * Total Algo open orders max allowed: `20` orders.
    ///
    /// Weight: 3000
    ///
    /// # Arguments
    ///
    /// - `params`: [`TimeWeightedAveragePriceSpotAlgoParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`RestApiResponse<models::TimeWeightedAveragePriceSpotAlgoResponse>`] 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/algo/spot-algo/Time-Weighted-Average-Price-New-Order).
    ///
    pub async fn time_weighted_average_price_spot_algo(
        &self,
        params: TimeWeightedAveragePriceSpotAlgoParams,
    ) -> anyhow::Result<RestApiResponse<models::TimeWeightedAveragePriceSpotAlgoResponse>> {
        self.spot_algo_api_client
            .time_weighted_average_price_spot_algo(params)
            .await
    }
}
