"""期权开仓:等待完全成交门禁."""
from __future__ import annotations

from lib.exchange.okx_options_lib import wait_option_order_full_fill


class _FakeEx:
    def __init__(self, sequence: list[dict]):
        self._seq = list(sequence)
        self.cancelled = False

    def private_get_trade_order(self, params):
        if not self._seq:
            return {"data": []}
        row = self._seq.pop(0)
        return {"data": [row]}

    def private_post_trade_cancel_order(self, params):
        self.cancelled = True
        return {"data": [{"sCode": "0"}]}


def test_wait_fill_success_when_filled():
    ex = _FakeEx(
        [
            {
                "ordId": "1",
                "instId": "ETH-USD_UM-260720-1870-C",
                "state": "live",
                "sz": "50",
                "accFillSz": "0",
            },
            {
                "ordId": "1",
                "instId": "ETH-USD_UM-260720-1870-C",
                "state": "filled",
                "sz": "50",
                "accFillSz": "50",
                "avgPx": "12.5",
            },
        ]
    )
    out = wait_option_order_full_fill(
        ex,  # type: ignore[arg-type]
        inst_id="ETH-USD_UM-260720-1870-C",
        ord_id="1",
        need_sheets=50,
        timeout_sec=2,
        poll_sec=0.01,
    )
    assert out["ok"] is True
    assert out["filled_sheets"] == 50
    assert float(out["avg_px"]) == 12.5
    assert ex.cancelled is False


def test_wait_fill_timeout_cancels_and_fails():
    ex = _FakeEx(
        [
            {
                "ordId": "2",
                "instId": "ETH-USD_UM-260720-1870-C",
                "state": "live",
                "sz": "50",
                "accFillSz": "0",
            }
            for _ in range(40)
        ]
        + [
            {
                "ordId": "2",
                "instId": "ETH-USD_UM-260720-1870-C",
                "state": "canceled",
                "sz": "50",
                "accFillSz": "0",
            }
        ]
    )
    out = wait_option_order_full_fill(
        ex,  # type: ignore[arg-type]
        inst_id="ETH-USD_UM-260720-1870-C",
        ord_id="2",
        need_sheets=50,
        timeout_sec=0.6,
        poll_sec=0.05,
        cancel_on_timeout=True,
    )
    assert out["ok"] is False
    assert "超时" in (out.get("msg") or "")
    assert ex.cancelled is True
