# app/tests/unit/trading/market_analysis/test_structure_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.models import MarketStructure
from src.trading.market_analysis.structure import market_structure


def _structure_candles(
    *,
    highs: list[float],
    lows: list[float],
) -> list[Candle]:
    candles: list[Candle] = []

    for index, (high, low) in enumerate(zip(highs, lows)):
        midpoint = (high + low) / 2

        candles.append(
            _candle(
                index=index,
                open_price=str(midpoint),
                high_price=str(high),
                low_price=str(low),
                close_price=str(midpoint),
            )
        )

    return candles


def test_market_structure_detects_higher_highs_and_higher_lows() -> None:
    candles = _structure_candles(
        highs=[2, 4, 3, 5, 4, 6, 5, 7, 6, 5],
        lows=[1, 0, 1, 0.5, 1.5, 1, 2, 1.5, 2.5, 2],
    )

    result, reason = market_structure(
        candles,
        atr_percent=0.30,
        structure_window=10,
        structure_swing_left=1,
        structure_swing_right=1,
    )

    assert result == MarketStructure.HH_HL
    assert reason.startswith("HIGHER_HIGH_HIGHER_LOW:")


def test_market_structure_detects_lower_highs_and_lower_lows() -> None:
    candles = _structure_candles(
        highs=[
            8.0,
            10.0,
            9.0,
            9.5,
            8.5,
            9.0,
            8.0,
            8.5,
            7.5,
            7.0,
        ],
        lows=[
            7.0,
            6.0,
            7.0,
            5.5,
            6.5,
            5.0,
            6.0,
            4.5,
            5.5,
            5.0,
        ],
    )

    result, reason = market_structure(
        candles,
        atr_percent=0.30,
        structure_window=10,
        structure_swing_left=1,
        structure_swing_right=1,
    )

    assert result == MarketStructure.LH_LL
    assert reason.startswith("LOWER_HIGH_LOWER_LOW:")


def test_market_structure_detects_mixed_structure() -> None:
    candles = _structure_candles(
        highs=[2, 4, 3, 5, 4, 6, 5, 7, 6, 5],
        lows=[5, 4, 5, 3, 4, 2, 3, 1, 2, 1.5],
    )

    result, reason = market_structure(
        candles,
        atr_percent=0.30,
        structure_window=10,
        structure_swing_left=1,
        structure_swing_right=1,
    )

    assert result == MarketStructure.MIXED
    assert reason.startswith("MIXED_MARKET_STRUCTURE:")


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

    result, reason = market_structure(
        candles,
        structure_window=10,
        structure_swing_left=1,
        structure_swing_right=1,
    )

    assert result == MarketStructure.UNKNOWN
    assert reason == "STRUCTURE_NOT_ENOUGH_CANDLES"


def test_market_structure_accepts_decimal_candle_values() -> None:
    candles = _structure_candles(
        highs=[2, 4, 3, 5, 4, 6, 5, 7, 6, 5],
        lows=[1, 0, 1, 0.5, 1.5, 1, 2, 1.5, 2.5, 2],
    )

    result, _ = market_structure(
        candles,
        atr_percent=0.30,
        structure_window=10,
        structure_swing_left=1,
        structure_swing_right=1,
    )

    assert result == MarketStructure.HH_HL
