import requests
from typing import Any, Dict, Optional
import os
from termcolor import colored

def http_exception(func):
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except requests.exceptions.HTTPError as e:
            print(colored(f"HTTP error occurred: {e.response.json()}", 'red'))
            raise
        except Exception as e:
            print(colored(f"An error occurred: {str(e)}", 'red'))
            raise
    return wrapper

class Client:
    def __init__(self, api_key: str, base_url: Optional[str] = None):
        self._api_key = api_key
        self.base_url = base_url or os.getenv("API_URL") or "https://api.galtea.ai"

    def _get_headers(self) -> Dict[str, str]:
        headers = { "User-agent": "Galtea SDK user agent" }
        if self._api_key:
            headers['Authorization'] = f"Bearer {self._api_key}"
        return headers

    @http_exception
    def get(self, endpoint: str, params: Optional[Dict[str, Any]] = None) -> requests.Response:
        url = f"{self.base_url}/{endpoint}"
        headers = self._get_headers()
        response = requests.get(url, params=params, headers=headers)
        response.raise_for_status()
        return response

    @http_exception
    def post(self, endpoint: str, data: Optional[Dict[str, Any]] = None, json: Optional[Dict[str, Any]] = None) -> requests.Response:
        url = f"{self.base_url}/{endpoint}"
        headers = self._get_headers()
        response = requests.post(url, data=data, json=json, headers=headers)
        response.raise_for_status()
        return response

    @http_exception
    def patch(self, endpoint: str, data: Optional[Dict[str, Any]] = None, json: Dict[str, Any] = None) -> requests.Response:
        url = f"{self.base_url}/{endpoint}"
        headers = self._get_headers()
        response = requests.patch(url, data=data, json=json, headers=headers)
        response.raise_for_status()
        return response

    @http_exception
    def delete(self, endpoint: str) -> requests.Response:
        url = f"{self.base_url}/{endpoint}"
        headers = self._get_headers()
        response = requests.delete(url, headers=headers)
        response.raise_for_status()
        return response