# app/tests/unit/trading/market_analysis/indicators/test_volatility_candle.py

from __future__ import annotations

from datetime import datetime, timezone
from decimal import Decimal

from src.market_data.acquisition.models.candle import Candle


def _candle(
    *,
    index: int = 0,
    open_price: str = "100",
    high_price: str = "110",
    low_price: str = "90",
    close_price: str = "105",
    volume: str = "10",
) -> Candle:
    return Candle(
        symbol="BTC/USD_LEVERAGE",
        interval="1m",
        open_time=datetime.fromtimestamp(
            1_750_000_000 + index * 60,
            tz=timezone.utc,
        ),
        open_price=Decimal(open_price),
        high_price=Decimal(high_price),
        low_price=Decimal(low_price),
        close_price=Decimal(close_price),
        volume=Decimal(volume),
        source="test",
    )


from src.trading.market_analysis.indicators.volatility import (
    atr,
    atr_percent_baseline,
)


def test_atr_accepts_canonical_candles_with_decimal_values() -> None:
    candles = [
        _candle(
            index=0,
            high_price="105",
            low_price="95",
            close_price="100",
        ),
        _candle(
            index=1,
            high_price="110",
            low_price="95",
            close_price="105",
        ),
        _candle(
            index=2,
            high_price="112",
            low_price="100",
            close_price="108",
        ),
    ]

    result = atr(candles, period=2)

    assert result == 13.5
    assert isinstance(result, float)


def test_atr_returns_none_when_candles_are_insufficient() -> None:
    candles = [
        _candle(index=0),
        _candle(index=1),
    ]

    assert atr(candles, period=2) is None


def test_atr_returns_none_for_non_positive_period() -> None:
    candles = [
        _candle(index=0),
        _candle(index=1),
    ]

    assert atr(candles, period=0) is None


def test_atr_skips_pair_with_non_finite_decimal_value() -> None:
    candles = [
        _candle(index=0, close_price="100"),
        _candle(index=1, high_price="NaN", low_price="95"),
        _candle(index=2, high_price="112", low_price="100"),
    ]

    assert atr(candles, period=2) is None


def test_atr_percent_baseline_accepts_decimal_candles() -> None:
    candles = [
        _candle(
            index=index,
            open_price=str(100 + index),
            high_price=str(105 + index),
            low_price=str(95 + index),
            close_price=str(101 + index),
        )
        for index in range(8)
    ]

    result = atr_percent_baseline(
        candles=candles,
        close_price=108.0,
        atr_period=2,
        atr_baseline_window=8,
    )

    assert result is not None
    assert isinstance(result, float)
    assert result > 0


def test_atr_percent_baseline_returns_none_for_invalid_close_price() -> None:
    candles = [
        _candle(index=index)
        for index in range(5)
    ]

    assert (
        atr_percent_baseline(
            candles=candles,
            close_price=0.0,
            atr_period=2,
            atr_baseline_window=5,
        )
        is None
    )
