import abc

from typing_extensions import override

from ._base import NotchPayBaseResource, AsyncNotchPayBaseResource
from .schemas.balance import NotchPayBalanceResponse
from .schemas.base import MaybeAwaitable

__all__ = [
    "NotchPayBalance",
    "AsyncNotchPayBalance",
]


class _NotchPayBalance(abc.ABC):
    """Abstract base class for Notchpay balance management."""

    @abc.abstractmethod
    def retrieve(self) -> MaybeAwaitable[NotchPayBalanceResponse]:
        """Retrieve account balance.

        Returns:
            NotchPayBalanceResponse: Response containing balance details.

        Raises:
            NotchPayError: In case of API request error.

        References:
            https://developer.notchpay.co/api-reference/retrieve-account-balance

        Example:
            >>> from notchpay import NotchPay
            >>> notchpay = NotchPay("your_api_key")
            >>> balance = notchpay.balance.retrieve()
            >>> print(f"Available: {balance.balance.available} {balance.balance.currency}")
        """
        ...


class NotchPayBalance(_NotchPayBalance, NotchPayBaseResource):
    """Synchronous client for Notchpay balance management.

    This class allows retrieving account balance synchronously.

    Example:
        >>> from notchpay import NotchPay
        >>> notchpay = NotchPay(api_key="your_api_key")
        >>> balance = notchpay.balance.retrieve()
        >>> print(f"Total: {balance.balance.total}")
    """

    def retrieve(self) -> NotchPayBalanceResponse:
        return self._request(
            "GET",
            "/balance",
            response_model=NotchPayBalanceResponse,
        )


class AsyncNotchPayBalance(_NotchPayBalance, AsyncNotchPayBaseResource):
    """Asynchronous client for Notchpay balance management.

    This class allows retrieving account balance asynchronously.

    Example:
        >>> import asyncio
        >>> from notchpay import AsyncNotchPay
        >>> async def main():
        ...    notchpay = AsyncNotchPay("your_api_key")
        ...    balance = await notchpay.balance.retrieve()
        ...    print(f"Available: {balance.balance.available}")
        >>> asyncio.run(main())
    """

    @override
    async def retrieve(self) -> NotchPayBalanceResponse:
        return await self._request(
            "GET",
            "/balance",
            response_model=NotchPayBalanceResponse,
        )
