import sys
import os
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

import pandas as pd
from demo import generate_synthetic_ohlcv
from core import indicators as ind
from core import candlestick_patterns as candles
from core import price_action as pa
from core.confidence_engine import calculate_confidence
from config import settings as cfg


def _df():
    return generate_synthetic_ohlcv(n=250)


def test_indicators_no_crash_and_correct_length():
    df = _df()
    all_ind = ind.compute_all(df)
    for name, val in all_ind.items():
        length = len(val) if isinstance(val, (pd.Series, pd.DataFrame)) else None
        assert length == len(df), f"{name} length mismatch"


def test_rsi_bounds():
    df = _df()
    rsi = ind.rsi(df["close"]).dropna()
    assert (rsi >= 0).all() and (rsi <= 100).all()


def test_candlestick_patterns_shape():
    df = _df()
    patterns = candles.detect_all(df)
    assert len(patterns) == len(df)
    assert set(patterns.values.flatten()).issubset({-1, 0, 1})


def test_market_structure_runs():
    df = _df()
    structure = pa.market_structure(df)
    assert structure["trend"] in ("uptrend", "downtrend", "ranging")


def test_confidence_engine_never_exceeds_100():
    df = _df()
    decision = calculate_confidence(df, "TEST", option_chain_score=100, news_score=100, global_market_score=100)
    assert decision.total_confidence <= 100.01


def test_confidence_engine_respects_threshold():
    df = _df()
    decision = calculate_confidence(df, "TEST")
    if decision.should_trade:
        assert decision.total_confidence >= cfg.MIN_CONFIDENCE_TO_TRADE
    else:
        assert decision.total_confidence < cfg.MIN_CONFIDENCE_TO_TRADE
        assert decision.direction == "NONE"


def test_risk_reward_ratio_when_trading():
    df = _df()
    decision = calculate_confidence(df, "TEST", option_chain_score=100, news_score=100, global_market_score=100)
    if decision.should_trade:
        risk = abs(decision.entry - decision.stop_loss)
        reward = abs(decision.target - decision.entry)
        assert abs(reward / risk - cfg.RISK_REWARD_RATIO) < 0.01


if __name__ == "__main__":
    import pytest
    pytest.main([__file__, "-v"])
