"""INVERTED_TP_SKIP (2026-06-16): un wick transitorio puo' far calcolare alla strategia
un tp dal lato SBAGLIATO dell'entry (es. donchian: segnale su barra wickata, entry al
prezzo recuperato gia' oltre il proprio tp). L'exit intrabar `bar_high>=tp` (long) /
`bar_low<=tp` (short) scatterebbe a bars_held=0 in PERDITA, con churn di fee e TP
reduce-only respinti. Verita' d'esecuzione, zero parametri: se il TP e' gia' sfondato
all'ingresso il segnale e' malformato -> NON si apre. TP dal lato giusto (o assente)
-> comportamento storico."""
from src.live.strategy_worker import StrategyWorker
from src.live.strategy_loader import load_strategy
from src.strategies.base import Signal


def _worker(tmp):
    w = StrategyWorker(strategy=load_strategy("MR02_donchian_fade"), asset="BTC", tf="15m",
                       capital=1000.0, data_dir=tmp)
    w._notify = lambda *a, **k: None
    return w


def test_long_inverted_tp_skipped(tmp_path):
    # long con tp SOTTO l'entry (caso reale 16-06: entry 66780, tp 66189) -> no entry
    w = _worker(tmp_path)
    sig = Signal(idx=119, direction=1, entry_price=66780.0,
                 metadata={"tp": 66189.25, "sl": 64218.21, "max_bars": 24})
    w._open_position(sig, 66780.0, current_ts=1)
    assert not w.in_position
    assert w.tp == 0.0


def test_short_inverted_tp_skipped(tmp_path):
    # short con tp SOPRA l'entry -> il TP intrabar `bar_low<=tp` scatterebbe subito -> no entry
    w = _worker(tmp_path)
    sig = Signal(idx=119, direction=-1, entry_price=100.0,
                 metadata={"tp": 105.0, "sl": 110.0, "max_bars": 24})
    w._open_position(sig, 100.0, current_ts=1)
    assert not w.in_position


def test_long_valid_tp_opens(tmp_path):
    # controllo positivo: long con tp SOPRA l'entry -> apre normalmente
    w = _worker(tmp_path)
    sig = Signal(idx=119, direction=1, entry_price=100.0,
                 metadata={"tp": 103.0, "sl": 98.0, "max_bars": 24})
    w._open_position(sig, 100.0, current_ts=1)
    assert w.in_position
    assert w.direction == 1
    assert w.tp == 103.0


def test_short_valid_tp_opens(tmp_path):
    # controllo positivo: short con tp SOTTO l'entry -> apre normalmente
    w = _worker(tmp_path)
    sig = Signal(idx=119, direction=-1, entry_price=100.0,
                 metadata={"tp": 97.0, "sl": 102.0, "max_bars": 24})
    w._open_position(sig, 100.0, current_ts=1)
    assert w.in_position
    assert w.direction == -1


def test_no_tp_opens(tmp_path):
    # segnale senza tp (strategie a orizzonte puro, es. SH01) -> il guard non si applica
    w = _worker(tmp_path)
    sig = Signal(idx=119, direction=1, entry_price=100.0, metadata={"max_bars": 12})
    w._open_position(sig, 100.0, current_ts=1)
    assert w.in_position


def test_inverted_skip_deduped_per_bar(tmp_path):
    # stesso bar_ts -> un solo log INVERTED_TP_SKIP; non blocca un bar successivo valido
    w = _worker(tmp_path)
    sig = Signal(idx=119, direction=1, entry_price=66780.0,
                 metadata={"tp": 66189.25, "max_bars": 24})
    w._open_position(sig, 66780.0, current_ts=1)
    w._open_position(sig, 66780.0, current_ts=1)
    assert not w.in_position
    assert w._inverted_tp_ts == 1
