"""
Unit tests for VolumeEngine and VolatilityEngine
"""
import pytest
import numpy as np
from python.analytics.volume_engine import VolumeEngine
from python.analytics.volatility_engine import VolatilityEngine

def test_rvol_calculation():
    vol = np.array([1000] * 20 + [2500], dtype=float)
    rvol = VolumeEngine.calculate_rvol(vol, lookback=20)
    assert round(rvol, 2) == 2.50

def test_obv_calculation():
    close = np.array([100, 102, 101, 105], dtype=float)
    volume = np.array([1000, 1500, 800, 2000], dtype=float)
    obv = VolumeEngine.calculate_obv(close, volume)
    assert obv[0] == 0
    assert obv[1] == 1500
    assert obv[2] == 700   # 1500 - 800
    assert obv[3] == 2700  # 700 + 2000

def test_mfi_calculation():
    h = np.linspace(100, 120, 20)
    l = np.linspace(95, 115, 20)
    c = np.linspace(98, 118, 20)
    v = np.full(20, 5000.0)
    mfi = VolumeEngine.calculate_mfi(h, l, c, v, period=14)
    assert not np.isnan(mfi[-1])
    assert 0 <= mfi[-1] <= 100

def test_bollinger_bands():
    close = np.linspace(100, 110, 30)
    mid, up, low, bw = VolatilityEngine.calculate_bollinger_bands(close, period=20, num_std=2.0)
    assert not np.isnan(mid[-1])
    assert up[-1] > mid[-1] > low[-1]
    assert bw[-1] > 0

def test_keltner_channels_and_squeeze():
    close = np.full(30, 100.0)
    high = close + 1.0
    low = close - 1.0
    kc_mid, kc_up, kc_low = VolatilityEngine.calculate_keltner_channels(high, low, close, 20, 10, 1.5)
    assert kc_up[-1] > kc_low[-1]

    # Test squeeze detection
    bb_up = np.array([101.0])
    bb_low = np.array([99.0])
    kc_u = np.array([102.0])
    kc_l = np.array([98.0])
    sq = VolatilityEngine.detect_volatility_squeeze(bb_up, bb_low, kc_u, kc_l)
    assert sq["squeeze_active"] is True
    assert sq["state"] == "COMPRESSION"
