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

from __future__ import annotations

from src.trading.market_analysis.models import (
    MarketPhase,
    MarketState,
    MomentumState,
    TrendDirection,
    TrendQuality,
    TrendStrength,
    VolatilityState,
)


def classify_market_state(
    *,
    trend: TrendDirection,
    volatility: VolatilityState,
    trend_strength: TrendStrength,
    trend_quality: TrendQuality,
    market_phase: MarketPhase,
    momentum_state: MomentumState,
    momentum_direction: TrendDirection,
    ema_fast_slope_percent: float | None,
    ema_slow_slope_percent: float | None,
    fast_slope_threshold_percent: float,
    slow_slope_threshold_percent: float,
    candle_noise_score: float | None,
    price_position_score: float | None,
    min_clean_candle_score: float,
    min_price_position_score: float,
) -> MarketState:
    fast_slope = ema_fast_slope_percent or 0.0
    range_slope_threshold_percent = max(
        fast_slope_threshold_percent,
        slow_slope_threshold_percent * 2,
    )

    if volatility == VolatilityState.HIGH:
        return MarketState.HIGH_VOLATILITY

    if volatility == VolatilityState.LOW:
        return MarketState.LOW_VOLATILITY

    if (
        trend == TrendDirection.UP
        and momentum_state in {MomentumState.BREAKOUT_UP, MomentumState.MOMENTUM_UP}
        and momentum_direction == TrendDirection.UP
        and fast_slope > 0
    ):
        return MarketState.TREND_UP

    if (
        trend == TrendDirection.DOWN
        and momentum_state in {MomentumState.BREAKOUT_DOWN, MomentumState.MOMENTUM_DOWN}
        and momentum_direction == TrendDirection.DOWN
        and fast_slope < 0
    ):
        return MarketState.TREND_DOWN

    if market_phase in {MarketPhase.RANGE, MarketPhase.SQUEEZE}:
        return MarketState.RANGE

    if trend_strength == TrendStrength.WEAK:
        return MarketState.RANGE

    if (
        trend_quality == TrendQuality.NOISY
        and trend_strength != TrendStrength.STRONG
    ):
        return MarketState.RANGE

    if (
        candle_noise_score is not None
        and candle_noise_score < min_clean_candle_score
        and abs(fast_slope) < range_slope_threshold_percent
    ):
        return MarketState.RANGE

    if (
        price_position_score is not None
        and price_position_score < min_price_position_score
        and abs(fast_slope) < range_slope_threshold_percent
    ):
        return MarketState.RANGE

    if (
        trend == TrendDirection.UP
        and trend_strength in {TrendStrength.NORMAL, TrendStrength.STRONG}
        and momentum_direction in {TrendDirection.UP, TrendDirection.FLAT}
        and fast_slope > 0
    ):
        return MarketState.TREND_UP

    if (
        trend == TrendDirection.DOWN
        and trend_strength in {TrendStrength.NORMAL, TrendStrength.STRONG}
        and momentum_direction in {TrendDirection.DOWN, TrendDirection.FLAT}
        and fast_slope < 0
    ):
        return MarketState.TREND_DOWN

    return MarketState.RANGE