import asyncio
import logging
from typing import Any

from grpc.aio import AioRpcError

from t_tech.invest.logging import get_metadata_from_aio_error
from t_tech.invest.retrying.base_retry_manager import BaseRetryManager

logger = logging.getLogger(__name__)


class AsyncRetryManager(BaseRetryManager):
    async def call_with_retries(self, call: Any):
        retries_left = self.get_initial_retries()
        while retries_left > 0:
            logger.debug("Trying to call")
            response = await call()
            try:
                await response
                logger.debug("Call succeeded")
                return response
            except AioRpcError as exception:
                retries_left -= 1
                logger.debug("Retries left = %s", retries_left)

                metadata = get_metadata_from_aio_error(exception)
                seconds_to_sleep = self.extract_seconds_to_sleep(metadata)
                await self._sleep(seconds_to_sleep)

        logger.debug("RetryManager exhausted, no retries left")
        return response

    async def _sleep(self, seconds_to_sleep):
        await asyncio.sleep(seconds_to_sleep)
