# tests/backtest/test_engine_sizing.py
import pytest

import sys
from pathlib import Path
import pandas as pd
from datetime import datetime, timedelta

# 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.risk.sizing.fixed import FixedPositionSizer

class BuyOnceStrategy(Strategy):
    """
    Estrategia dummy:
    - BUY en la primera vela
    - SELL en la segunda
    """

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

    def init_indicators(self, data: pd.DataFrame) -> pd.DataFrame:
        return data
    
    def generate_signal(self, idx: int) -> Signal:
        if idx == 0:
            return Signal.BUY
        if idx == 1:
            return Signal.SELL
        return Signal.HOLD
    
def test_engine_uses_fixed_position_sizer():
    """
    El engine debe usar el PositionSizer
    y NO el position_size_fraction por defecto.
    """

    # -------------------------
    # Datos dummy
    # -------------------------
    dates = [
        datetime(2024, 1, 1),
        datetime(2024, 1, 2),
        datetime(2024, 1, 3),
    ]

    data = pd.DataFrame(
        {
            "open": [100, 100, 100],
            "high": [100, 100, 100],
            "low": [100, 100, 100],
            "close": [100, 100, 100],
            "volume": [1, 1, 1],
        },
        index=dates,
    )

    # -------------------------
    # Engine + Sizer
    # -------------------------
    strategy = BuyOnceStrategy()

    sizer = FixedPositionSizer(capital_fraction=0.5)

    engine = Engine(
        strategy=strategy,
        initial_capital=10000,
        commission=0.0,
        slippage=0.0,
        position_size=0.95,
        position_sizer=sizer
    )

    results = engine.run(data)
    # -------------------------
    # Validaciones
    # -------------------------
    trades = results["trades"]
    assert len(trades) == 1

    trade = trades[0]

    invested_value = trade.entry_price * trade.size

    # Esperamos ~50% del capital
    assert invested_value == pytest.approx(5000, rel=1e-3)

    # Sanity check
    assert invested_value < 9500  # NO debe usar 95%