from __future__ import annotations

from dataclasses import dataclass
from decimal import Decimal

from src.execution.order_intent import OrderIntent


@dataclass(frozen=True)
class RiskContext:
    open_positions: int
    kill_switch_active: bool
    daily_loss_exceeded: bool


@dataclass(frozen=True)
class RiskDecision:
    allowed: bool
    reasons: tuple[str, ...] = ()


@dataclass(frozen=True)
class PretradeRiskGate:
    min_order_notional_usd: Decimal
    max_parallel_positions: int
    max_order_notional_usd: Decimal | None = None
    max_risk_usd: Decimal | None = None

    def evaluate(self, intent: OrderIntent, context: RiskContext) -> RiskDecision:
        reasons: list[str] = []
        if context.kill_switch_active:
            reasons.append("kill_switch")
        if context.daily_loss_exceeded:
            reasons.append("daily_loss_exceeded")
        if not intent.reduce_only and intent.stop_loss is None:
            reasons.append("stop_loss_required")
        if not intent.reduce_only and intent.estimated_notional_usd < self.min_order_notional_usd:
            reasons.append("min_notional")
        if self.max_order_notional_usd is not None and not intent.reduce_only and intent.estimated_notional_usd > self.max_order_notional_usd:
            reasons.append("max_notional")
        if self.max_risk_usd is not None and not intent.reduce_only and intent.risk_usd > self.max_risk_usd:
            reasons.append("max_risk")
        if not intent.reduce_only and context.open_positions >= self.max_parallel_positions:
            reasons.append("max_parallel_positions")
        return RiskDecision(allowed=not reasons, reasons=tuple(reasons))
