from dataclasses import dataclass
from datetime import datetime
from decimal import Decimal
from dydx.core import timestamp as ts
from typing_extensions import Literal, NotRequired, TypedDict
from ..core import IndexerMixin, response_parser

class Order(TypedDict):
  id: str
  subaccountId: str
  clientId: str
  clobPairId: str
  side: Literal['BUY', 'SELL']
  size: Decimal
  totalFilled: Decimal
  price: Decimal
  type: Literal['LIMIT', 'MARKET', 'STOP_LIMIT', 'STOP_MARKET', 'TRAILING_STOP', 'TAKE_PROFIT', 'TAKE_PROFIT_MARKET', 'HARD_TRADE', 'FAILED_HARD_TRADE', 'TRANSFER_PLACEHOLDER']
  status: Literal['OPEN', 'FILLED', 'CANCELED', 'BEST_EFFORT_CANCELED', 'UNTRIGGERED', 'BEST_EFFORT_OPENED', 'PENDING']
  timeInForce: Literal['GTT', 'IOC', 'FOK']
  reduceOnly: NotRequired[bool | None]
  orderFlags: str
  goodTilBlock: NotRequired[str | None]
  goodTilBlockTime: NotRequired[datetime | None]
  createdAtHeight: NotRequired[str | None]
  clientMetadata: NotRequired[str | None]
  triggerPrice: NotRequired[Decimal | None]
  postOnly: NotRequired[bool | None]
  ticker: str
  updatedAt: NotRequired[datetime | None]
  updatedAtHeight: NotRequired[str | None]
  subaccountNumber: int
  orderRouterAddress: NotRequired[str|None]
  builderFee: NotRequired[Decimal | None]
  feePpm: NotRequired[Decimal | None]

parse_response = response_parser(list[Order])

@dataclass
class ListParentOrders(IndexerMixin):
  async def list_parent_orders(
    self,
    *,
    address: str,
    parent_subaccount_number: int,
    limit: int | None = None,
    ticker: str | None = None,
    side: Literal['BUY', 'SELL'] | None = None,
    status: Literal[
      'OPEN', 'FILLED', 'CANCELED', 'BEST_EFFORT_CANCELED', 'UNTRIGGERED', 'BEST_EFFORT_OPENED', 'PENDING'
    ] | None = None,
    type: Literal[
      'LIMIT', 'MARKET', 'STOP_LIMIT', 'STOP_MARKET', 'TRAILING_STOP', 'TAKE_PROFIT', 'TAKE_PROFIT_MARKET', 'HARD_TRADE', 'FAILED_HARD_TRADE', 'TRANSFER_PLACEHOLDER'
    ] | None = None,
    good_til_block_before_or_at: int | None = None,
    good_til_block_time_before_or_at: datetime | None = None,
    return_latest_orders: bool | None = None,
    validate: bool | None = None
  ) -> list[Order]:
    """
    List parent orders

    - `address`: Wallet address that owns the account.
    - `parent_subaccount_number`: Parent subaccount number.
    - `limit`: Maximum number of results to return.
    - `ticker`: Ticker filter.
    - `side`: Order side filter.
    - `status`: Order status filter.
    - `type`: Order type filter.
    - `good_til_block_before_or_at`: Latest good-til-block to include.
    - `good_til_block_time_before_or_at`: Latest good-til-block time to include.
    - `return_latest_orders`: Whether to return only the latest orders.
    - `validate`: Whether to validate the response against the generated schema.

    > [Official API docs](https://docs.dydx.xyz/indexer-client/http/accounts#list-parent-orders)
    """
    params: dict[str, object] = {
      'address': address,
      'parentSubaccountNumber': parent_subaccount_number,
    }
    if limit is not None:
      params['limit'] = limit
    if ticker is not None:
      params['ticker'] = ticker
    if side is not None:
      params['side'] = side
    if status is not None:
      params['status'] = status
    if type is not None:
      params['type'] = type
    if good_til_block_before_or_at is not None:
      params['goodTilBlockBeforeOrAt'] = good_til_block_before_or_at
    if good_til_block_time_before_or_at is not None:
      params['goodTilBlockTimeBeforeOrAt'] = ts.dump(good_til_block_time_before_or_at)
    if return_latest_orders is not None:
      params['returnLatestOrders'] = return_latest_orders
    r = await self.request('GET', '/v4/orders/parentSubaccountNumber', params=params)
    return parse_response(r, validate=self.validate(validate))

