# src/risk/stops/trailing_stop.py
import pandas as pd
from src.risk.stops.base import StopLoss
from src.core.trade import TradeType, Position


class TrailingStop(StopLoss):
    """
    Trailing Stop porcentual basado en el precio de cierre.

    - LONG: el stop solo sube
    - SHORT: el stop solo baja
    """

    def __init__(self, trailing_fraction: float):
        """
        Args:
            trailing_fraction: ej 0.05 = 5%
        """
        if trailing_fraction <= 0 or trailing_fraction >= 1:
            raise ValueError("trailing_fraction debe estar entre 0 y 1")

        self.trailing_fraction = trailing_fraction

    def get_stop_price(
        self,
        *,
        data: pd.DataFrame,
        idx: int,
        entry_price: float,
        trade_type: TradeType
    ) -> float:
        """
        Stop inicial al abrir la posición
        """
        if trade_type == TradeType.LONG:
            return entry_price * (1 - self.trailing_fraction)

        elif trade_type == TradeType.SHORT:
            return entry_price * (1 + self.trailing_fraction)

        else:
            raise ValueError(f"TradeType no soportado: {trade_type}")

    def update_stop(
        self,
        *,
        data: pd.DataFrame,
        idx: int,
        position: Position
    ) -> float | None:
        """
        Calcula un nuevo stop si el precio ha mejorado.
        Devuelve None si el stop no debe moverse.
        """
        current_price = data.iloc[idx]["close"]

        if position.trade_type == TradeType.LONG:
            candidate = current_price * (1 - self.trailing_fraction)

            if position.stop_price is None or candidate > position.stop_price:
                return candidate

        elif position.trade_type == TradeType.SHORT:
            candidate = current_price * (1 + self.trailing_fraction)

            if position.stop_price is None or candidate < position.stop_price:
                return candidate

        return None
