"""实盘限流 / 退避单测。"""

from __future__ import annotations

import time

from app.live.rate_limit import (
    LiveRetryGate,
    RateLimitError,
    TradeThrottle,
    get_throttle,
    is_rate_limit_error,
)


def test_is_rate_limit_error() -> None:
    assert is_rate_limit_error("HTTP 429 too many")
    assert is_rate_limit_error("binance eapi cooldown 12s")
    assert is_rate_limit_error(RateLimitError("x", retry_after=5))
    assert not is_rate_limit_error("保证金不足")


def test_trade_throttle_cooldown() -> None:
    t = TradeThrottle("ut_throttle", min_interval_sec=0.01, cooldown_429_sec=0.3)
    t.before_request()
    t.mark_http(429)
    try:
        t.before_request()
        assert False, "expected RateLimitError"
    except RateLimitError as e:
        assert e.retry_after > 0
    time.sleep(0.35)
    t.before_request()  # 冷却结束后可继续


def test_get_throttle_singleton() -> None:
    a = get_throttle("ut_shared_x", min_interval_sec=0.01)
    b = get_throttle("ut_shared_x")
    assert a is b


def test_live_retry_gate_backoff() -> None:
    g = LiveRetryGate(base_sec=0.05, max_sec=0.2, rate_limit_min_sec=0.1, trip_after=100)
    assert g.allow("k")[0] is True
    d1 = g.fail("k")
    assert d1 >= 0.05
    ok, left = g.allow("k")
    assert ok is False
    assert left > 0
    time.sleep(d1 + 0.02)
    assert g.allow("k")[0] is True
    g.success("k")
    assert g.fails("k") == 0


def test_live_retry_gate_rate_limited_longer() -> None:
    g = LiveRetryGate(base_sec=0.01, rate_limit_min_sec=0.2)
    d = g.fail("rl", rate_limited=True)
    assert d >= 0.2
