"""Risk Management Agent — the final gate. Computes entry, stop-loss, profit
targets, risk-to-reward, and position size, then approves or rejects the
setup against configured risk rules. Rejections include explicit reasons."""
from .base import Agent, AgentResult
from ..config import settings


class RiskManagerAgent(Agent):
    name = "risk_manager"

    def run(self, context: dict) -> AgentResult:
        price = context["quote"]["price"]
        direction = context["direction"]
        atr_val = context["atr"] or price * 0.02
        confidence = context["confidence"]
        probability = context["probability"]
        open_risk_usd = context.get("open_risk_usd", 0.0)

        atr_mult = float(context.get("atr_mult", 1.5))
        sign = 1 if direction in ("CALL", "BUY") else -1
        entry = round(price, 2)
        stop = round(entry - sign * atr_mult * atr_val, 2)
        risk_per_share = abs(entry - stop)
        target1 = round(entry + sign * 2 * risk_per_share, 2)
        target2 = round(entry + sign * 3 * risk_per_share, 2)
        rr = round(abs(target1 - entry) / risk_per_share, 2) if risk_per_share else 0.0

        # Regime-aware sizing: high-volatility regimes halve the risk budget
        risk_scale = float(context.get("risk_scale", 1.0))
        max_risk_usd = settings.ACCOUNT_EQUITY * settings.MAX_RISK_PER_TRADE_PCT / 100 * risk_scale
        position_size = int(max_risk_usd / risk_per_share) if risk_per_share else 0
        # Cap position at 20% of equity notional
        max_shares_notional = int(settings.ACCOUNT_EQUITY * 0.2 / entry) if entry else 0
        position_size = max(0, min(position_size, max_shares_notional))
        actual_risk_usd = round(position_size * risk_per_share, 2)

        reasons: list[str] = []
        if confidence < settings.MIN_CONFIDENCE:
            reasons.append(f"Confidence {confidence} below minimum {settings.MIN_CONFIDENCE}")
        if probability < settings.MIN_PROBABILITY:
            reasons.append(f"Probability {probability}% below minimum {settings.MIN_PROBABILITY}%")
        if rr < settings.MIN_RISK_REWARD:
            reasons.append(f"Risk/reward {rr} below minimum {settings.MIN_RISK_REWARD}")
        if position_size <= 0:
            reasons.append("Position size computes to zero — risk per share too large")
        max_daily_risk = settings.ACCOUNT_EQUITY * settings.MAX_DAILY_RISK_PCT / 100
        if open_risk_usd + actual_risk_usd > max_daily_risk:
            reasons.append(
                f"Would exceed max daily risk (${open_risk_usd + actual_risk_usd:,.0f} > ${max_daily_risk:,.0f})"
            )

        # Earnings blackout (audit Phase 7: earnings-event restrictions)
        days_to_earnings = context.get("days_to_earnings")
        if days_to_earnings is not None:
            from ..services.earnings import blackout_days

            blackout = blackout_days()
            if days_to_earnings <= blackout:
                reasons.append(
                    f"Earnings in {days_to_earnings} day(s) — inside the "
                    f"{blackout}-day blackout window (gap risk)"
                )

        approved = not reasons
        risk_rating = "low" if confidence >= 80 and rr >= 2.5 else "medium" if confidence >= 65 else "high"

        notes = [f"Entry {entry}, stop {stop} ({atr_mult}×ATR), targets {target1}/{target2}, R:R {rr}"]
        notes.append(f"Position {position_size} shares, max risk ${actual_risk_usd:,.2f} "
                     f"({settings.MAX_RISK_PER_TRADE_PCT}% rule"
                     f"{', halved for high-volatility regime' if risk_scale < 1.0 else ''})")
        notes += reasons

        return AgentResult(
            agent=self.name,
            score=100.0 if approved else 0.0,
            direction=direction,
            data={
                "approved": approved, "entry": entry, "stop_loss": stop,
                "target1": target1, "target2": target2, "risk_reward": rr,
                "position_size": position_size, "max_risk_usd": actual_risk_usd,
                "risk_rating": risk_rating, "rejection_reasons": reasons,
            },
            notes=notes,
        )
