import requests
from requests.adapters import HTTPAdapter, Retry
import urllib3
from xclientai.utils.config_utils import get_api_key, get_default_workspace
from xclientai.config import Config
from xclientai.utils.logging import configure_logger
from typing import Optional

logger = configure_logger(__name__)

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


def do_request(
    url, 
    http_method, 
    json_data=None, 
    headers=None,
    params=None,
    xcloud_auth: bool = True,
    workspace_id: Optional[str] = None,
    throw_error: bool = True
):
    if xcloud_auth and not Config.DEBUG:
        api_key = get_api_key()
        assert api_key is not None, "We were not able to find your API key. To use the CLI or the Python client you need one. You can get an API Key in your profile. Then run the command `xcloud configure` or use the environment variable XCLOUD_API_KEY"
        
        headers = {} if headers is None else headers
        headers['x-api-key'] = api_key
        
    if workspace_id is None and not Config.DEBUG:
        workspace_id = get_default_workspace()
        
        assert workspace_id is not None, "The workspace_id cannot be None. Configure your workspace running the command `xcloud configure` or use the environment variable XCLOUD_DEFAULT_WORKSPACE"
        
        headers = {} if headers is None else headers
        headers['workspaceId'] = workspace_id
        
    session = requests.Session()
    retries = Retry(
        total=5,
        status_forcelist=[ 500, 502, 503, 504 ]
    )
    
    session.mount("http://", HTTPAdapter(max_retries=retries))
        
    params_fn = {
        "url": url, 
        "json": json_data,
        "timeout": 300,
        "headers": headers,
        "verify": False,
        "params": params
    }
    
    if Config.DEBUG:
        logger.debug(f"Request params: {params_fn}")
    
    if http_method == "get":
        response = session.get(**params_fn)
    elif http_method == "post":
        response = session.post(**params_fn)
    elif http_method == "patch":
        response = session.patch(**params_fn)
    elif http_method == "delete":
        response = session.delete(**params_fn)
    elif http_method == "put":
        response = session.put(**params_fn)
    
    error = False
    try:
        response.raise_for_status()
    except Exception as ex:
        error = True
        
    if error and throw_error:
        if 'application/json' in response.headers.get('Content-Type', ''):
            raise ValueError(response.json()["message"])
        else:
            raise ValueError(response.text)
    
    return response