"""
Binance Derivatives Trading Options REST API

OpenAPI Specification for the Binance Derivatives Trading Options 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_derivatives_trading_options.rest_api.api import (
    MarketMakerBlockTradeApi,
)
from binance_sdk_derivatives_trading_options.rest_api.models import (
    AcceptBlockTradeOrderResponse,
)
from binance_sdk_derivatives_trading_options.rest_api.models import (
    AccountBlockTradeListResponse,
)

from binance_sdk_derivatives_trading_options.rest_api.models import (
    ExtendBlockTradeOrderResponse,
)
from binance_sdk_derivatives_trading_options.rest_api.models import (
    NewBlockTradeOrderResponse,
)
from binance_sdk_derivatives_trading_options.rest_api.models import (
    QueryBlockTradeDetailsResponse,
)
from binance_sdk_derivatives_trading_options.rest_api.models import (
    QueryBlockTradeOrderResponse,
)


class TestMarketMakerBlockTradeApi:
    @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 = MarketMakerBlockTradeApi(
            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_accept_block_trade_order_success(self, mock_get_signature):
        """Test accept_block_trade_order() successfully with required parameters only."""

        params = {
            "block_order_matching_key": "block_order_matching_key_example",
        }

        expected_response = {
            "blockTradeSettlementKey": "7d046e6e-a429-4335-ab9d-6a681febcde5",
            "expireTime": 1730172115801,
            "liquidity": "MAKER",
            "status": "ACCEPTED",
            "createTime": 1730170315803,
            "legs": [
                {
                    "symbol": "BNB-241101-700-C",
                    "side": "SELL",
                    "quantity": "1.2",
                    "price": "2.8",
                }
            ],
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.accept_block_trade_order(**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 "/eapi/v1/block/order/execute" in request_kwargs["url"]
        assert request_kwargs["method"] == "POST"
        assert normalized["blockOrderMatchingKey"] == "block_order_matching_key_example"

        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(AcceptBlockTradeOrderResponse)

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

        assert response.data() == expected

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

        params = {
            "block_order_matching_key": "block_order_matching_key_example",
            "recv_window": 5000,
        }

        expected_response = {
            "blockTradeSettlementKey": "7d046e6e-a429-4335-ab9d-6a681febcde5",
            "expireTime": 1730172115801,
            "liquidity": "MAKER",
            "status": "ACCEPTED",
            "createTime": 1730170315803,
            "legs": [
                {
                    "symbol": "BNB-241101-700-C",
                    "side": "SELL",
                    "quantity": "1.2",
                    "price": "2.8",
                }
            ],
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.accept_block_trade_order(**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 "/eapi/v1/block/order/execute" 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(AcceptBlockTradeOrderResponse)

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

        assert response.data() == expected

    def test_accept_block_trade_order_missing_required_param_block_order_matching_key(
        self,
    ):
        """Test that accept_block_trade_order() raises RequiredError when 'block_order_matching_key' is missing."""
        params = {
            "block_order_matching_key": "block_order_matching_key_example",
        }
        params["block_order_matching_key"] = None

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

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

        params = {
            "block_order_matching_key": "block_order_matching_key_example",
        }

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

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

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

        expected_response = [
            {
                "parentOrderId": "4675011431944499201",
                "crossType": "USER_BLOCK",
                "legs": [
                    {
                        "createTime": 1730170445600,
                        "updateTime": 1730170445600,
                        "symbol": "BNB-241101-700-C",
                        "orderId": "4675011431944499203",
                        "orderPrice": 2.8,
                        "orderQuantity": 1.2,
                        "orderStatus": "FILLED",
                        "executedQty": 1.2,
                        "executedAmount": 3.36,
                        "fee": 0.336,
                        "orderType": "PREV_QUOTED",
                        "orderSide": "BUY",
                        "id": "1125899906900937837",
                        "tradeId": 1,
                        "tradePrice": 2.8,
                        "tradeQty": 1.2,
                        "tradeTime": 1730170445600,
                        "liquidity": "TAKER",
                        "commission": 0.336,
                    }
                ],
                "blockTradeSettlementKey": "7d085e6e-a229-2335-ab9d-6a581febcd25",
            }
        ]
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.account_block_trade_list()

        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 "/eapi/v1/block/user-trades" 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(AccountBlockTradeListResponse)

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

        assert response.data() == expected

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

        params = {
            "end_time": 1641782889000,
            "start_time": 1623319461670,
            "underlying": "underlying_example",
            "recv_window": 5000,
        }

        expected_response = [
            {
                "parentOrderId": "4675011431944499201",
                "crossType": "USER_BLOCK",
                "legs": [
                    {
                        "createTime": 1730170445600,
                        "updateTime": 1730170445600,
                        "symbol": "BNB-241101-700-C",
                        "orderId": "4675011431944499203",
                        "orderPrice": 2.8,
                        "orderQuantity": 1.2,
                        "orderStatus": "FILLED",
                        "executedQty": 1.2,
                        "executedAmount": 3.36,
                        "fee": 0.336,
                        "orderType": "PREV_QUOTED",
                        "orderSide": "BUY",
                        "id": "1125899906900937837",
                        "tradeId": 1,
                        "tradePrice": 2.8,
                        "tradeQty": 1.2,
                        "tradeTime": 1730170445600,
                        "liquidity": "TAKER",
                        "commission": 0.336,
                    }
                ],
                "blockTradeSettlementKey": "7d085e6e-a229-2335-ab9d-6a581febcd25",
            }
        ]
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.account_block_trade_list(**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 "/eapi/v1/block/user-trades" 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(AccountBlockTradeListResponse)

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

        assert response.data() == expected

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

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

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

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

        params = {
            "block_order_matching_key": "block_order_matching_key_example",
        }

        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response({})

        response = self.client.cancel_block_trade_order(**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 "/eapi/v1/block/order/create" in request_kwargs["url"]
        assert request_kwargs["method"] == "DELETE"
        assert normalized["blockOrderMatchingKey"] == "block_order_matching_key_example"

        assert response is not None

        assert response.data() == {}

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

        params = {
            "block_order_matching_key": "block_order_matching_key_example",
            "recv_window": 5000,
        }

        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response({})

        response = self.client.cancel_block_trade_order(**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 "/eapi/v1/block/order/create" in request_kwargs["url"]
        assert request_kwargs["method"] == "DELETE"

        self.mock_session.request.assert_called_once()
        assert response is not None

        assert response.data() == {}

    def test_cancel_block_trade_order_missing_required_param_block_order_matching_key(
        self,
    ):
        """Test that cancel_block_trade_order() raises RequiredError when 'block_order_matching_key' is missing."""
        params = {
            "block_order_matching_key": "block_order_matching_key_example",
        }
        params["block_order_matching_key"] = None

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

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

        params = {
            "block_order_matching_key": "block_order_matching_key_example",
        }

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

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

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

        params = {
            "block_order_matching_key": "block_order_matching_key_example",
        }

        expected_response = {
            "blockTradeSettlementKey": "3668822b8-1baa-6a2f-adb8-d3de6289b361",
            "expireTime": 1730172007000,
            "liquidity": "TAKER",
            "status": "RECEIVED",
            "createTime": 1730170088111,
            "legs": [
                {
                    "symbol": "BNB-241101-700-C",
                    "side": "BUY",
                    "quantity": "1.2",
                    "price": "2.8",
                }
            ],
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.extend_block_trade_order(**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 "/eapi/v1/block/order/create" in request_kwargs["url"]
        assert request_kwargs["method"] == "PUT"
        assert normalized["blockOrderMatchingKey"] == "block_order_matching_key_example"

        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(ExtendBlockTradeOrderResponse)

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

        assert response.data() == expected

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

        params = {
            "block_order_matching_key": "block_order_matching_key_example",
            "recv_window": 5000,
        }

        expected_response = {
            "blockTradeSettlementKey": "3668822b8-1baa-6a2f-adb8-d3de6289b361",
            "expireTime": 1730172007000,
            "liquidity": "TAKER",
            "status": "RECEIVED",
            "createTime": 1730170088111,
            "legs": [
                {
                    "symbol": "BNB-241101-700-C",
                    "side": "BUY",
                    "quantity": "1.2",
                    "price": "2.8",
                }
            ],
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.extend_block_trade_order(**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 "/eapi/v1/block/order/create" in request_kwargs["url"]
        assert request_kwargs["method"] == "PUT"

        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(ExtendBlockTradeOrderResponse)

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

        assert response.data() == expected

    def test_extend_block_trade_order_missing_required_param_block_order_matching_key(
        self,
    ):
        """Test that extend_block_trade_order() raises RequiredError when 'block_order_matching_key' is missing."""
        params = {
            "block_order_matching_key": "block_order_matching_key_example",
        }
        params["block_order_matching_key"] = None

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

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

        params = {
            "block_order_matching_key": "block_order_matching_key_example",
        }

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

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

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

        params = {
            "liquidity": "liquidity_example",
            "legs": [
                [
                    {
                        "symbol": "BTC-210115-35000-C",
                        "price": "100",
                        "quantity": "0.0002",
                        "side": "BUY",
                        "type": "LIMIT",
                    }
                ]
            ],
        }

        expected_response = {
            "blockTradeSettlementKey": "3668822b8-1baa-6a2f-adb8-d3de6289b361",
            "expireTime": 1730171888109,
            "liquidity": "TAKER",
            "status": "RECEIVED",
            "legs": [
                {
                    "symbol": "BNB-241101-700-C",
                    "side": "BUY",
                    "quantity": "1.2",
                    "price": "2.8",
                }
            ],
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.new_block_trade_order(**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 "/eapi/v1/block/order/create" in request_kwargs["url"]
        assert request_kwargs["method"] == "POST"
        assert normalized["liquidity"] == "liquidity_example"
        assert "legs" in normalized

        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(NewBlockTradeOrderResponse)

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

        assert response.data() == expected

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

        params = {
            "liquidity": "liquidity_example",
            "legs": [
                [
                    {
                        "symbol": "BTC-210115-35000-C",
                        "price": "100",
                        "quantity": "0.0002",
                        "side": "BUY",
                        "type": "LIMIT",
                    }
                ]
            ],
            "recv_window": 5000,
        }

        expected_response = {
            "blockTradeSettlementKey": "3668822b8-1baa-6a2f-adb8-d3de6289b361",
            "expireTime": 1730171888109,
            "liquidity": "TAKER",
            "status": "RECEIVED",
            "legs": [
                {
                    "symbol": "BNB-241101-700-C",
                    "side": "BUY",
                    "quantity": "1.2",
                    "price": "2.8",
                }
            ],
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.new_block_trade_order(**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 "/eapi/v1/block/order/create" 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(NewBlockTradeOrderResponse)

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

        assert response.data() == expected

    def test_new_block_trade_order_missing_required_param_liquidity(self):
        """Test that new_block_trade_order() raises RequiredError when 'liquidity' is missing."""
        params = {
            "liquidity": "liquidity_example",
            "legs": [
                [
                    {
                        "symbol": "BTC-210115-35000-C",
                        "price": "100",
                        "quantity": "0.0002",
                        "side": "BUY",
                        "type": "LIMIT",
                    }
                ]
            ],
        }
        params["liquidity"] = None

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

    def test_new_block_trade_order_missing_required_param_legs(self):
        """Test that new_block_trade_order() raises RequiredError when 'legs' is missing."""
        params = {
            "liquidity": "liquidity_example",
            "legs": [
                [
                    {
                        "symbol": "BTC-210115-35000-C",
                        "price": "100",
                        "quantity": "0.0002",
                        "side": "BUY",
                        "type": "LIMIT",
                    }
                ]
            ],
        }
        params["legs"] = None

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

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

        params = {
            "liquidity": "liquidity_example",
            "legs": [
                [
                    {
                        "symbol": "BTC-210115-35000-C",
                        "price": "100",
                        "quantity": "0.0002",
                        "side": "BUY",
                        "type": "LIMIT",
                    }
                ]
            ],
        }

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

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

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

        params = {
            "block_order_matching_key": "block_order_matching_key_example",
        }

        expected_response = {
            "blockTradeSettlementKey": "12b96c28-ba05-8906-c89t-703215cfb2e6",
            "expireTime": 1730171860460,
            "liquidity": "MAKER",
            "status": "RECEIVED",
            "createTime": 1730170060462,
            "legs": [
                {
                    "symbol": "BNB-241101-700-C",
                    "side": "SELL",
                    "quantity": "1.66",
                    "price": "20",
                }
            ],
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.query_block_trade_details(**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 "/eapi/v1/block/order/execute" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"
        assert normalized["blockOrderMatchingKey"] == "block_order_matching_key_example"

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
