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.stops.fixed_stop import FixedStop


class AlwaysBuyStrategy(Strategy):
    """
    Estrategia dummy para testing:
    - Compra en la primera vela
    - Nunca vende
    """

    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


def _build_test_data():
    timestamps = pd.date_range(
        start=datetime(2024, 1, 1),
        periods=5,
        freq="1h"
    )

    return pd.DataFrame(
        {
            "open":   [100, 100, 100, 100, 100],
            "high":   [101, 101, 101, 101, 101],
            "low":    [99,  98,  95,  90,  85],
            "close":  [100, 99,  96,  91,  86],
            "volume": [1, 1, 1, 1, 1],
        },
        index=timestamps
    )


def test_engine_closes_position_on_stop_hit():
    """
    Con stop activo → debe cerrarse por Stop Loss
    """
    data = _build_test_data()
    strategy = AlwaysBuyStrategy()

    engine = Engine(
        strategy=strategy,
        initial_capital=10_000,
        commission=0.0,
        slippage=0.0,
        position_size=1.0,
        stop_loss=FixedStop(0.03)
    )

    engine.run(data)

    assert len(engine.trades) == 1

    trade = engine.trades[0]
    assert trade.status == TradeStatus.CLOSED
    assert trade.exit_reason == "Stop Loss"


def test_engine_closes_position_at_end_without_stop():
    """
    Sin stop → la posición debe cerrarse al final del backtest
    """
    data = _build_test_data()
    strategy = AlwaysBuyStrategy()

    engine = Engine(
        strategy=strategy,
        initial_capital=10_000,
        commission=0.0,
        slippage=0.0,
        position_size=1.0,
        stop_loss=None
    )

    engine.run(data)

    assert len(engine.trades) == 1

    trade = engine.trades[0]
    assert trade.status == TradeStatus.CLOSED
    assert trade.exit_reason == "End of backtest"
