import asyncio
import requests
from requests.sessions import Session
from requests.cookies import RequestsCookieJar


from gumband_python_sdk.endpoint_manager import EndpointManager
from gumband_python_sdk.logging_handler import get_local_logger
from gumband_python_sdk.service_name import ServiceName

logger = get_local_logger()


class NetworkHandler:
    def __init__(self, endpoint_manager: EndpointManager):
        self.endpoint_manager = endpoint_manager
        self.jwt = None
        self.session = Session()
        self.session.cookies = RequestsCookieJar()
        logger.info("NetworkHandler initialized.")

    def set_jwt(self, jwt: str):
        self.jwt = jwt
        self.session.headers.update({"Authorization": f"Bearer {self.jwt}"})
        logger.debug("JWT token set.")

    async def _request(
        self,
        method: str,
        service_name: ServiceName,
        endpoint: str,
        data: dict = None,
        params: dict = None,
        stream: bool = False,
    ):
        url = self.endpoint_manager.get_endpoint(service_name=service_name, endpoint=endpoint)
        headers = {"Content-Type": "application/json"}

        logger.debug("Making %s request to %s", method.upper(), url)
        try:
            requestTask = asyncio.create_task(
                asyncio.to_thread(self.session.request, method=method, url=url, headers=headers, json=data, params=params, stream=stream)
            )
            response = await requestTask
            response.raise_for_status()
            logger.debug(f"Request successful with status code {response.status_code}")
            if stream:
                return response
            else:
                return response.json()
        except requests.exceptions.HTTPError as http_err:
            logger.error("HTTP error occurred: %s", str(http_err))
            raise
        except Exception as err:
            logger.error("An error occurred: %s", str(err))
            raise

    async def post(self, service: ServiceName, endpoint: str, data: dict):
        return await self._request("post", service_name=service, endpoint=endpoint, data=data)

    async def get(self, service: ServiceName, endpoint: str, params: dict = None, stream=False):
        return await self._request("get", service_name=service, endpoint=endpoint, params=params, stream=stream)
