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

from __future__ import annotations

from collections.abc import Sequence
from math import isfinite

from src.core.numbers import safe_float
from src.market_data.acquisition.models.candle import Candle
from src.trading.market_analysis.models import TrendDirection


def candle_noise_score(
    candles: Sequence[Candle],
    *,
    candle_noise_window: int,
    min_clean_body_ratio: float,
) -> float | None:
    window = candles[-candle_noise_window:]

    if not window:
        return None

    clean_count = 0
    total_count = 0

    for candle in window:
        high = safe_float(candle.high_price)
        low = safe_float(candle.low_price)
        open_price = safe_float(candle.open_price)
        close_price = safe_float(candle.close_price)

        if (
            high is None
            or low is None
            or open_price is None
            or close_price is None
            or not isfinite(high)
            or not isfinite(low)
            or not isfinite(open_price)
            or not isfinite(close_price)
            or high <= low
        ):
            continue

        candle_range = high - low
        body = abs(close_price - open_price)
        body_ratio = body / candle_range

        total_count += 1

        if body_ratio >= min_clean_body_ratio:
            clean_count += 1

    if total_count == 0:
        return None

    return clean_count / total_count


def price_position_score(
    *,
    closes: list[float],
    ema_fast: float,
    trend: TrendDirection,
    price_position_window: int,
) -> float | None:
    window = closes[-price_position_window:]

    if not window:
        return None

    valid_count = 0

    for close_price in window:
        if trend == TrendDirection.UP:
            if close_price > ema_fast:
                valid_count += 1

        elif trend == TrendDirection.DOWN:
            if close_price < ema_fast:
                valid_count += 1

        else:
            return None

    return valid_count / len(window)