"""Typed request/response models for the FereAI Gateway API."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any


@dataclass
class TaskResponse:
    task_id: str
    status: str = "queued"
    poll_url: str | None = None
    notification_stream: str | None = None


@dataclass
class TaskStatusResponse:
    task_id: str
    status: str
    result: dict[str, Any] | None = None


@dataclass
class ChatEvent:
    event: str
    data: dict[str, Any]


@dataclass
class TokenInfo:
    token: str
    expires_in: int


@dataclass
class RegisterInfo:
    registration_id: str
    challenge: str


@dataclass
class WalletInfo:
    address: str
    chain_type: str


@dataclass
class CreditsInfo:
    credits_available: float | None = None


@dataclass
class SwapRequest:
    chain_id_in: int
    chain_id_out: int
    token_in: str
    token_out: str
    amount: str
    slippage_bps: int = 50
    dryrun: bool = False
    stop_loss: dict | None = None
    take_profit: dict | None = None
    cancel_conditional_orders: bool | None = None

    def to_dict(self) -> dict:
        d: dict = {
            "chain_id_in": self.chain_id_in,
            "chain_id_out": self.chain_id_out,
            "token_in": self.token_in,
            "token_out": self.token_out,
            "amount": self.amount,
            "slippage_bps": self.slippage_bps,
            "dryrun": self.dryrun,
        }
        if self.stop_loss:
            d["stop_loss"] = self.stop_loss
        if self.take_profit:
            d["take_profit"] = self.take_profit
        if self.cancel_conditional_orders is not None:
            d["cancel_conditional_orders"] = self.cancel_conditional_orders
        return d


@dataclass
class LimitOrderRequest:
    chain_id_in: int
    chain_id_out: int
    token_in: str
    token_out: str
    amount: str
    price_usd_trigger: float
    trigger_token_address: str
    trigger_token_chain: str
    condition: str
    slippage_bps: int = 50
    query: str | None = None

    def to_dict(self) -> dict:
        d: dict = {
            "chain_id_in": self.chain_id_in,
            "chain_id_out": self.chain_id_out,
            "token_in": self.token_in,
            "token_out": self.token_out,
            "amount": self.amount,
            "price_usd_trigger": self.price_usd_trigger,
            "trigger_token_address": self.trigger_token_address,
            "trigger_token_chain": self.trigger_token_chain,
            "condition": self.condition,
            "slippage_bps": self.slippage_bps,
        }
        if self.query:
            d["query"] = self.query
        return d


@dataclass
class HooksRequest:
    chain_id: int
    token_address: str
    stop_loss: dict | None = None
    take_profit: dict | None = None

    def to_dict(self) -> dict:
        d: dict = {
            "chain_id": self.chain_id,
            "token_address": self.token_address,
        }
        if self.stop_loss:
            d["stop_loss"] = self.stop_loss
        if self.take_profit:
            d["take_profit"] = self.take_profit
        return d


@dataclass
class DepositRequest:
    amount_usdc: float
    position_id: str | None = None

    def to_dict(self) -> dict:
        d: dict = {"amount_usdc": self.amount_usdc}
        if self.position_id:
            d["position_id"] = self.position_id
        return d


@dataclass
class WithdrawRequest:
    position_id: str
    amount_usdc: float

    def to_dict(self) -> dict:
        return {
            "position_id": self.position_id,
            "amount_usdc": self.amount_usdc,
        }


class TaskTimeoutError(Exception):
    """Raised when a task does not complete within the timeout."""

    def __init__(self, task_id: str, timeout: int):
        self.task_id = task_id
        self.timeout = timeout
        super().__init__(f"Task {task_id} did not complete within {timeout}s")
