# app/src/trading/market_analysis/payload.py

from __future__ import annotations

from src.core.numbers import get_value, safe_round
from src.core.types import JsonDict
from src.trading.market_analysis.models import (
    EmaDistanceState,
    EntryTimingState,
    MarketPhase,
    MarketState,
    MarketStructure,
    MomentumState,
    TrendDirection,
    TrendQuality,
    TrendStrength,
    VolatilityState,
)


def build_market_analysis_payload(
    *,
    symbol: str,
    interval: str,
    state: MarketState,
    trend: TrendDirection,
    volatility: VolatilityState,
    trend_strength: TrendStrength,
    trend_quality: TrendQuality,
    market_phase: MarketPhase,
    phase_direction: TrendDirection,
    phase_change_percent: float | None,
    phase_direction_consistency: float | None,
    current_interval_change_percent: float | None,
    current_interval_direction: TrendDirection,
    current_interval_label: str,
    phase_reason: str | None,
    market_structure: MarketStructure,
    market_structure_reason: str | None,
    momentum_state: MomentumState,
    momentum_direction: TrendDirection,
    momentum_change_percent: float | None,
    momentum_strength: float | None,
    breakout_level: float | None,
    breakout_distance_percent: float | None,
    breakout_reason: str | None,
    trend_gap_percent: float | None,
    ema_fast_slope_percent: float | None,
    ema_slow_slope_percent: float | None,
    trend_consistency: float | None,
    trend_efficiency: float | None,
    trend_quality_score_value: float | None,
    ema_distance_atr_ratio: float | None,
    ema_distance_state: EmaDistanceState,
    entry_timing_state: EntryTimingState,
    entry_timing_reason: str | None,
    candle_noise_score: float | None,
    price_position_score: float | None,
    close_price: float,
    ema_fast_period: int,
    ema_slow_period: int,
    ema_fast: float,
    ema_slow: float,
    atr_period: int,
    atr_value: float,
    atr_percent: float,
    atr_percent_baseline: float | None,
    volatility_ratio: float | None,
    rsi_period: int,
    rsi_value: float | None,
    rsi_overbought: float,
    rsi_oversold: float,
    candles_count: int,
    is_trade_allowed: bool,
    htf_context: JsonDict | None,
    htf_trend_context: JsonDict | None,
    market_score: int | None = None,
    market_score_label: str | None = None,
    market_long_score: int | None = None,
    market_short_score: int | None = None,
    last_closed_candle_change_percent: float | None = None,
    last_closed_candle_direction: TrendDirection | None = None,
) -> JsonDict:
    # HTF-контексты могут быть пустыми, если старший ТФ временно недоступен.
    htf_context = htf_context or {}
    htf_trend_context = htf_trend_context or {}

    return {
        # ---------- Base ----------
        "symbol": symbol,
        "interval": interval,
        "candles_count": candles_count,
        "is_trade_allowed": is_trade_allowed,

        # ---------- Market ----------
        "market_state": get_value(state),
        "market_score": market_score,
        "market_score_label": market_score_label,
        "market_long_score": market_long_score,
        "market_short_score": market_short_score,

        # ---------- Trend ----------
        "trend": get_value(trend),
        "market_trend_strength": get_value(trend_strength),
        "market_trend_quality": get_value(trend_quality),
        "market_trend_gap_percent": safe_round(trend_gap_percent, 5),
        "market_trend_consistency": safe_round(trend_consistency, 3),
        "market_trend_efficiency": safe_round(trend_efficiency, 3),
        "trend_quality_score": safe_round(trend_quality_score_value, 3),

        # ---------- Volatility ----------
        "volatility": get_value(volatility),
        "volatility_ratio": safe_round(volatility_ratio, 4),

        # ---------- Phase ----------
        "market_phase": get_value(market_phase),
        "market_phase_direction": get_value(phase_direction),
        "market_phase_change_percent": safe_round(phase_change_percent, 5),
        "market_phase_direction_consistency": safe_round(phase_direction_consistency, 3),
        "market_phase_reason": phase_reason,

        # ---------- Current / Last Candle ----------
        "current_interval_change_percent": safe_round(current_interval_change_percent, 5),
        "current_interval_direction": get_value(current_interval_direction),
        "current_interval_label": current_interval_label,
        "last_closed_candle_change_percent": safe_round(last_closed_candle_change_percent, 5),
        "last_closed_candle_direction": get_value(last_closed_candle_direction),

        # ---------- Structure ----------
        "market_structure": get_value(market_structure),
        "market_structure_reason": market_structure_reason,

        # ---------- Momentum / Breakout ----------
        "momentum_state": get_value(momentum_state),
        "momentum_direction": get_value(momentum_direction),
        "momentum_change_percent": safe_round(momentum_change_percent, 5),
        "momentum_strength": safe_round(momentum_strength, 3),
        "breakout_level": breakout_level,
        "breakout_distance_percent": safe_round(breakout_distance_percent, 5),
        "breakout_reason": breakout_reason,

        # ---------- EMA ----------
        "ema_fast_period": ema_fast_period,
        "ema_slow_period": ema_slow_period,
        "ema_fast": safe_round(ema_fast, 8),
        "ema_slow": safe_round(ema_slow, 8),
        "ema_fast_slope_percent": safe_round(ema_fast_slope_percent, 5),
        "ema_slow_slope_percent": safe_round(ema_slow_slope_percent, 5),
        "ema_distance_atr_ratio": safe_round(ema_distance_atr_ratio, 3),
        "ema_distance_state": get_value(ema_distance_state),

        # ---------- Entry Timing ----------
        "entry_timing_state": get_value(entry_timing_state),
        "entry_timing_reason": entry_timing_reason,

        # ---------- Candle / Price Quality ----------
        "candle_noise_score": safe_round(candle_noise_score, 3),
        "price_position_score": safe_round(price_position_score, 3),
        "close_price": safe_round(close_price, 8),

        # ---------- ATR ----------
        "atr_period": atr_period,
        "atr": safe_round(atr_value, 8),
        "atr_percent": safe_round(atr_percent, 4),
        "atr_percent_baseline": safe_round(atr_percent_baseline, 4),

        # ---------- RSI ----------
        "rsi_period": rsi_period,
        "rsi": safe_round(rsi_value, 2),
        "rsi_overbought": rsi_overbought,
        "rsi_oversold": rsi_oversold,

        # ---------- HTF Volatility ----------
        "htf_interval": htf_context.get("htf_interval"),
        "htf_atr_percent": htf_context.get("htf_atr_percent"),
        "htf_atr_percent_baseline": htf_context.get("htf_atr_percent_baseline"),
        "htf_volatility_ratio": htf_context.get("htf_volatility_ratio"),
        "htf_volatility": htf_context.get("htf_volatility"),
        "htf_volatility_reason": htf_context.get("htf_reason"),

        # ---------- HTF Trend ----------
        "htf_market_state": htf_trend_context.get("htf_market_state"),
        "htf_trend": htf_trend_context.get("htf_trend"),
        "htf_trend_strength": htf_trend_context.get("htf_trend_strength"),
        "htf_trend_quality": htf_trend_context.get("htf_trend_quality"),
        "htf_market_phase": htf_trend_context.get("htf_market_phase"),
        "htf_alignment": htf_trend_context.get("htf_alignment"),
        "htf_confirmation_score": htf_trend_context.get("htf_confirmation_score"),
        "htf_reason": htf_trend_context.get("htf_reason"),
    }