"""
Binance Algo REST API

OpenAPI Specification for the Binance Algo 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 json
import pytest
import requests

from unittest.mock import MagicMock, patch
from urllib.parse import parse_qs

from binance_common.configuration import ConfigurationRestAPI
from binance_common.errors import RequiredError
from binance_common.utils import normalize_query_values, is_one_of_model, snake_to_camel

from binance_sdk_algo.rest_api.api import SpotAlgoApi
from binance_sdk_algo.rest_api.models import CancelAlgoOrderSpotAlgoResponse
from binance_sdk_algo.rest_api.models import QueryCurrentAlgoOpenOrdersSpotAlgoResponse
from binance_sdk_algo.rest_api.models import QueryHistoricalAlgoOrdersSpotAlgoResponse
from binance_sdk_algo.rest_api.models import QuerySubOrdersSpotAlgoResponse
from binance_sdk_algo.rest_api.models import TimeWeightedAveragePriceSpotAlgoResponse


class TestSpotAlgoApi:
    @pytest.fixture(autouse=True)
    def setup_client(self):
        """Setup a client instance with mocked session before each test method."""
        self.mock_session = MagicMock(spec=requests.Session)
        config = ConfigurationRestAPI(
            api_key="test-api-key",
            api_secret="test-api-secret",
        )
        self.client = SpotAlgoApi(configuration=config, session=self.mock_session)

    def set_mock_response(self, data: dict = {}, status_code=200, headers=None):
        """Helper method to setup mock response for the client's session request."""
        if headers is None:
            headers = {}

        mock_response = MagicMock()
        mock_response.status_code = status_code
        mock_response.json.return_value = data
        mock_response.text = json.dumps(data)
        mock_response.headers = headers

        self.mock_session.request.return_value = mock_response

    @patch("binance_common.utils.get_signature")
    def test_cancel_algo_order_spot_algo_success(self, mock_get_signature):
        """Test cancel_algo_order_spot_algo() successfully with required parameters only."""

        params = {
            "algo_id": 1,
        }

        expected_response = {"algoId": 14511, "success": True, "code": 0, "msg": "OK"}
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.cancel_algo_order_spot_algo(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs
        parsed_params = parse_qs(request_kwargs["params"])
        camel_case_params = {snake_to_camel(k): v for k, v in params.items()}
        normalized = normalize_query_values(parsed_params, camel_case_params)

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/algo/spot/order" in request_kwargs["url"]
        assert request_kwargs["method"] == "DELETE"
        assert normalized["algoId"] == 1

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(CancelAlgoOrderSpotAlgoResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof or is_list or hasattr(CancelAlgoOrderSpotAlgoResponse, "from_dict")
        ):
            expected = CancelAlgoOrderSpotAlgoResponse.from_dict(expected_response)
        else:
            expected = CancelAlgoOrderSpotAlgoResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    @patch("binance_common.utils.get_signature")
    def test_cancel_algo_order_spot_algo_success_with_optional_params(
        self, mock_get_signature
    ):
        """Test cancel_algo_order_spot_algo() successfully with optional parameters."""

        params = {"algo_id": 1, "recv_window": 5000}

        expected_response = {"algoId": 14511, "success": True, "code": 0, "msg": "OK"}
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.cancel_algo_order_spot_algo(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/algo/spot/order" in request_kwargs["url"]
        assert request_kwargs["method"] == "DELETE"

        self.mock_session.request.assert_called_once()
        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(CancelAlgoOrderSpotAlgoResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof or is_list or hasattr(CancelAlgoOrderSpotAlgoResponse, "from_dict")
        ):
            expected = CancelAlgoOrderSpotAlgoResponse.from_dict(expected_response)
        else:
            expected = CancelAlgoOrderSpotAlgoResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    def test_cancel_algo_order_spot_algo_missing_required_param_algo_id(self):
        """Test that cancel_algo_order_spot_algo() raises RequiredError when 'algo_id' is missing."""
        params = {
            "algo_id": 1,
        }
        params["algo_id"] = None

        with pytest.raises(RequiredError, match="Missing required parameter 'algo_id'"):
            self.client.cancel_algo_order_spot_algo(**params)

    def test_cancel_algo_order_spot_algo_server_error(self):
        """Test that cancel_algo_order_spot_algo() raises an error when the server returns an error."""

        params = {
            "algo_id": 1,
        }

        mock_error = Exception("ResponseError")
        self.client.cancel_algo_order_spot_algo = MagicMock(side_effect=mock_error)

        with pytest.raises(Exception, match="ResponseError"):
            self.client.cancel_algo_order_spot_algo(**params)

    @patch("binance_common.utils.get_signature")
    def test_query_current_algo_open_orders_spot_algo_success(self, mock_get_signature):
        """Test query_current_algo_open_orders_spot_algo() successfully with required parameters only."""

        expected_response = {
            "total": 1,
            "orders": [
                {
                    "algoId": 14517,
                    "symbol": "ETHUSDT",
                    "side": "SELL",
                    "totalQty": "5.000",
                    "executedQty": "0.000",
                    "executedAmt": "0.00000000",
                    "avgPrice": "0.00",
                    "clientAlgoId": "d7096549481642f8a0bb69e9e2e31f2e",
                    "bookTime": 1649756817004,
                    "endTime": 0,
                    "algoStatus": "WORKING",
                    "algoType": "TWAP",
                    "urgency": "LOW",
                }
            ],
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.query_current_algo_open_orders_spot_algo()

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/algo/spot/openOrders" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(QueryCurrentAlgoOpenOrdersSpotAlgoResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(QueryCurrentAlgoOpenOrdersSpotAlgoResponse, "from_dict")
        ):
            expected = QueryCurrentAlgoOpenOrdersSpotAlgoResponse.from_dict(
                expected_response
            )
        else:
            expected = QueryCurrentAlgoOpenOrdersSpotAlgoResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    @patch("binance_common.utils.get_signature")
    def test_query_current_algo_open_orders_spot_algo_success_with_optional_params(
        self, mock_get_signature
    ):
        """Test query_current_algo_open_orders_spot_algo() successfully with optional parameters."""

        params = {"recv_window": 5000}

        expected_response = {
            "total": 1,
            "orders": [
                {
                    "algoId": 14517,
                    "symbol": "ETHUSDT",
                    "side": "SELL",
                    "totalQty": "5.000",
                    "executedQty": "0.000",
                    "executedAmt": "0.00000000",
                    "avgPrice": "0.00",
                    "clientAlgoId": "d7096549481642f8a0bb69e9e2e31f2e",
                    "bookTime": 1649756817004,
                    "endTime": 0,
                    "algoStatus": "WORKING",
                    "algoType": "TWAP",
                    "urgency": "LOW",
                }
            ],
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.query_current_algo_open_orders_spot_algo(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/algo/spot/openOrders" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        self.mock_session.request.assert_called_once()
        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(QueryCurrentAlgoOpenOrdersSpotAlgoResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(QueryCurrentAlgoOpenOrdersSpotAlgoResponse, "from_dict")
        ):
            expected = QueryCurrentAlgoOpenOrdersSpotAlgoResponse.from_dict(
                expected_response
            )
        else:
            expected = QueryCurrentAlgoOpenOrdersSpotAlgoResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    def test_query_current_algo_open_orders_spot_algo_server_error(self):
        """Test that query_current_algo_open_orders_spot_algo() raises an error when the server returns an error."""

        mock_error = Exception("ResponseError")
        self.client.query_current_algo_open_orders_spot_algo = MagicMock(
            side_effect=mock_error
        )

        with pytest.raises(Exception, match="ResponseError"):
            self.client.query_current_algo_open_orders_spot_algo()

    @patch("binance_common.utils.get_signature")
    def test_query_historical_algo_orders_spot_algo_success(self, mock_get_signature):
        """Test query_historical_algo_orders_spot_algo() successfully with required parameters only."""

        expected_response = {
            "total": 1,
            "orders": [
                {
                    "algoId": 14518,
                    "symbol": "BNBUSDT",
                    "side": "BUY",
                    "totalQty": "100.00",
                    "executedQty": "0.00",
                    "executedAmt": "0.00000000",
                    "avgPrice": "0.000",
                    "clientAlgoId": "acacab56b3c44bef9f6a8f8ebd2a8408",
                    "bookTime": 1649757019503,
                    "endTime": 1649757088101,
                    "algoStatus": "CANCELLED",
                    "algoType": "VP",
                    "urgency": "LOW",
                }
            ],
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.query_historical_algo_orders_spot_algo()

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/algo/spot/historicalOrders" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(QueryHistoricalAlgoOrdersSpotAlgoResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(QueryHistoricalAlgoOrdersSpotAlgoResponse, "from_dict")
        ):
            expected = QueryHistoricalAlgoOrdersSpotAlgoResponse.from_dict(
                expected_response
            )
        else:
            expected = QueryHistoricalAlgoOrdersSpotAlgoResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    @patch("binance_common.utils.get_signature")
    def test_query_historical_algo_orders_spot_algo_success_with_optional_params(
        self, mock_get_signature
    ):
        """Test query_historical_algo_orders_spot_algo() successfully with optional parameters."""

        params = {
            "symbol": "BTCUSDT",
            "side": "BUY",
            "start_time": 1623319461670,
            "end_time": 1641782889000,
            "page": 1,
            "page_size": 100,
            "recv_window": 5000,
        }

        expected_response = {
            "total": 1,
            "orders": [
                {
                    "algoId": 14518,
                    "symbol": "BNBUSDT",
                    "side": "BUY",
                    "totalQty": "100.00",
                    "executedQty": "0.00",
                    "executedAmt": "0.00000000",
                    "avgPrice": "0.000",
                    "clientAlgoId": "acacab56b3c44bef9f6a8f8ebd2a8408",
                    "bookTime": 1649757019503,
                    "endTime": 1649757088101,
                    "algoStatus": "CANCELLED",
                    "algoType": "VP",
                    "urgency": "LOW",
                }
            ],
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.query_historical_algo_orders_spot_algo(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/algo/spot/historicalOrders" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        self.mock_session.request.assert_called_once()
        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(QueryHistoricalAlgoOrdersSpotAlgoResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(QueryHistoricalAlgoOrdersSpotAlgoResponse, "from_dict")
        ):
            expected = QueryHistoricalAlgoOrdersSpotAlgoResponse.from_dict(
                expected_response
            )
        else:
            expected = QueryHistoricalAlgoOrdersSpotAlgoResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    def test_query_historical_algo_orders_spot_algo_server_error(self):
        """Test that query_historical_algo_orders_spot_algo() raises an error when the server returns an error."""

        mock_error = Exception("ResponseError")
        self.client.query_historical_algo_orders_spot_algo = MagicMock(
            side_effect=mock_error
        )

        with pytest.raises(Exception, match="ResponseError"):
            self.client.query_historical_algo_orders_spot_algo()

    @patch("binance_common.utils.get_signature")
    def test_query_sub_orders_spot_algo_success(self, mock_get_signature):
        """Test query_sub_orders_spot_algo() successfully with required parameters only."""

        params = {
            "algo_id": 1,
        }

        expected_response = {
            "total": 1,
            "executedQty": "1.000",
            "executedAmt": "3229.44000000",
            "subOrders": [
                {
                    "algoId": 13723,
                    "orderId": 8389765519993909000,
                    "orderStatus": "FILLED",
                    "executedQty": "1.000",
                    "executedAmt": "3229.44000000",
                    "feeAmt": "-1.61471999",
                    "feeAsset": "USDT",
                    "bookTime": 1649319001964,
                    "avgPrice": "3229.44",
                    "side": "SELL",
                    "symbol": "ETHUSDT",
                    "subId": 1,
                    "timeInForce": "IMMEDIATE_OR_CANCEL",
                    "origQty": "1.000",
                }
            ],
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.query_sub_orders_spot_algo(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs
        parsed_params = parse_qs(request_kwargs["params"])
        camel_case_params = {snake_to_camel(k): v for k, v in params.items()}
        normalized = normalize_query_values(parsed_params, camel_case_params)

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/algo/spot/subOrders" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"
        assert normalized["algoId"] == 1

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(QuerySubOrdersSpotAlgoResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof or is_list or hasattr(QuerySubOrdersSpotAlgoResponse, "from_dict")
        ):
            expected = QuerySubOrdersSpotAlgoResponse.from_dict(expected_response)
        else:
            expected = QuerySubOrdersSpotAlgoResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    @patch("binance_common.utils.get_signature")
    def test_query_sub_orders_spot_algo_success_with_optional_params(
        self, mock_get_signature
    ):
        """Test query_sub_orders_spot_algo() successfully with optional parameters."""

        params = {"algo_id": 1, "page": 1, "page_size": 100, "recv_window": 5000}

        expected_response = {
            "total": 1,
            "executedQty": "1.000",
            "executedAmt": "3229.44000000",
            "subOrders": [
                {
                    "algoId": 13723,
                    "orderId": 8389765519993909000,
                    "orderStatus": "FILLED",
                    "executedQty": "1.000",
                    "executedAmt": "3229.44000000",
                    "feeAmt": "-1.61471999",
                    "feeAsset": "USDT",
                    "bookTime": 1649319001964,
                    "avgPrice": "3229.44",
                    "side": "SELL",
                    "symbol": "ETHUSDT",
                    "subId": 1,
                    "timeInForce": "IMMEDIATE_OR_CANCEL",
                    "origQty": "1.000",
                }
            ],
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.query_sub_orders_spot_algo(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/algo/spot/subOrders" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        self.mock_session.request.assert_called_once()
        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(QuerySubOrdersSpotAlgoResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof or is_list or hasattr(QuerySubOrdersSpotAlgoResponse, "from_dict")
        ):
            expected = QuerySubOrdersSpotAlgoResponse.from_dict(expected_response)
        else:
            expected = QuerySubOrdersSpotAlgoResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    def test_query_sub_orders_spot_algo_missing_required_param_algo_id(self):
        """Test that query_sub_orders_spot_algo() raises RequiredError when 'algo_id' is missing."""
        params = {
            "algo_id": 1,
        }
        params["algo_id"] = None

        with pytest.raises(RequiredError, match="Missing required parameter 'algo_id'"):
            self.client.query_sub_orders_spot_algo(**params)

    def test_query_sub_orders_spot_algo_server_error(self):
        """Test that query_sub_orders_spot_algo() raises an error when the server returns an error."""

        params = {
            "algo_id": 1,
        }

        mock_error = Exception("ResponseError")
        self.client.query_sub_orders_spot_algo = MagicMock(side_effect=mock_error)

        with pytest.raises(Exception, match="ResponseError"):
            self.client.query_sub_orders_spot_algo(**params)

    @patch("binance_common.utils.get_signature")
    def test_time_weighted_average_price_spot_algo_success(self, mock_get_signature):
        """Test time_weighted_average_price_spot_algo() successfully with required parameters only."""

        params = {
            "symbol": "BTCUSDT",
            "side": "BUY",
            "quantity": 1.0,
            "duration": 5000,
        }

        expected_response = {
            "clientAlgoId": "65ce1630101a480b85915d7e11fd5078",
            "success": True,
            "code": 0,
            "msg": "OK",
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.time_weighted_average_price_spot_algo(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs
        parsed_params = parse_qs(request_kwargs["params"])
        camel_case_params = {snake_to_camel(k): v for k, v in params.items()}
        normalized = normalize_query_values(parsed_params, camel_case_params)

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/algo/spot/newOrderTwap" in request_kwargs["url"]
        assert request_kwargs["method"] == "POST"
        assert normalized["symbol"] == "BTCUSDT"
        assert normalized["side"] == "BUY"
        assert normalized["quantity"] == 1.0
        assert normalized["duration"] == 5000

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(TimeWeightedAveragePriceSpotAlgoResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(TimeWeightedAveragePriceSpotAlgoResponse, "from_dict")
        ):
            expected = TimeWeightedAveragePriceSpotAlgoResponse.from_dict(
                expected_response
            )
        else:
            expected = TimeWeightedAveragePriceSpotAlgoResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    @patch("binance_common.utils.get_signature")
    def test_time_weighted_average_price_spot_algo_success_with_optional_params(
        self, mock_get_signature
    ):
        """Test time_weighted_average_price_spot_algo() successfully with optional parameters."""

        params = {
            "symbol": "BTCUSDT",
            "side": "BUY",
            "quantity": 1.0,
            "duration": 5000,
            "client_algo_id": "1",
            "limit_price": 1.0,
        }

        expected_response = {
            "clientAlgoId": "65ce1630101a480b85915d7e11fd5078",
            "success": True,
            "code": 0,
            "msg": "OK",
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.time_weighted_average_price_spot_algo(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/algo/spot/newOrderTwap" in request_kwargs["url"]
        assert request_kwargs["method"] == "POST"

        self.mock_session.request.assert_called_once()
        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(TimeWeightedAveragePriceSpotAlgoResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(TimeWeightedAveragePriceSpotAlgoResponse, "from_dict")
        ):
            expected = TimeWeightedAveragePriceSpotAlgoResponse.from_dict(
                expected_response
            )
        else:
            expected = TimeWeightedAveragePriceSpotAlgoResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    def test_time_weighted_average_price_spot_algo_missing_required_param_symbol(self):
        """Test that time_weighted_average_price_spot_algo() raises RequiredError when 'symbol' is missing."""
        params = {
            "symbol": "BTCUSDT",
            "side": "BUY",
            "quantity": 1.0,
            "duration": 5000,
        }
        params["symbol"] = None

        with pytest.raises(RequiredError, match="Missing required parameter 'symbol'"):
            self.client.time_weighted_average_price_spot_algo(**params)

    def test_time_weighted_average_price_spot_algo_missing_required_param_side(self):
        """Test that time_weighted_average_price_spot_algo() raises RequiredError when 'side' is missing."""
        params = {
            "symbol": "BTCUSDT",
            "side": "BUY",
            "quantity": 1.0,
            "duration": 5000,
        }
        params["side"] = None

        with pytest.raises(RequiredError, match="Missing required parameter 'side'"):
            self.client.time_weighted_average_price_spot_algo(**params)

    def test_time_weighted_average_price_spot_algo_missing_required_param_quantity(
        self,
    ):
        """Test that time_weighted_average_price_spot_algo() raises RequiredError when 'quantity' is missing."""
        params = {
            "symbol": "BTCUSDT",
            "side": "BUY",
            "quantity": 1.0,
            "duration": 5000,
        }
        params["quantity"] = None

        with pytest.raises(
            RequiredError, match="Missing required parameter 'quantity'"
        ):
            self.client.time_weighted_average_price_spot_algo(**params)

    def test_time_weighted_average_price_spot_algo_missing_required_param_duration(
        self,
    ):
        """Test that time_weighted_average_price_spot_algo() raises RequiredError when 'duration' is missing."""
        params = {
            "symbol": "BTCUSDT",
            "side": "BUY",
            "quantity": 1.0,
            "duration": 5000,
        }
        params["duration"] = None

        with pytest.raises(
            RequiredError, match="Missing required parameter 'duration'"
        ):
            self.client.time_weighted_average_price_spot_algo(**params)

    def test_time_weighted_average_price_spot_algo_server_error(self):
        """Test that time_weighted_average_price_spot_algo() raises an error when the server returns an error."""

        params = {
            "symbol": "BTCUSDT",
            "side": "BUY",
            "quantity": 1.0,
            "duration": 5000,
        }

        mock_error = Exception("ResponseError")
        self.client.time_weighted_average_price_spot_algo = MagicMock(
            side_effect=mock_error
        )

        with pytest.raises(Exception, match="ResponseError"):
            self.client.time_weighted_average_price_spot_algo(**params)
