from __future__ import annotations

from decimal import Decimal, ROUND_DOWN

from src.execution.order_intent import OrderIntent
from src.market.trend_retest_features import TrendRetestFeatures

MOMENTUM_RESEARCH_ID = "research_v77_2_relative_strength_momentum_continuation"
MOMENTUM_VERSION = "v77.2.0"
MOMENTUM_COINS = {"BTC", "ETH", "LINK"}


def momentum_blockers(feature: TrendRetestFeatures) -> list[str]:
    blockers: list[str] = []
    if feature.coin not in MOMENTUM_COINS:
        blockers.append("coin_not_momentum_universe")
    if not feature.data_quality_allowed:
        blockers.extend(feature.data_quality_reasons or ("data_quality",))
    if feature.volume_24h < Decimal("25000000"):
        blockers.append("weak_liquidity")
    if feature.spread_pct > Decimal("0.06"):
        blockers.append("spread_too_wide")
    if feature.buy_impact_1k_pct > Decimal("0.06"):
        blockers.append("impact_slippage_too_high")
    if feature.sma_1h_fast <= feature.sma_1h_slow or feature.close_15m <= feature.sma_1h_fast:
        blockers.append("trend_1h_not_bullish")
    if feature.sma_4h_fast <= feature.sma_4h_slow:
        blockers.append("trend_4h_not_bullish")
    if feature.breadth_positive_pct < Decimal("60"):
        blockers.append("breadth_not_supportive")
    if feature.strength_rank > 2:
        blockers.append("not_top_two_relative_strength")
    if feature.move_1h_pct < Decimal("0.40"):
        blockers.append("momentum_not_established")
    if feature.move_15m_pct <= 0:
        blockers.append("latest_close_not_positive")
    if feature.move_15m_pct > Decimal("0.90") or feature.move_1h_pct > Decimal("2.50"):
        blockers.append("momentum_overheated")
    if feature.close_15m <= feature.recent_high:
        blockers.append("breakout_close_missing")
    if not feature.continuation_closes_confirmed:
        blockers.append("two_close_confirmation_missing")
    if feature.volume_ratio < Decimal("1.05"):
        blockers.append("volume_confirmation_missing")
    if feature.rsi_15m < Decimal("52"):
        blockers.append("rsi_momentum_missing")
    if feature.rsi_15m > Decimal("72"):
        blockers.append("rsi_overheated")
    distance_above_fast = (feature.close_15m / feature.sma_1h_fast - Decimal("1")) * Decimal("100") if feature.sma_1h_fast > 0 else Decimal("999")
    if distance_above_fast > Decimal("1.50"):
        blockers.append("too_far_above_1h_trend")
    if feature.funding_rate_hourly_pct > Decimal("0.020"):
        blockers.append("funding_too_crowded")
    return list(dict.fromkeys(blockers))


def build_momentum_intent(feature: TrendRetestFeatures, *, client_order_id: str) -> OrderIntent | None:
    if momentum_blockers(feature):
        return None
    price = feature.current_price
    if price <= 0:
        return None
    notional = Decimal("10")
    stop_distance_pct = max(Decimal("0.65"), min(Decimal("0.75"), feature.atr_pct * Decimal("0.80")))
    stop = price * (Decimal("1") - stop_distance_pct / Decimal("100"))
    take_profit = price + (price - stop) * Decimal("1.50")
    size = (notional / price).quantize(Decimal("0.00000001"), rounding=ROUND_DOWN)
    risk_usd = notional * stop_distance_pct / Decimal("100")
    return OrderIntent(
        strategy_id=MOMENTUM_RESEARCH_ID,
        symbol=f"{feature.coin}/USDC:USDC",
        coin=feature.coin,
        side="buy",
        reduce_only=False,
        order_type="market",
        tif="Ioc",
        size=size,
        price=None,
        trigger_price=None,
        stop_loss=stop.quantize(Decimal("0.00000001"), rounding=ROUND_DOWN),
        take_profit=take_profit.quantize(Decimal("0.00000001"), rounding=ROUND_DOWN),
        client_order_id=client_order_id,
        reason="relative_strength_two_close_momentum_continuation_research",
        risk_usd=risk_usd,
        estimated_notional_usd=notional,
    )
