import httpx
import pandas as pd

from ._http import fetch_parquet
from ._query import BaseQuery, EventQuery


class AaveNamespace:
    def __init__(self, session: httpx.AsyncClient, base_url: str):
        self._session = session
        self._base_url = base_url

    def _q(self, event: str) -> EventQuery:
        return EventQuery(self._session, self._base_url, "/aave/read", {"event": event})

    def deposits(self) -> EventQuery:
        return self._q("deposit")

    def withdrawals(self) -> EventQuery:
        return self._q("withdraw")

    def borrows(self) -> EventQuery:
        return self._q("borrow")

    def repays(self) -> EventQuery:
        return self._q("repay")

    def flashloans(self) -> EventQuery:
        return self._q("flashloan")

    def liquidations(self) -> EventQuery:
        return self._q("liquidation")


class UniswapNamespace:
    def __init__(self, session: httpx.AsyncClient, base_url: str):
        self._session = session
        self._base_url = base_url

    def _q(self, event: str, symbol0: str, symbol1: str, fee: int) -> EventQuery:
        return EventQuery(
            self._session,
            self._base_url,
            "/uniswap/read",
            {"event": event, "symbol0": symbol0, "symbol1": symbol1, "fee": fee},
        )

    def swaps(self, symbol0: str, symbol1: str, fee: int) -> EventQuery:
        return self._q("swap", symbol0, symbol1, fee)

    def deposits(self, symbol0: str, symbol1: str, fee: int) -> EventQuery:
        return self._q("deposit", symbol0, symbol1, fee)

    def withdrawals(self, symbol0: str, symbol1: str, fee: int) -> EventQuery:
        return self._q("withdraw", symbol0, symbol1, fee)

    def collects(self, symbol0: str, symbol1: str, fee: int) -> EventQuery:
        return self._q("collect", symbol0, symbol1, fee)


class LidoNamespace:
    def __init__(self, session: httpx.AsyncClient, base_url: str):
        self._session = session
        self._base_url = base_url

    def _q(self, event: str) -> EventQuery:
        return EventQuery(self._session, self._base_url, "/lido/read", {"event": event})

    def deposits(self) -> EventQuery:
        return self._q("deposit")

    def withdrawal_requests(self) -> EventQuery:
        return self._q("withdrawal_request")

    def withdrawals_claimed(self) -> EventQuery:
        return self._q("withdrawal_claimed")


class StaderNamespace:
    def __init__(self, session: httpx.AsyncClient, base_url: str):
        self._session = session
        self._base_url = base_url

    def _q(self, event: str) -> EventQuery:
        return EventQuery(self._session, self._base_url, "/stader/read", {"event": event})

    def deposits(self) -> EventQuery:
        return self._q("deposit")

    def withdrawal_requests(self) -> EventQuery:
        return self._q("withdrawal_request")

    def withdrawals(self) -> EventQuery:
        return self._q("withdrawal")


class ThresholdNamespace:
    def __init__(self, session: httpx.AsyncClient, base_url: str):
        self._session = session
        self._base_url = base_url

    def _q(self, event: str) -> EventQuery:
        return EventQuery(self._session, self._base_url, "/threshold/read", {"event": event})

    def deposits(self) -> EventQuery:
        return self._q("deposit")

    def deposit_requests(self) -> EventQuery:
        return self._q("deposit_request")

    def withdrawals(self) -> EventQuery:
        return self._q("withdrawal")

    def withdrawal_requests(self) -> EventQuery:
        return self._q("withdrawal_request")


class NativeTransfersQuery(BaseQuery):
    def __init__(self, session: httpx.AsyncClient, base_url: str):
        super().__init__(session, base_url, {})
        self._min_amount = None

    def min_amount(self, amount: float) -> "NativeTransfersQuery":
        self._min_amount = amount
        return self

    async def fetch(self) -> pd.DataFrame:
        if self._min_amount is not None:
            self._body["min_amount"] = self._min_amount
            path = "/native_transfers/read/min"
        else:
            path = "/native_transfers/read"
        return await fetch_parquet(self._session, self._base_url + path, self._body)


class NativeNamespace:
    def __init__(self, session: httpx.AsyncClient, base_url: str):
        self._session = session
        self._base_url = base_url

    def transfers(self) -> NativeTransfersQuery:
        return NativeTransfersQuery(self._session, self._base_url)


class CacheNamespace:
    def __init__(self, session: httpx.AsyncClient, base_url: str):
        self._session = session
        self._base_url = base_url

    async def flush(self) -> None:
        await self._session.post(self._base_url + "/cache/flush", json={})
