from typing import Any, Dict, Optional
import httpx
import logging
import google.cloud.logging


# Initialize Google Cloud Logging
client = google.cloud.logging.Client()
client.setup_logging()

# Configure the logger
logger = logging.getLogger("uvicorn")
logger.setLevel(logging.INFO)

class AsyncClientWrapper:
    def __init__(self):
        self.client: Optional[httpx.AsyncClient] = None

    def start(self):
        """Initialize the httpx.AsyncClient."""
        if self.client is None:
            self.client = httpx.AsyncClient(
                timeout=httpx.Timeout(180.0, connect=10.0), # We want a big ass timeout because permission fetching can take a while
                headers={"Content-Type": "application/json"},
            )
            logger.info("Async HTTP Client initialized.")

    async def stop(self):
        """Close the httpx.AsyncClient."""
        if self.client:
            await self.client.aclose()
            self.client = None
            logger.info("Async HTTP Client closed.")

    async def request(
        self,
        method: str,
        url: str,
        data: Optional[Dict[str, Any]] = None,
        params: Optional[Dict[str, Any]] = None,
        headers: Optional[Dict[str, str]] = None,
        **kwargs,
    ) -> httpx.Response:
        """Centralized request method with error handling."""
        if self.client is None:
            raise RuntimeError("AsyncClientWrapper not started. Call start() first.")

        try:
            response = await self.client.request(
                method, url, json=data, params=params, headers=headers, **kwargs
            )
            response.raise_for_status()
            return response
        except httpx.HTTPStatusError as e:
            logger.error(
                f"HTTP {method} error on {url}: {e.response.status_code} - {e.response.text}"
            )
            raise
        except httpx.RequestError as e:
            logger.error(f"Network error on {method} {url}: {str(e)}")
            raise

    async def get(
        self, url: str, params: Optional[Dict[str, Any]] = None, **kwargs
    ) -> httpx.Response:
        return await self.request("GET", url, params=params, **kwargs)

    async def post(
        self, url: str, data: Optional[Dict[str, Any]] = None, **kwargs
    ) -> httpx.Response:
        return await self.request("POST", url, data=data, **kwargs)

    async def put(
        self, url: str, data: Optional[Dict[str, Any]] = None, **kwargs
    ) -> httpx.Response:
        return await self.request("PUT", url, data=data, **kwargs)

    async def delete(self, url: str, **kwargs) -> httpx.Response:
        return await self.request("DELETE", url, **kwargs)
