# tests/backtest/test_engine_percent_risk.py
import sys
from pathlib import Path
import pandas as pd
from datetime import datetime

# Añadir raíz del proyecto al path
sys.path.insert(0, str(Path(__file__).parent.parent.parent))

from src.core.engine import Engine
from src.core.strategy import Strategy, Signal
from src.core.trade import TradeStatus
from src.risk.sizing.percent_risk import PercentRiskSizer
from src.risk.stops.fixed_stop import FixedStop


# --------------------------------------------------
# Estrategia dummy
# --------------------------------------------------
class AlwaysBuyStrategy(Strategy):
    """
    Compra en la primera vela y nunca vende.
    El stop debe cerrar la posición.
    """

    def __init__(self):
        super().__init__(name="AlwaysBuy", params={})

    def init_indicators(self, data):
        return data

    def generate_signal(self, idx: int):
        if idx == 0:
            return Signal.BUY
        return Signal.HOLD


# --------------------------------------------------
# Test de integración real
# --------------------------------------------------
def test_engine_percent_risk_with_fixed_stop():
    """
    Verifica que:
    - El size se calcula usando el stop
    - El riesgo por trade ≈ % configurado
    - El stop cierra la posición
    """

    # -----------------------------
    # Datos simulados
    # -----------------------------
    timestamps = pd.date_range(
        start=datetime(2024, 1, 1),
        periods=5,
        freq="1h",
    )

    data = pd.DataFrame(
        {
            "open":  [100, 100, 100, 100, 100],
            "high":  [101, 101, 101, 101, 101],
            "low":   [99,  97,  95,  93,  90],
            "close": [100, 98,  96,  94,  91],  # rompe stop
            "volume": [1, 1, 1, 1, 1],
        },
        index=timestamps,
    )

    # -----------------------------
    # Configuración
    # -----------------------------
    initial_capital = 10_000
    risk_fraction = 0.01  # 1% por trade
    stop_fraction = 0.02  # stop al 2%

    strategy = AlwaysBuyStrategy()

    engine = Engine(
        strategy=strategy,
        initial_capital=initial_capital,
        commission=0.0,
        slippage=0.0,
        position_sizer=PercentRiskSizer(risk_fraction),
        stop_loss=FixedStop(stop_fraction),
    )

    # -----------------------------
    # Ejecutar backtest
    # -----------------------------
    engine.run(data)

    # -----------------------------
    # Assertions
    # -----------------------------
    assert len(engine.trades) == 1

    trade = engine.trades[0]

    # Trade cerrado por stop
    assert trade.status == TradeStatus.CLOSED
    assert trade.exit_reason == "Stop Loss"

    # Riesgo real ≈ riesgo esperado
    expected_risk = initial_capital * risk_fraction
    actual_loss = abs(trade.pnl)

    # Permitimos pequeño error numérico
    assert abs(actual_loss - expected_risk) / expected_risk < 0.05
