# Copyright (c) 2025 Patrick Motsch
# All rights reserved.

"""
API Client helper for SharePoint operations.
Handles Microsoft Graph API calls with timeout and error handling.
"""

import logging
import aiohttp
import asyncio
from typing import Dict, Any

logger = logging.getLogger(__name__)

class ApiClientHelper:
    """Helper for Microsoft Graph API calls"""
    
    def __init__(self, methodInstance):
        """
        Initialize API client helper.
        
        Args:
            methodInstance: Instance of MethodSharepoint (for access to services)
        """
        self.method = methodInstance
        self.services = methodInstance.services
    
    async def makeGraphApiCall(self, endpoint: str, method: str = "GET", data: bytes = None) -> Dict[str, Any]:
        """
        Make a Microsoft Graph API call with timeout and detailed logging.
        
        Args:
            endpoint: API endpoint (without base URL)
            method: HTTP method (GET, POST, PUT)
            data: Optional request body data (bytes)
            
        Returns:
            Dict with API response or error information
        """
        try:
            if not hasattr(self.services, 'sharepoint') or not self.services.sharepoint._target.accessToken:
                return {"error": "SharePoint service not configured with access token"}
            
            headers = {
                "Authorization": f"Bearer {self.services.sharepoint._target.accessToken}",
                "Content-Type": "application/json" if data and method != "PUT" else "application/octet-stream" if data else "application/json"
            }
            
            url = f"https://graph.microsoft.com/v1.0/{endpoint}"
            logger.info(f"Making Graph API call: {method} {url}")
            
            # Set timeout to 30 seconds
            timeout = aiohttp.ClientTimeout(total=30)
            
            async with aiohttp.ClientSession(timeout=timeout) as session:
                if method == "GET":
                    logger.debug(f"Starting GET request to {url}")
                    async with session.get(url, headers=headers) as response:
                        logger.info(f"Graph API response: {response.status}")
                        if response.status == 200:
                            result = await response.json()
                            logger.debug(f"Graph API success: {len(str(result))} characters response")
                            return result
                        else:
                            errorText = await response.text()
                            logger.error(f"Graph API call failed: {response.status} - {errorText}")
                            return {"error": f"API call failed: {response.status} - {errorText}"}
                
                elif method == "PUT":
                    logger.debug(f"Starting PUT request to {url}")
                    async with session.put(url, headers=headers, data=data) as response:
                        logger.info(f"Graph API response: {response.status}")
                        if response.status in [200, 201]:
                            result = await response.json()
                            logger.debug(f"Graph API success: {len(str(result))} characters response")
                            return result
                        else:
                            errorText = await response.text()
                            logger.error(f"Graph API call failed: {response.status} - {errorText}")
                            return {"error": f"API call failed: {response.status} - {errorText}"}
                
                elif method == "POST":
                    logger.debug(f"Starting POST request to {url}")
                    async with session.post(url, headers=headers, data=data) as response:
                        logger.info(f"Graph API response: {response.status}")
                        if response.status in [200, 201]:
                            result = await response.json()
                            logger.debug(f"Graph API success: {len(str(result))} characters response")
                            return result
                        else:
                            errorText = await response.text()
                            logger.error(f"Graph API call failed: {response.status} - {errorText}")
                            return {"error": f"API call failed: {response.status} - {errorText}"}
                
                elif method == "DELETE":
                    logger.debug(f"Starting DELETE request to {url}")
                    async with session.delete(url, headers=headers) as response:
                        logger.info(f"Graph API response: {response.status}")
                        if response.status in [200, 204]:
                            logger.debug(f"Graph API DELETE success")
                            return {"success": True}
                        else:
                            errorText = await response.text()
                            logger.error(f"Graph API call failed: {response.status} - {errorText}")
                            return {"error": f"API call failed: {response.status} - {errorText}"}
                            
        except asyncio.TimeoutError:
            logger.error(f"Graph API call timed out after 30 seconds: {endpoint}")
            return {"error": f"API call timed out after 30 seconds: {endpoint}"}
        except Exception as e:
            logger.error(f"Error making Graph API call: {str(e)}")
            return {"error": f"Error making Graph API call: {str(e)}"}

