"""
V11 — Strategy: Momentum Taker.

Detecta movimiento de Binance vs strike y genera señal direccional.
Sin EWMA, sin fair value — pura señal de precio.
"""
from dataclasses import dataclass
from typing import Optional

from .config import (
    Config,
    MOMENTUM_THRESHOLD,
    MAX_ENTRY_PRICE, MIN_ENTRY_PRICE,
    ENTRY_SIZE_USD, MIN_SHARES,
    TAKER_FEE_RATE, PAPER_SLIPPAGE,
    TICK_SIZE, snap_price,
)


@dataclass
class Signal:
    """Señal de momentum detectada."""
    side: str           # "YES" o "NO"
    token_id: str       # Token a comprar
    price: float        # Precio estimado de entrada
    size: float         # Shares a comprar
    size_usd: float     # USD
    move_pct: float     # Movimiento % que disparó la señal
    reason: str = ""    # Por qué se generó


class MomentumStrategy:
    def __init__(self, cfg: Config):
        self.cfg = cfg

    def check_signal(self, price: float, strike: float, t_left: int,
                     token_yes: str, token_no: str,
                     best_ask_yes: float, best_ask_no: float,
                     already_entered: bool) -> Optional[Signal]:
        """Evalúa si hay señal de momentum.

        Returns Signal si hay que entrar, None si no.
        """
        if already_entered:
            return None

        if strike <= 0 or price <= 0:
            return None

        # Timing check (from config, depends on window duration)
        if t_left > self.cfg.signal_start_tleft:
            return None
        if t_left < self.cfg.signal_stop_tleft:
            return None

        # Calcular movimiento
        move = (price - strike) / strike
        abs_move = abs(move)

        if abs_move < self.cfg.momentum_threshold:
            return None

        # Determinar dirección
        if move > 0:
            side = "YES"
            token_id = token_yes
            entry_price = best_ask_yes
        else:
            side = "NO"
            token_id = token_no
            entry_price = best_ask_no

        # Sin precio real del CLOB, no entrar — no inventar precios
        if entry_price <= 0:
            return None

        entry_price = snap_price(entry_price)

        # Filtro de precio (per-asset: ETH/SOL max 0.55, BTC max 0.65)
        if entry_price > self.cfg.max_entry_price:
            return None
        if entry_price < MIN_ENTRY_PRICE:
            return None

        # Confirmación CLOB: para assets donde Binance/Polymarket divergen
        # (ETH, SOL, etc), solo entrar si el CLOB ya refleja nuestra dirección.
        # Precio bajo = mercado no ve el move → señal poco fiable.
        if entry_price < self.cfg.min_ask_confirm:
            return None

        # Calcular tamaño
        n_shares = max(round(self.cfg.entry_size_usd / entry_price, 2), MIN_SHARES)
        cost_usd = round(n_shares * entry_price, 2)

        return Signal(
            side=side,
            token_id=token_id,
            price=entry_price,
            size=n_shares,
            size_usd=cost_usd,
            move_pct=round(move * 100, 4),
            reason=f"momentum {move:+.4%} > threshold {self.cfg.momentum_threshold:.4%}",
        )
