from __future__ import annotations

from decimal import Decimal
from typing import Any

from src.strategies.swing_trend_retest import STRATEGY_ID, SwingRetestContext, build_swing_trend_retest_intent, swing_retest_blockers


def _ctx(**overrides: Any) -> SwingRetestContext:
    data: dict[str, Any] = dict(
        coin="BTC",
        symbol="BTC/USDC:USDC",
        current_price=Decimal("103"),
        sma_fast=Decimal("101"),
        sma_slow=Decimal("98"),
        swing_high=Decimal("106"),
        retest_low=Decimal("100"),
        atr_pct=Decimal("1.20"),
        trend_strength_pct=Decimal("3.00"),
        pullback_from_high_pct=Decimal("2.83"),
        reclaim_pct=Decimal("3.00"),
        volume_24h=Decimal("50000000"),
        spread_pct=Decimal("0.03"),
        expected_slippage_pct=Decimal("0.02"),
        funding_rate_hourly_pct=Decimal("0"),
        market_breadth=4,
        relative_strength_rank=2,
        wallet_equity_usdc=Decimal("75"),
        data_quality_allowed=True,
    )
    data.update(overrides)
    return SwingRetestContext(**data)


def test_swing_retest_builds_research_only_intent_after_pullback_reclaim():
    intent = build_swing_trend_retest_intent(_ctx(), client_order_id="swing-test")

    assert intent is not None
    assert intent.strategy_id == STRATEGY_ID
    assert intent.reason == "swing_trend_retest_reclaim"
    assert intent.stop_loss < Decimal("103")
    assert intent.estimated_notional_usd <= Decimal("15")


def test_swing_retest_blocks_chasing_without_meaningful_pullback():
    blockers = swing_retest_blockers(_ctx(pullback_from_high_pct=Decimal("0.20")))

    assert "no_meaningful_pullback" in blockers
    assert build_swing_trend_retest_intent(_ctx(pullback_from_high_pct=Decimal("0.20")), client_order_id="x") is None


def test_swing_retest_blocks_non_primary_universe_and_weak_trend():
    blockers = swing_retest_blockers(_ctx(coin="WLD", current_price=Decimal("99"), sma_fast=Decimal("100")))

    assert "coin_not_primary_swing_universe" in blockers
    assert "trend_not_confirmed" in blockers
