from __future__ import annotations

from dataclasses import replace
from decimal import Decimal

from src.market.trend_retest_features import TrendRetestFeatures
from src.strategies.relative_strength_momentum_v77_2 import (
    MOMENTUM_RESEARCH_ID,
    MOMENTUM_VERSION,
    build_momentum_intent,
    momentum_blockers,
)


def _feature(**changes) -> TrendRetestFeatures:
    base = TrendRetestFeatures(
        coin="ETH", current_price=Decimal("102"), candle_ts=200, data_window_id="w1",
        open_15m=Decimal("101.5"), high_15m=Decimal("102.2"), low_15m=Decimal("101.3"), close_15m=Decimal("102"),
        move_15m_pct=Decimal("0.49"), move_1h_pct=Decimal("1.20"),
        sma_1h_fast=Decimal("101"), sma_1h_slow=Decimal("99"), sma_4h_fast=Decimal("98"), sma_4h_slow=Decimal("96"),
        atr_pct=Decimal("0.70"), rsi_15m=Decimal("64"), volume_24h=Decimal("80000000"), volume_ratio=Decimal("1.15"),
        recent_high=Decimal("101.8"), recent_low=Decimal("99.5"), pullback_from_high_pct=Decimal("-0.20"), rebound_from_low_pct=Decimal("2.51"),
        spread_pct=Decimal("0.02"), bid_depth_notional_5=Decimal("50000"), ask_depth_notional_5=Decimal("50000"),
        buy_impact_1k_pct=Decimal("0.02"), sell_impact_1k_pct=Decimal("0.02"), funding_rate_hourly_pct=Decimal("0.001"),
        open_interest=Decimal("1000"), premium_pct=Decimal("0"), strength_rank=1, weakness_rank=4, breadth_positive_pct=Decimal("75"),
        continuation_closes_confirmed=True,
    )
    return replace(base, **changes)


def test_momentum_candidate_accepts_strong_non_overheated_eth_continuation():
    feature = _feature()
    assert momentum_blockers(feature) == []
    intent = build_momentum_intent(feature, client_order_id="m1")
    assert intent is not None
    assert intent.strategy_id == MOMENTUM_RESEARCH_ID
    assert intent.side == "buy"
    assert intent.estimated_notional_usd == Decimal("10")
    assert intent.risk_usd <= Decimal("0.075")
    assert MOMENTUM_VERSION == "v77.2.0"


def test_momentum_candidate_blocks_weak_breadth_rank_and_missing_two_close_confirmation():
    blockers = momentum_blockers(_feature(strength_rank=3, breadth_positive_pct=Decimal("25"), continuation_closes_confirmed=False))
    assert "not_top_two_relative_strength" in blockers
    assert "breadth_not_supportive" in blockers
    assert "two_close_confirmation_missing" in blockers


def test_momentum_candidate_blocks_chase_and_unapproved_coin():
    blockers = momentum_blockers(_feature(coin="SOL", move_15m_pct=Decimal("1.10"), move_1h_pct=Decimal("3.1"), rsi_15m=Decimal("75")))
    assert "coin_not_momentum_universe" in blockers
    assert "momentum_overheated" in blockers
    assert "rsi_overheated" in blockers


def test_momentum_candidate_requires_real_liquidity_volume_and_trend():
    feature = _feature(volume_ratio=Decimal("1.01"), spread_pct=Decimal("0.09"), sma_4h_fast=Decimal("95"), sma_4h_slow=Decimal("96"))
    blockers = momentum_blockers(feature)
    assert "volume_confirmation_missing" in blockers
    assert "spread_too_wide" in blockers
    assert "trend_4h_not_bullish" in blockers
