"""sentinel_deployer.py — Reverse sentinel conditional orders.

Deploys STOP_LIMIT orders in the opposite direction of a main position
as tail-risk protection. The sentinel only activates when price reaches
a key reversal level (2× ATR beyond entry in the favorable direction).

Design principles:
  - Sentinel is a CONDITIONAL order, not an active position
  - Zero holding cost — only activates if price reaches the trigger
  - Small position (10-15% of main) — purely insurance, not profit-seeking
  - Deployed at main position's take-profit level (potential reversal zone)

Usage::

    from src.sentinel_deployer import deploy_sentinel, should_deploy

    if should_deploy(regime, adx, main_position):
        sentinel = deploy_sentinel(main_position, atr_value)
"""
from __future__ import annotations
from typing import Any


# ── Deployment thresholds ──────────────────────────────────────────

SENTINEL_VOLUME_RATIO = 0.12       # 12% of main position size
SENTINEL_ATR_OFFSET = 2.0          # Deploy at TP level (2× ATR from entry)
SENTINEL_SL_ATR = 1.5              # Sentinel's own SL (1.5× ATR)
SENTINEL_TP_ATR = 0.5              # Sentinel's TP (0.5× ATR — quick scalp)

# Regimes where sentinel is NOT deployed
NO_SENTINEL_REGIMES = {
    "EXTREME",       # Already in full protection mode
    "VOLATILITY_SPIKE",  # Too volatile for conditional orders
    "FAKE_TREND",    # Unreliable signal
    "TRANSITION",    # No position to protect
    "UNKNOWN",
}


def should_deploy(
    regime: str,
    adx: float,
    main_position: dict | None,
) -> bool:
    """Should a sentinel be deployed for the current main position?

    Sentinel is deployed when:
    1. Regime is WEAK_TREND or STRONG_TREND (trending market)
    2. ADX is in the fragile zone (28-45) — trend exists but can reverse
    3. Main position is open and has profit potential
    4. Regime is NOT in the no-deploy set
    """
    if regime in NO_SENTINEL_REGIMES:
        return False
    if not main_position or not main_position.get("side"):
        return False
    if adx < 25:  # No trend → no sentinel needed
        return False
    if adx > 45:  # Iron trend → sentinel wasteful
        return False
    # Deploy in the fragile zone: ADX 25-45
    return True


def deploy_sentinel(
    main_position: dict,
    atr_value: float,
    *,
    volume_ratio: float = SENTINEL_VOLUME_RATIO,
    atr_offset: float = SENTINEL_ATR_OFFSET,
) -> dict[str, Any] | None:
    """Create a reverse sentinel conditional order.

    The sentinel is a STOP_LIMIT order placed at the main position's
    take-profit level (the most likely reversal zone).

    Args:
        main_position: {side, entry, tp, sl, volume}
        atr_value: Current ATR in price units
        volume_ratio: Fraction of main position size for sentinel
        atr_offset: ATR multiplier for trigger distance

    Returns:
        Sentinel order dict or None if deployment conditions not met.
    """
    main_side = str(main_position.get("side", "") or "").upper()
    if main_side not in ("BUY", "SELL"):
        return None

    main_entry = float(main_position.get("entry", 0) or 0)
    main_tp = float(main_position.get("tp", 0) or 0)
    main_vol = float(main_position.get("volume", 0.01) or 0.01)

    if main_entry <= 0 or main_tp <= 0 or atr_value <= 0:
        return None

    sentinel_side = "SELL" if main_side == "BUY" else "BUY"
    sentinel_vol = round(main_vol * volume_ratio, 3)

    # Sentinel trigger = main position TP (the reversal zone)
    if main_side == "BUY":
        trigger_price = main_tp
        sl_price = round(main_tp + atr_value * SENTINEL_SL_ATR, 2)
        tp_price = round(main_tp - atr_value * SENTINEL_TP_ATR, 2)
    else:
        trigger_price = main_tp
        sl_price = round(main_tp - atr_value * SENTINEL_SL_ATR, 2)
        tp_price = round(main_tp + atr_value * SENTINEL_TP_ATR, 2)

    return {
        "type": "SENTINEL",
        "order_type": "STOP_LIMIT",
        "side": sentinel_side,
        "trigger_price": trigger_price,
        "volume": sentinel_vol,
        "sl": sl_price,
        "tp": tp_price,
        "parent_side": main_side,
        "parent_entry": main_entry,
        "reason": f"reverse_sentinel_at_tp:{main_side}_vol:{sentinel_vol}",
        "_sentinel": True,
    }
