"""
AgentBroker SDK Data Models

These dataclasses represent the structured responses returned by the API.
All fields mirror the JSON response from the AgentBroker API.
"""

from __future__ import annotations
from dataclasses import dataclass, field
from typing import Optional, List
from datetime import datetime


@dataclass
class Agent:
    """Registered agent profile."""
    agent_id: str
    name: str
    api_key: Optional[str] = None
    owner_email: Optional[str] = None
    callback_url: Optional[str] = None
    preferred_pairs: List[str] = field(default_factory=list)
    balance_usdc: Optional[str] = None
    strategy: Optional["Strategy"] = None
    trade_count: int = 0
    created_at: Optional[str] = None
    updated_at: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> "Agent":
        strategy = None
        if data.get("strategy"):
            strategy = Strategy.from_dict(data["strategy"])
        return cls(
            agent_id=data.get("agent_id", ""),
            name=data.get("name", ""),
            api_key=data.get("api_key"),
            owner_email=data.get("owner_email"),
            callback_url=data.get("callback_url"),
            preferred_pairs=data.get("preferred_pairs", []),
            balance_usdc=data.get("balance_usdc"),
            strategy=strategy,
            trade_count=data.get("trade_count", 0),
            created_at=data.get("created_at"),
            updated_at=data.get("updated_at"),
        )


@dataclass
class Strategy:
    """Trading strategy."""
    name: str
    display_name: str
    description: Optional[str] = None
    parameters: Optional[dict] = None
    selected_at: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> "Strategy":
        return cls(
            name=data.get("name", ""),
            display_name=data.get("display_name", ""),
            description=data.get("description"),
            parameters=data.get("parameters"),
            selected_at=data.get("selected_at"),
        )


@dataclass
class Account:
    """Agent account summary."""
    agent_id: str
    name: str
    balance_usdc: str
    strategy: Optional[Strategy] = None
    total_deposited: Optional[str] = None
    total_trades: int = 0

    @classmethod
    def from_dict(cls, data: dict) -> "Account":
        strategy = None
        if data.get("strategy"):
            strategy = Strategy.from_dict(data["strategy"])
        return cls(
            agent_id=data.get("agent_id", ""),
            name=data.get("name", ""),
            balance_usdc=data.get("balance_usdc", "0.000000"),
            strategy=strategy,
            total_deposited=data.get("total_deposited"),
            total_trades=data.get("total_trades", 0),
        )


@dataclass
class Deposit:
    """Deposit record."""
    deposit_id: int
    agent_id: str
    amount_usdc: str
    balance_usdc: str
    tx_hash: Optional[str] = None
    status: str = "confirmed"
    created_at: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> "Deposit":
        return cls(
            deposit_id=data.get("deposit_id", 0),
            agent_id=data.get("agent_id", ""),
            amount_usdc=data.get("amount_usdc", "0.000000"),
            balance_usdc=data.get("balance_usdc", "0.000000"),
            tx_hash=data.get("tx_hash"),
            status=data.get("status", "confirmed"),
            created_at=data.get("created_at"),
        )


@dataclass
class Fill:
    """Order fill detail."""
    fill_price: str
    fill_quantity: str
    fill_value_usdc: str
    fee_usdc: str
    trade_id: int

    @classmethod
    def from_dict(cls, data: dict) -> "Fill":
        return cls(
            fill_price=data.get("fill_price", "0"),
            fill_quantity=data.get("fill_quantity", "0"),
            fill_value_usdc=data.get("fill_value_usdc", "0"),
            fee_usdc=data.get("fee_usdc", "0"),
            trade_id=data.get("trade_id", 0),
        )


@dataclass
class Order:
    """Order record."""
    order_id: int
    agent_id: str
    pair: str
    side: str
    type: str
    quantity: str
    filled_quantity: str
    status: str
    price: Optional[str] = None
    fills: List[Fill] = field(default_factory=list)
    balance_usdc: Optional[str] = None
    created_at: Optional[str] = None
    updated_at: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> "Order":
        fills = [Fill.from_dict(f) for f in data.get("fills", [])]
        return cls(
            order_id=data.get("order_id", 0),
            agent_id=data.get("agent_id", ""),
            pair=data.get("pair", ""),
            side=data.get("side", ""),
            type=data.get("type", data.get("order_type", "")),
            quantity=data.get("quantity", "0"),
            filled_quantity=data.get("filled_quantity", "0"),
            status=data.get("status", ""),
            price=data.get("price"),
            fills=fills,
            balance_usdc=data.get("balance_usdc"),
            created_at=data.get("created_at"),
            updated_at=data.get("updated_at"),
        )


@dataclass
class OrderBookLevel:
    """Single price level in the order book."""
    price: str
    quantity: str
    total: str

    @classmethod
    def from_dict(cls, data: dict) -> "OrderBookLevel":
        return cls(
            price=data.get("price", "0"),
            quantity=data.get("quantity", "0"),
            total=data.get("total", "0"),
        )


@dataclass
class OrderBook:
    """Full order book for a trading pair."""
    pair: str
    timestamp: str
    bids: List[OrderBookLevel] = field(default_factory=list)
    asks: List[OrderBookLevel] = field(default_factory=list)

    @classmethod
    def from_dict(cls, data: dict) -> "OrderBook":
        return cls(
            pair=data.get("pair", ""),
            timestamp=data.get("timestamp", ""),
            bids=[OrderBookLevel.from_dict(b) for b in data.get("bids", [])],
            asks=[OrderBookLevel.from_dict(a) for a in data.get("asks", [])],
        )


@dataclass
class Price:
    """Current price for a trading pair."""
    pair: str
    price: float
    change_24h: Optional[float] = None
    volume_24h: Optional[float] = None
    high_24h: Optional[float] = None
    low_24h: Optional[float] = None
    timestamp: Optional[str] = None

    @classmethod
    def from_dict(cls, pair: str, data: dict) -> "Price":
        return cls(
            pair=pair,
            price=float(data.get("price", 0)),
            change_24h=data.get("change_24h"),
            volume_24h=data.get("volume_24h"),
            high_24h=data.get("high_24h"),
            low_24h=data.get("low_24h"),
            timestamp=data.get("timestamp"),
        )


@dataclass
class Withdrawal:
    """Withdrawal record."""
    withdrawal_id: int
    agent_id: str
    amount_usdc: str
    address: str
    status: str
    tx_hash: Optional[str] = None
    balance_usdc: Optional[str] = None
    created_at: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> "Withdrawal":
        return cls(
            withdrawal_id=data.get("withdrawal_id", 0),
            agent_id=data.get("agent_id", ""),
            amount_usdc=data.get("amount_usdc", "0"),
            address=data.get("address", ""),
            status=data.get("status", ""),
            tx_hash=data.get("tx_hash"),
            balance_usdc=data.get("balance_usdc"),
            created_at=data.get("created_at"),
        )


@dataclass
class Trade:
    """Executed trade record."""
    trade_id: int
    pair: str
    side: str
    quantity: str
    price: str
    fee_usdc: str
    created_at: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> "Trade":
        return cls(
            trade_id=data.get("trade_id", data.get("id", 0)),
            pair=data.get("pair", ""),
            side=data.get("side", ""),
            quantity=data.get("quantity", "0"),
            price=data.get("price", "0"),
            fee_usdc=data.get("fee_usdc", "0"),
            created_at=data.get("created_at"),
        )


@dataclass
class BalanceHistory:
    """Balance history entry."""
    balance_usdc: str
    event_type: str
    amount: str
    timestamp: str

    @classmethod
    def from_dict(cls, data: dict) -> "BalanceHistory":
        return cls(
            balance_usdc=data.get("balance_usdc", "0"),
            event_type=data.get("event_type", ""),
            amount=data.get("amount", "0"),
            timestamp=data.get("timestamp", ""),
        )
