import urllib.parse
from abc import ABC

import aiohttp

from .exceptions import UnknownResponse


class BaseClient(ABC):
    def __init__(self, url: str):
        self.url = url
        self._session = aiohttp.ClientSession()

    def _url(self, uri: str) -> str:
        return urllib.parse.urljoin(self.url, uri)

    async def _request(self, method: str, uri: str, expected_status: int, **kwargs):
        async with self._session.request(method, self._url(uri), **kwargs) as response:
            await self._handle_response(response, expected_status)
            return await response.read()

    @staticmethod
    async def _handle_response(response, expected_status):
        if response.status != expected_status:
            raise UnknownResponse(
                status_code=response.status, payload=await response.content.read()
            )

    async def close(self):
        await self._session.close()

    async def __aenter__(self):
        return self

    async def __aexit__(self, *args, **kwargs):
        await self._session.close()
