"""Risk tier auto-adjustment controller for the autonomous trading engine.

Pure computation module — no DB access. Persistence of tier changes is
handled by the caller. All methods operate on values passed in as
arguments and return deterministic results.

Tier ordering: conservative → moderate → aggressive
"""

from __future__ import annotations

from services.trading.models import PerformanceMetrics

# Ordered from lowest to highest risk.
TIER_ORDER: list[str] = ["conservative", "moderate", "aggressive"]


class RiskTierController:
    """Evaluates performance metrics and determines whether the active
    risk tier should change.

    Downgrade conditions (any one triggers a downgrade by one level):
    - Trailing 30-day win rate < 40%
    - Current drawdown > 15%

    Upgrade conditions (ALL must be true):
    - Trailing 30-day win rate > 55%
    - Reserve pool > 20% of total portfolio
    - Current drawdown < 5%
    """

    def __init__(self) -> None:
        # No configuration needed — uses TIER_ORDER for ordering.
        pass

    def evaluate(
        self,
        current_tier: str,
        metrics: PerformanceMetrics,
        reserve_pct: float,
    ) -> str | None:
        """Evaluate whether the tier should change based on performance.

        Parameters
        ----------
        current_tier:
            The currently active tier name (e.g. ``"moderate"``).
        metrics:
            Latest portfolio performance metrics.
        reserve_pct:
            Reserve pool balance as a fraction of total portfolio value
            (e.g. 0.25 means 25%).

        Returns
        -------
        str | None
            The new tier name if a change is needed, or ``None`` if the
            current tier should remain.
        """
        current_index = TIER_ORDER.index(current_tier)

        # --- Downgrade check (any condition triggers) ---
        should_downgrade = (
            metrics.win_rate < 0.40 or metrics.current_drawdown_pct > 0.15
        )

        if should_downgrade:
            if current_index > 0:
                return TIER_ORDER[current_index - 1]
            # Already at the lowest tier — no change.
            return None

        # --- Upgrade check (all conditions must be true) ---
        should_upgrade = (
            metrics.win_rate > 0.55
            and reserve_pct > 0.20
            and metrics.current_drawdown_pct < 0.05
        )

        if should_upgrade:
            if current_index < len(TIER_ORDER) - 1:
                return TIER_ORDER[current_index + 1]
            # Already at the highest tier — no change.
            return None

        # Neither condition met — stay at current tier.
        return None
