from __future__ import annotations

from dataclasses import dataclass
import os
from typing import Any
from decimal import Decimal

from src.execution.order_intent import OrderIntent
from src.execution.payloads import PreparedOrderPayload, prepare_order_payload
from src.hyperliquid.rounding import HyperliquidAssetMeta


@dataclass(frozen=True)
class ExecutionResult:
    status: str
    intent: OrderIntent
    exchange_response: Any = None
    side_effects: tuple[str, ...] = ()
    prepared_payload: PreparedOrderPayload | None = None


class HyperliquidLiveExecutor:
    def __init__(self, *, exchange: Any, expected_confirmation: str, dry_run: bool = False) -> None:
        self.exchange = exchange
        self.expected_confirmation = expected_confirmation
        self.dry_run = dry_run

    def _check_live_gates(self) -> None:
        if os.getenv("CTB_LIVE_TRADING_ALLOWED", "").lower() != "true":
            raise PermissionError("CTB_LIVE_TRADING_ALLOWED must be true before live execution")
        if os.getenv("CTB_LIVE_CONFIRMATION") != self.expected_confirmation:
            raise PermissionError("CTB_LIVE_CONFIRMATION does not match expected confirmation")

    def prepare_payload(self, intent: OrderIntent, meta: HyperliquidAssetMeta, *, min_notional_usd: Decimal) -> PreparedOrderPayload:
        return prepare_order_payload(intent, meta, min_notional_usd=min_notional_usd)

    def execute(self, intent: OrderIntent) -> ExecutionResult:
        if self.dry_run:
            return ExecutionResult(status="dry_run", intent=intent, side_effects=())
        self._check_live_gates()
        is_buy = intent.side == "buy"
        response = self.exchange.market_open(intent.coin, is_buy, float(intent.size), None, None)
        return ExecutionResult(status="submitted", intent=intent, exchange_response=response, side_effects=("hyperliquid_order",))
