from __future__ import annotations

from dataclasses import dataclass
from decimal import Decimal
from typing import Literal

Side = Literal["buy", "sell"]
OrderType = Literal["market", "limit", "trigger"]
TimeInForce = Literal["Alo", "Ioc", "Gtc"]


@dataclass(frozen=True)
class OrderIntent:
    strategy_id: str
    symbol: str
    coin: str
    side: Side
    reduce_only: bool
    order_type: OrderType
    tif: TimeInForce | None
    size: Decimal
    price: Decimal | None
    trigger_price: Decimal | None
    stop_loss: Decimal | None
    take_profit: Decimal | None
    client_order_id: str
    reason: str
    risk_usd: Decimal
    estimated_notional_usd: Decimal

    def __post_init__(self) -> None:
        if not self.strategy_id:
            raise ValueError("strategy_id is required")
        if not self.coin or self.coin != self.coin.upper():
            raise ValueError("coin must be uppercase")
        if self.size <= 0:
            raise ValueError("size must be positive")
        if self.estimated_notional_usd < 0:
            raise ValueError("estimated_notional_usd must be non-negative")
        if self.risk_usd < 0:
            raise ValueError("risk_usd must be non-negative")
        if not self.reduce_only and self.stop_loss is None:
            raise ValueError("entry OrderIntent requires stop_loss")
        if self.order_type == "limit" and self.price is None:
            raise ValueError("limit OrderIntent requires price")
        if self.order_type == "trigger" and self.trigger_price is None:
            raise ValueError("trigger OrderIntent requires trigger_price")
