"""Unit tests for market feature calculations."""

from libs.oracle_client.models import PriceBar

BARS = [
    PriceBar(date="2026-01-26", open=227.5, high=230.0, low=226.0, close=229.5, volume=48000000),
    PriceBar(date="2026-01-27", open=229.0, high=232.0, low=228.0, close=231.0, volume=55000000),
    PriceBar(date="2026-01-28", open=231.5, high=234.0, low=230.0, close=233.0, volume=60000000),
    PriceBar(date="2026-01-29", open=240.0, high=245.0, low=238.0, close=243.0, volume=120000000),
]


def test_reaction_day_return():
    from libs.features.market_features import reaction_day_return
    r = reaction_day_return(BARS, "2026-01-29")
    assert r is not None
    expected = (243.0 - 233.0) / 233.0
    assert abs(r - expected) < 1e-6


def test_reaction_day_return_missing_date():
    from libs.features.market_features import reaction_day_return
    assert reaction_day_return(BARS, "2026-12-01") is None


def test_volume_ratio_20d():
    from libs.features.market_features import volume_ratio_20d
    r = volume_ratio_20d(BARS, "2026-01-29")
    assert r is not None
    avg = (48000000 + 55000000 + 60000000) / 3
    assert abs(r - 120000000 / avg) < 1e-3


def test_close_location():
    from libs.features.market_features import close_location
    bar = PriceBar(date="2026-01-29", open=240.0, high=245.0, low=238.0, close=243.0, volume=120000000)
    cl = close_location(bar)
    assert cl is not None
    expected = (243.0 - 238.0) / (245.0 - 238.0)
    assert abs(cl - expected) < 1e-6


def test_close_location_zero_range():
    from libs.features.market_features import close_location
    bar = PriceBar(date="2026-01-29", open=100.0, high=100.0, low=100.0, close=100.0, volume=1000)
    assert close_location(bar) is None


def test_gap_size():
    from libs.features.market_features import gap_size
    g = gap_size(BARS, "2026-01-29")
    assert g is not None
    expected = (240.0 - 233.0) / 233.0
    assert abs(g - expected) < 1e-6


def test_atr_14():
    from libs.features.market_features import atr_14
    # With fewer than 14 bars, should still return avg TR
    r = atr_14(BARS)
    assert r is not None
    assert r > 0


def test_compute_market_features_dict():
    from libs.features.market_features import compute_market_features
    features = compute_market_features(BARS, "2026-01-29")
    assert "reaction_day_return" in features
    assert "volume_ratio_20d" in features
    assert "gap_size" in features
    assert "atr_14" in features
    assert "close_location" in features
