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 Account(TypedDict):
  address: str
  subaccountNumber: NotRequired[int|None]

class Transfer(TypedDict):
  id: str
  sender: Account
  recipient: Account
  size: Decimal
  createdAt: datetime
  createdAtHeight: str
  symbol: str
  type: Literal['TRANSFER_IN', 'TRANSFER_OUT', 'DEPOSIT', 'WITHDRAWAL']
  transactionHash: str

class TransfersResponse(TypedDict):
  transfers: list[Transfer]

parse_response = response_parser(TransfersResponse)

@dataclass
class GetTransfersBetween(IndexerMixin):
  async def get_transfers_between(
    self,
    *,
    source_address: str,
    source_subaccount_number: str,
    recipient_address: str,
    recipient_subaccount_number: str,
    created_before_or_at_height: int | None = None,
    created_before_or_at: datetime | None = None,
    validate: bool | None = None
  ) -> TransfersResponse:
    """
    Get transfers between subaccounts

    - `source_address`: Sender wallet address.
    - `source_subaccount_number`: Sender subaccount number.
    - `recipient_address`: Recipient wallet address.
    - `recipient_subaccount_number`: Recipient subaccount number.
    - `created_before_or_at_height`: Restrict results to entries created at or before a specific block height.
    - `created_before_or_at`: Restrict results to entries created at or before a specific timestamp.
    - `validate`: Whether to validate the response against the generated schema.

    > [Official API docs](https://docs.dydx.xyz/indexer-client/http/accounts#get-transfers-between)
    """
    params: dict[str, object] = {
      'sourceAddress': source_address,
      'sourceSubaccountNumber': source_subaccount_number,
      'recipientAddress': recipient_address,
      'recipientSubaccountNumber': recipient_subaccount_number,
    }
    if created_before_or_at_height is not None:
      params['createdBeforeOrAtHeight'] = created_before_or_at_height
    if created_before_or_at is not None:
      params['createdBeforeOrAt'] = ts.dump(created_before_or_at)
    r = await self.request('GET', '/v4/transfers/between', params=params)
    return parse_response(r, validate=self.validate(validate))

