# ruff: noqa: N815, D103, T201 ANN201,ANN001, # type: ignore

import json

import aiohttp
from fastapi import HTTPException, status

from app.utils.log_utils import LogUtils

log = LogUtils(__name__)


async def fetch_data_async(url, params=None, data=None, method="GET", headers=None):
    print(url, headers)
    """
    Asynchronous utility function to make HTTP requests using aiohttp.

    Parameters
    ----------
    - `url`: The URL to make the request to.
    - `params`: (Optional) Dictionary or bytes to be sent in the query string for a GET request.
    - `data`: (Optional) Dictionary, bytes, or file-like object to send in the body of the request for a POST request.
    - `method`: (Optional) The HTTP method to use ("GET" or "POST"). Defaults to "GET".
    - `headers`: (Optional) Dictionary of HTTP headers.

    Returns
    -------
    - The response object from the HTTP request.
    """
    method = method.upper()

    if method not in ["GET", "POST"]:
        raise ValueError("Invalid HTTP method. Supported methods are 'GET' and 'POST'.")

    async with aiohttp.ClientSession() as session:
        if method == "GET":
            async with session.get(url, params=params, headers=headers) as response:
                content_type = response.headers.get("Content-Type", "")
                if "application/json" in content_type:
                    return await response.json()
                else:
                    return await response.text()
        elif method == "POST":
            async with session.post(url, params=params, data=data, headers=headers) as response:
                content_type = response.headers.get("Content-Type", "")
                if "application/json" in content_type:
                    return await response.json()
                else:
                    return await response.text()


async def fetch_data_using_post(url: str, headers: dict = None, body: dict = None):
    # Set 45 seconds timeout
    timeout = aiohttp.ClientTimeout(total=60)

    async with aiohttp.ClientSession(timeout=timeout) as session:
        request_args = {"url": url}
        if headers:
            request_args["headers"] = headers
        if body:
            request_args["json"] = body
        try:
            async with session.post(**request_args) as response:
                content_type = response.headers.get("content-type")
                if "json" in content_type:  # type: ignore
                    response_data = await response.json()
                # Check if its in xml format
                elif "xml" in content_type:
                    print("File is in xml format")
                    response_data = await response.text()
                else:
                    response_data = await response.text()
                    # Convert to JSON
                    response_data = json.loads(response_data)
                return response_data
        except TimeoutError as err:
            raise HTTPException(
                status_code=status.HTTP_408_REQUEST_TIMEOUT,
                detail="Unable to connect with raqamyah.net,ssl timeout error",
            ) from err


class HttpClient:
    def __init__(self, method: str = "GET") -> None:
        self.method = method.lower()
        if self.method not in ["get", "post"]:
            raise ValueError("Unsupported HTTP method. Supported methods: 'GET', 'POST'.")

    async def request(self, url: str, payload: dict | None = None, headers: dict | None = None) -> dict | str | None:
        """Make a request to the given URL with the given payload and headers."""
        if self.method == "get":
            return await self.get(url, payload, headers=headers)
        return await self.post(url, payload, headers=headers)

    async def get(self, url, payload=None, headers=None):
        async with aiohttp.ClientSession() as session, session.get(url, params=payload, headers=headers) as response:
            content_type = response.headers.get("content-type")
            if content_type and "json" in content_type:
                data = await response.json()
                return data
            else:
                return await response.text()

    async def post(
        self,
        url: str,
        payload: dict | None = None,
        headers: dict | None = None,
        data: dict | None = None,
    ) -> dict | str | None:
        """Make a POST request to the given URL with the given payload and headers."""
        async with aiohttp.ClientSession() as session:
            post_params = {
                "url": url,
                "headers": headers,
            }
            if payload is not None:
                post_params["json"] = payload
            if data is not None:
                post_params["data"] = data

            async with session.post(**post_params) as response:
                log_message = f"URL:{url} Payload: {payload} Headers: {headers} Status: {response.status}"
                log.debug_log(log_message)
                content_type = response.headers.get("content-type")
                if content_type and "json" in content_type:
                    return await response.json()

                return await response.text()

    async def post_request(self, url, payload, headers=None):
        async with aiohttp.ClientSession() as session, session.post(url, json=payload, headers=headers) as response:
            return response


async def fetch_data_using_get(url: str, headers: dict, params: dict = None) -> dict:
    async with aiohttp.ClientSession() as session:
        if not params:
            async with session.get(url, headers=headers) as response:
                content_type = response.headers.get("content-type")
                if "json" in content_type:
                    data = await response.json()
                else:
                    data = await response.text()
                    # Convert to JSON
                    data = json.loads(data)
                return data
        else:
            async with session.get(url, headers=headers, params=params) as response:
                content_type = response.headers.get("content-type")
                if "json" in content_type:
                    data = await response.json()
                else:
                    data = await response.text()
                    # Convert to JSON
                    data = json.loads(data)
                return data



