"""
Binance Dual Investment REST API

OpenAPI Specification for the Binance Dual Investment REST API
The version of the OpenAPI document: 1.0.0
Generated by OpenAPI Generator (https://openapi-generator.tech)

Do not edit the class manually.
"""

import requests
from typing import Optional, TypeVar, Union
from binance_common.configuration import ConfigurationRestAPI
from binance_common.models import ApiResponse
from binance_common.signature import Signers
from binance_common.utils import send_request
from .api.market_data_api import MarketDataApi
from .api.trade_api import TradeApi

from .models import GetDualInvestmentProductListResponse
from .models import ChangeAutoCompoundStatusResponse
from .models import CheckDualInvestmentAccountsResponse
from .models import GetDualInvestmentPositionsResponse
from .models import SubscribeDualInvestmentProductsResponse


T = TypeVar("T")


class DualInvestmentRestAPI:
    def __init__(
        self,
        configuration: ConfigurationRestAPI,
    ) -> None:
        self.configuration = configuration
        self._session = requests.Session()
        self._signer = (
            Signers.get_signer(
                configuration.private_key, configuration.private_key_passphrase
            )
            if configuration.private_key is not None
            else None
        )

        self._marketDataApi = MarketDataApi(
            self.configuration, self._session, self._signer
        )
        self._tradeApi = TradeApi(self.configuration, self._session, self._signer)

    def send_request(
        self,
        endpoint: str,
        method: str,
        query_params: Optional[dict] = None,
        body_params: Optional[dict] = None,
    ) -> ApiResponse[T]:
        """
        Sends an request to the Binance REST API.

        Args:
            endpoint (str): The API endpoint path to send the request to.
            method (str): The HTTP method to use for the request (e.g. "GET", "POST", "PUT", "DELETE").
            query_params (Optional[dict]): The request payload as a dictionary, or None if no payload is required.
            body_params (Optional[dict]): The request body as a dictionary, or None if no body is required.

        Returns:
            ApiResponse[T]: The API response, where T is the expected response type.
        """
        return send_request[T](
            self._session,
            self.configuration,
            method,
            endpoint,
            query_params,
            body_params,
        )

    def send_signed_request(
        self,
        endpoint: str,
        method: str,
        query_params: Optional[dict] = None,
        body_params: Optional[dict] = None,
    ) -> ApiResponse[T]:
        """
        Sends a signed request to the Binance REST API.

        Args:
            endpoint (str): The API endpoint path to send the request to.
            method (str): The HTTP method to use for the request (e.g. "GET", "POST", "PUT", "DELETE").
            query_params (Optional[dict]): The request payload as a dictionary, or None if no payload is required.
            body_params (Optional[dict]): The request body as a dictionary, or None if no body is required.

        Returns:
            ApiResponse[T]: The API response, where T is the expected response type.
        """
        return send_request[T](
            self._session,
            self.configuration,
            method,
            endpoint,
            query_params,
            body_params,
            is_signed=True,
            signer=self._signer,
        )

    def get_dual_investment_product_list(
        self,
        option_type: Union[str, None],
        exercised_coin: Union[str, None],
        invest_coin: Union[str, None],
        page_size: Optional[int] = None,
        page_index: Optional[int] = None,
        recv_window: Optional[int] = None,
    ) -> ApiResponse[GetDualInvestmentProductListResponse]:
        """
                Get Dual Investment product list

                Get Dual Investment product list

        Weight: 1(IP)

                Args:
                    option_type (Union[str, None]): Input CALL or PUT
                    exercised_coin (Union[str, None]): Target exercised asset, e.g.: if you subscribe to a high sell product (call option), you should input: `optionType`:CALL,`exercisedCoin`:USDT,`investCoin`:BNB; if you subscribe to a low buy product (put option), you should input: `optionType`:PUT,`exercisedCoin`:BNB,`investCoin`:USDT
                    invest_coin (Union[str, None]): Asset used for subscribing, e.g.: if you subscribe to a high sell product (call option), you should input: `optionType`:CALL,`exercisedCoin`:USDT,`investCoin`:BNB; if you subscribe to a low buy product (put option), you should input: `optionType`:PUT,`exercisedCoin`:BNB,`investCoin`:USDT
                    page_size (Optional[int] = None): Default: 10, Maximum: 100
                    page_index (Optional[int] = None): Default: 1
                    recv_window (Optional[int] = None): The value cannot be greater than 60000

                Returns:
                    ApiResponse[GetDualInvestmentProductListResponse]

                Raises:
                    RequiredError: If a required parameter is missing.

        """

        return self._marketDataApi.get_dual_investment_product_list(
            option_type, exercised_coin, invest_coin, page_size, page_index, recv_window
        )

    def change_auto_compound_status(
        self,
        position_id: Union[str, None],
        auto_compound_plan: Optional[str] = None,
        recv_window: Optional[int] = None,
    ) -> ApiResponse[ChangeAutoCompoundStatusResponse]:
        """
                Change Auto-Compound status(USER_DATA)

                Change Auto-Compound status

        Weight: 1(IP)

                Args:
                    position_id (Union[str, None]): Get positionId from `/sapi/v1/dci/product/positions`
                    auto_compound_plan (Optional[str] = None):
                    recv_window (Optional[int] = None): The value cannot be greater than 60000

                Returns:
                    ApiResponse[ChangeAutoCompoundStatusResponse]

                Raises:
                    RequiredError: If a required parameter is missing.

        """

        return self._tradeApi.change_auto_compound_status(
            position_id, auto_compound_plan, recv_window
        )

    def check_dual_investment_accounts(
        self,
        recv_window: Optional[int] = None,
    ) -> ApiResponse[CheckDualInvestmentAccountsResponse]:
        """
                Check Dual Investment accounts(USER_DATA)

                Check Dual Investment accounts

        Weight: 1(IP)

                Args:
                    recv_window (Optional[int] = None): The value cannot be greater than 60000

                Returns:
                    ApiResponse[CheckDualInvestmentAccountsResponse]

                Raises:
                    RequiredError: If a required parameter is missing.

        """

        return self._tradeApi.check_dual_investment_accounts(recv_window)

    def get_dual_investment_positions(
        self,
        status: Optional[str] = None,
        page_size: Optional[int] = None,
        page_index: Optional[int] = None,
        recv_window: Optional[int] = None,
    ) -> ApiResponse[GetDualInvestmentPositionsResponse]:
        """
                Get Dual Investment positions(USER_DATA)

                Get Dual Investment positions (batch)

        Weight: 1(IP)

                Args:
                    status (Optional[str] = None): `PENDING`:Products are purchasing, will give results later;`PURCHASE_SUCCESS`:purchase successfully;`SETTLED`: Products are finish settling;`PURCHASE_FAIL`:fail to purchase;`REFUNDING`:refund ongoing;`REFUND_SUCCESS`:refund to spot account successfully; `SETTLING`:Products are settling. If don't fill this field, will response all the position status.
                    page_size (Optional[int] = None): Default: 10, Maximum: 100
                    page_index (Optional[int] = None): Default: 1
                    recv_window (Optional[int] = None): The value cannot be greater than 60000

                Returns:
                    ApiResponse[GetDualInvestmentPositionsResponse]

                Raises:
                    RequiredError: If a required parameter is missing.

        """

        return self._tradeApi.get_dual_investment_positions(
            status, page_size, page_index, recv_window
        )

    def subscribe_dual_investment_products(
        self,
        id: Union[str, None],
        order_id: Union[str, None],
        deposit_amount: Union[float, None],
        auto_compound_plan: Union[str, None],
        recv_window: Optional[int] = None,
    ) -> ApiResponse[SubscribeDualInvestmentProductsResponse]:
        """
                Subscribe Dual Investment products(USER_DATA)

                Subscribe Dual Investment products

        * Products are not available. // this means APR changes to lower value, or orders are not unavailable.
        * Failed. This means System or network errors.

        Weight: 1(IP)

                Args:
                    id (Union[str, None]): get id from `/sapi/v1/dci/product/list`
                    order_id (Union[str, None]): get orderId from `/sapi/v1/dci/product/list`
                    deposit_amount (Union[float, None]): the amount for subscribing
                    auto_compound_plan (Union[str, None]): `NONE`: switch off the plan, `STANDARD`:standard plan,`ADVANCED`:advanced plan
                    recv_window (Optional[int] = None): The value cannot be greater than 60000

                Returns:
                    ApiResponse[SubscribeDualInvestmentProductsResponse]

                Raises:
                    RequiredError: If a required parameter is missing.

        """

        return self._tradeApi.subscribe_dual_investment_products(
            id, order_id, deposit_amount, auto_compound_plan, recv_window
        )
