"""Fixed, opt-in close-triggered entry-loss replay for the preregistered experiment."""
from __future__ import annotations

import numpy as np

from strategies.strategy_mlp_scores import _score_to_signals


def entry_loss_signals(df, params, stoch_peak, close, high, *, loss_fraction=None):
    """Preserve canonical ordering and trail; None is the disabled control."""
    if loss_fraction not in (None, 0.10):
        raise ValueError('Only disabled control or preregistered 10% is supported')
    op = _score_to_signals(df, params, stoch_peak, close, high, return_opportunities=True)
    n = len(df)
    result = {key: np.zeros(n, dtype=bool) for key in (
        'position', 'execute_entry', 'execute_exit', 'score_exit_flag',
        'trailing_exit_flag', 'entry_loss_flag')}
    result['entry_signal_close'] = np.full(n, np.nan)
    result['trade_high'] = np.full(n, np.nan)
    result['entry_loss_overshoot_pct'] = np.full(n, np.nan)
    position, use_raw, fill_bar = False, False, -1
    entry_price = trade_high = np.nan
    for t in range(n):
        if position:
            if t != fill_bar:
                trade_high = max(trade_high, high[t])
            score_exit = bool(op['fallback'][t] if use_raw else op['exit'][t])
            trail_exit = bool(op['trail'] > 0 and close[t] <= trade_high * (1 - op['trail']))
            loss_exit = bool(loss_fraction is not None and close[t] <= entry_price * (1 - loss_fraction))
            result['entry_signal_close'][t] = entry_price
            result['trade_high'][t] = trade_high
            result['score_exit_flag'][t] = score_exit
            result['trailing_exit_flag'][t] = trail_exit
            result['entry_loss_flag'][t] = loss_exit
            if loss_exit:
                result['entry_loss_overshoot_pct'][t] = (1 - loss_fraction - close[t] / entry_price) * 100
            if op['time_ok'][t] and (score_exit or trail_exit or loss_exit):
                result['execute_exit'][t] = True
                position, use_raw, fill_bar = False, False, -1
        elif op['entry'][t] and op['time_ok'][t]:
            position = True
            result['execute_entry'][t] = True
            entry_price = trade_high = close[t]
            fill_bar = t + 1
            use_raw = bool(op['dead_zone'] and op['score_exit'][t] < op['exit_threshold'])
            result['entry_signal_close'][t] = entry_price
            result['trade_high'][t] = trade_high
        result['position'][t] = position
    for key, values in result.items():
        df[key] = values.astype(int) if key == 'position' else values
    return df
