# app/src/trading/execution/constants.py

from __future__ import annotations


# ----- Runtime autonomous actions -----

RUNTIME_ACTION_COOLDOWN_SECONDS = 30
RUNTIME_EXIT_CONFIDENCE_THRESHOLD = 0.75

RUNTIME_ACTION_SKIPPED = "RUNTIME_ACTION_SKIPPED"
RUNTIME_ACTION_COOLDOWN = "RUNTIME_ACTION_COOLDOWN"
RUNTIME_ACTION_UNKNOWN = "RUNTIME_ACTION_UNKNOWN"


# ----- Auto / execution states -----

AUTO_STATUS_RUNNING = "RUNNING"

EXECUTION_STATUS_RUNNING = "RUNNING"
EXECUTION_DECISION_READY = "READY"


# ----- Position sides -----

POSITION_SIDE_NONE = "NONE"
POSITION_SIDE_LONG = "LONG"
POSITION_SIDE_SHORT = "SHORT"


# ----- Signals -----

SIGNAL_BUY = "BUY"
SIGNAL_SELL = "SELL"


# ----- Execution actions -----

EXECUTION_ACTION_NONE = "NONE"
EXECUTION_ACTION_OPEN_LONG = "OPEN_LONG"
EXECUTION_ACTION_OPEN_SHORT = "OPEN_SHORT"
EXECUTION_ACTION_CLOSE = "CLOSE"
EXECUTION_ACTION_FLIP_BLOCKED = "FLIP_BLOCKED"

EXECUTION_ACTION_FORCE_CLOSE_PREFIX = "FORCE_CLOSE_"


# -----Execution types -----

EXECUTION_TYPE_ENTRY = "ENTRY"
EXECUTION_TYPE_EXIT = "EXIT"
EXECUTION_TYPE_ENTRY_REJECTED = "ENTRY_REJECTED"
EXECUTION_TYPE_RUNTIME_ACTION = "RUNTIME_ACTION"

EXECUTION_TYPE_FLIP = "FLIP"
EXECUTION_TYPE_FLIP_REJECTED = "FLIP_REJECTED"
EXECUTION_TYPE_FLIP_BLOCKED = "FLIP_BLOCKED"


# ----- Execution reasons -----

EXECUTION_REASON_MANUAL = "MANUAL"
EXECUTION_REASON_AUTONOMOUS_EXIT = "AUTONOMOUS_EXIT"


# ----- Pricing modes -----

PRICING_ENTRY_MODE = "ask_for_long_bid_for_short"
PRICING_EXIT_MODE = "bid_for_long_exit_ask_for_short_exit"
PRICING_FLIP_MODE = "exit_by_side_then_entry_by_side"


# ----- Execution limits -----

EXECUTION_MAX_CONSECUTIVE_LOSSES = 5

# ----- Execution quality -----

EXECUTION_QUALITY_BLOCKED = "BLOCKED"
EXECUTION_QUALITY_WARNING = "WARNING"


# ----- Autonomous management -----

AUTONOMOUS_ACTION_HOLD = "HOLD"
AUTONOMOUS_ACTION_WATCH = "WATCH"
AUTONOMOUS_ACTION_PROTECT = "PROTECT"
AUTONOMOUS_ACTION_REDUCE = "REDUCE"
AUTONOMOUS_ACTION_EXIT = "EXIT"
AUTONOMOUS_ACTION_EXIT_BLOCKED = "EXIT_BLOCKED"

AUTONOMOUS_EXIT_CONFIDENCE_THRESHOLD = 0.75
AUTONOMOUS_AGGRESSIVE_EXIT_CONFIDENCE_THRESHOLD = 0.65


# ----- Position exit signals -----

POSITION_EXIT_SIGNAL_HOLD = "HOLD"
POSITION_EXIT_SIGNAL_WATCH = "WATCH"
POSITION_EXIT_SIGNAL_REDUCE_OR_PROTECT = "REDUCE_OR_PROTECT"
POSITION_EXIT_SIGNAL_EXIT = "EXIT"

POSITION_EXIT_SIGNAL_EXIT_CONFIDENCE = 0.75
POSITION_EXIT_SIGNAL_PROTECT_CONFIDENCE = 0.50
POSITION_EXIT_SIGNAL_WATCH_CONFIDENCE = 0.30


# ----- Position pressure / trend -----

POSITION_PRESSURE_HIGH_LOSS = "HIGH_LOSS"
POSITION_PRESSURE_LOSS = "LOSS"

POSITION_TREND_AGAINST = "AGAINST"


# ----- Position risk -----

POSITION_RISK_HIGH = "HIGH"
POSITION_RISK_ELEVATED = "ELEVATED"
POSITION_RISK_MODERATE = "MODERATE"
POSITION_RISK_LOW = "LOW"


# ----- Position health -----

POSITION_HEALTH_HEALTHY = "HEALTHY"
POSITION_HEALTH_WATCH = "WATCH"
POSITION_HEALTH_PRESSURE = "PRESSURE"
POSITION_HEALTH_DANGER = "DANGER"
POSITION_HEALTH_UNKNOWN = "UNKNOWN"

POSITION_HEALTH_PNL_HARD_LOSS_PERCENT = -1.0
POSITION_HEALTH_PNL_HIGH_PRESSURE_PERCENT = -0.6
POSITION_HEALTH_PNL_PRESSURE_PERCENT = -0.25
POSITION_HEALTH_PNL_GOOD_PROFIT_PERCENT = 0.8

POSITION_EXIT_PRESSURE_LOSS_PERCENT = -0.4


# ----- Position stop-loss ratios -----

POSITION_STOP_LOSS_RATIO_WATCH = 0.50
POSITION_STOP_LOSS_RATIO_WARNING = 0.55
POSITION_STOP_LOSS_RATIO_CRITICAL = 0.80


# ----- Position momentum / candle thresholds -----

POSITION_MOMENTUM_STRONG = 0.80

POSITION_CURRENT_INTERVAL_ADVERSE_MOVE_PERCENT = 0.04
POSITION_CURRENT_INTERVAL_RISK_MOVE_PERCENT = 0.12


# ----- Position lifecycle / semantics -----

POSITION_LIFECYCLE_NEW_SECONDS = 60
POSITION_LIFECYCLE_ACTIVE_SECONDS = 300
POSITION_LIFECYCLE_MATURE_SECONDS = 900

POSITION_EXIT_DAMPING_NEW_SECONDS = 300
POSITION_EXIT_DAMPING_MATURE_SECONDS = 900
POSITION_EXIT_DAMPING_NEW_MULTIPLIER = 0.45
POSITION_EXIT_DAMPING_MATURE_MULTIPLIER = 0.70

POSITION_GIVEBACK_HIGH_PERCENT = 70
POSITION_GIVEBACK_MEDIUM_PERCENT = 45
POSITION_GIVEBACK_LOW_PERCENT = 25

POSITION_REVERSAL_HIGH_GIVEBACK_PERCENT = 45
POSITION_REVERSAL_ELEVATED_GIVEBACK_PERCENT = 25

POSITION_STALL_EARLY_SECONDS = 300
POSITION_STALL_DEVELOPING_SECONDS = 600
POSITION_STALL_CONFIRMED_SECONDS = 900
POSITION_STALL_LOW_PROGRESS_PNL_PERCENT = 0.25
POSITION_STALL_LOW_PROGRESS_MFE_PERCENT = 0.35
POSITION_STALL_ADVERSE_MAE_PERCENT = -0.35


# ----- Market / flip filters -----

MARKET_VOLATILITY_HIGH_STATES = {"HIGH", "HIGH_VOLATILITY"}

MARKET_STATE_FLIP_BLOCKED = {
    "RANGE",
    "HIGH_VOLATILITY",
    "LOW_VOLATILITY",
    "UNKNOWN",
    "",
}

MARKET_PHASE_FLIP_BLOCKED = {
    "RANGE",
    "UNKNOWN",
    "",
}

FLIP_MIN_EXECUTION_CONFIDENCE = 0.70
FLIP_MIN_HTF_CONFIRMATION_SCORE = 0.65
FLIP_BREAKOUT_CONFIDENCE_THRESHOLD = 0.85

# ----- Asset-specific thresholds -----

DEFAULT_POSITION_THRESHOLDS = {
    "health": {
        "high_loss": -0.75,
        "loss": -0.40,
        "profit": 0.45,
        "strong_profit": 1.20,
    },
    "exit": {
        "min_hold": 1500,
        "neutral_min_hold": 1800,
        "neutral_band": 0.40,
        "normal_pullback": -0.45,
        "hard_loss": -0.90,
        "noisy_min_hold": 600,
        "noisy_loss_exit": -0.30,
        "noisy_profit_giveback": 35,
        "clean_giveback_min_peak": 1.10,
        "clean_giveback_percent": 55,
        "noisy_giveback_min_peak": 0.40,
        "noisy_giveback_percent": 35,
    },
}


POSITION_THRESHOLDS_BY_ASSET = {
    "BTC": {
        "health": {
            "high_loss": -0.65,
            "loss": -0.30,
            "profit": 0.30,
            "strong_profit": 0.90,
        },
        "exit": {
            "min_hold": 1200,
            "neutral_min_hold": 1500,
            "neutral_band": 0.30,
            "normal_pullback": -0.35,
            "hard_loss": -0.75,
            "noisy_min_hold": 600,
            "noisy_loss_exit": -0.25,
            "noisy_profit_giveback": 35,
            "clean_giveback_min_peak": 1.20,
            "clean_giveback_percent": 55,
            "noisy_giveback_min_peak": 0.45,
            "noisy_giveback_percent": 35,
        },
    },
    "ETH": {
        "health": {
            "high_loss": -0.85,
            "loss": -0.45,
            "profit": 0.40,
            "strong_profit": 1.10,
        },
        "exit": {
            "min_hold": 1500,
            "neutral_min_hold": 1800,
            "neutral_band": 0.40,
            "normal_pullback": -0.45,
            "hard_loss": -0.85,
            "noisy_min_hold": 600,
            "noisy_loss_exit": -0.30,
            "noisy_profit_giveback": 35,
            "clean_giveback_min_peak": 1.10,
            "clean_giveback_percent": 55,
            "noisy_giveback_min_peak": 0.40,
            "noisy_giveback_percent": 35,
        },
    },
    "LTC": {
        "health": {
            "high_loss": -1.00,
            "loss": -0.55,
            "profit": 0.55,
            "strong_profit": 1.35,
        },
        "exit": {
            "min_hold": 1800,
            "neutral_min_hold": 2100,
            "neutral_band": 0.45,
            "normal_pullback": -0.55,
            "hard_loss": -1.00,
            "noisy_min_hold": 600,
            "noisy_loss_exit": -0.40,
            "noisy_profit_giveback": 35,
            "clean_giveback_min_peak": 1.20,
            "clean_giveback_percent": 55,
            "noisy_giveback_min_peak": 0.45,
            "noisy_giveback_percent": 35,
        },
    },
    "XRP": {
        "health": {
            "high_loss": -1.10,
            "loss": -0.60,
            "profit": 0.60,
            "strong_profit": 1.50,
        },
        "exit": {
            "min_hold": 1800,
            "neutral_min_hold": 2100,
            "neutral_band": 0.50,
            "normal_pullback": -0.60,
            "hard_loss": -1.10,
            "noisy_min_hold": 600,
            "noisy_loss_exit": -0.40,
            "noisy_profit_giveback": 35,
            "clean_giveback_min_peak": 1.20,
            "clean_giveback_percent": 55,
            "noisy_giveback_min_peak": 0.45,
            "noisy_giveback_percent": 35,
        },
    },
}


# ---- Helpers -----

def asset_symbol(symbol: str | None) -> str:
    if not symbol:
        return ""

    base = str(symbol).split("_", 1)[0].upper()

    if "/" in base:
        return base.split("/", 1)[0]

    for suffix in ("USDT", "USD", "EUR", "BTC"):
        if base.endswith(suffix) and len(base) > len(suffix):
            return base[: -len(suffix)]

    return base


def get_position_thresholds(symbol: str | None) -> dict[str, dict[str, float]]:
    asset = asset_symbol(symbol)

    return POSITION_THRESHOLDS_BY_ASSET.get(
        asset,
        DEFAULT_POSITION_THRESHOLDS,
    )


def get_position_health_thresholds(symbol: str | None) -> dict[str, float]:
    return get_position_thresholds(symbol)["health"]


def get_position_exit_thresholds(symbol: str | None) -> dict[str, float]:
    return get_position_thresholds(symbol)["exit"]


def build_flip_action(
    old_side: str,
    new_side: str,
) -> str:
    return f"FLIP_{old_side}_TO_{new_side}"