"""OKX 中控委托:须为 OCO 条件单,不得带 reduceOnly 或分两笔 market."""
from __future__ import annotations

import sys
import unittest
from pathlib import Path
from unittest.mock import MagicMock, patch

ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "manual_trading_hub"))

from exchange_orders import _okx_place_tp_sl  # noqa: E402


class TestHubOkxPlaceTpsl(unittest.TestCase):
    def test_okx_place_tpsl_single_oco_without_reduce_only(self):
        captured: list[dict] = []

        def fake_create_order(symbol, order_type, side, amount, price, params):
            captured.append(
                {
                    "symbol": symbol,
                    "type": order_type,
                    "side": side,
                    "amount": amount,
                    "params": dict(params or {}),
                }
            )
            return {"id": "algo-1"}

        ex = MagicMock()
        ex.create_order = fake_create_order
        ex.load_markets = MagicMock()
        ex.amount_to_precision = lambda sym, amt: str(amt)
        ex.price_to_precision = lambda sym, px: str(px)

        with patch.dict(
            "os.environ",
            {"OKX_POS_MODE": "hedge", "OKX_TD_MODE": "cross"},
            clear=False,
        ):
            _okx_place_tp_sl(
                ex,
                "HYPE/USDT:USDT",
                "short",
                6.0,
                75.5,
                70.2,
            )

        self.assertEqual(len(captured), 1, captured)
        call = captured[0]
        self.assertEqual(call["type"], "oco")
        self.assertEqual(call["side"], "buy")
        params = call["params"]
        self.assertNotIn("reduceOnly", params)
        self.assertEqual(params.get("posSide"), "short")
        self.assertEqual(params.get("positionSide"), "short")
        self.assertEqual(params.get("stopLossPrice"), 75.5)
        self.assertEqual(params.get("takeProfitPrice"), 70.2)
        self.assertEqual(params.get("tpOrdPx"), "-1")
        self.assertEqual(params.get("slOrdPx"), "-1")
        self.assertNotIn("stopLoss", params)


if __name__ == "__main__":
    unittest.main()
