"""
Tano Shield Base Client
"""

import requests
from tano_shield.core.errors import ApiRequestError, AuthenticationError, create_error_from_response
from tano_shield.core.config import DEFAULT_CONFIG, get_endpoints

class TanoShieldClient:
    """
    Base client for Tano Shield API
    """
    
    def __init__(self, api_key=None, base_url=None, timeout=None, version=None):
        """
        Create a new Tano Shield client
        
        Args:
            api_key (str): API key for authentication
            base_url (str, optional): Base URL for API requests
            timeout (int, optional): Request timeout in seconds
            version (str, optional): API version
        """
        self.api_key = api_key
        self.base_url = base_url or DEFAULT_CONFIG['base_url']
        self.timeout = timeout or DEFAULT_CONFIG['timeout']
        self.version = version or DEFAULT_CONFIG['version']
        
        # Initialize endpoints
        self.endpoints = get_endpoints(self.base_url, self.version)
        
        # Create session
        self.session = requests.Session()
        self.session.headers.update({
            'Content-Type': 'application/json',
        })
    
    def set_api_key(self, api_key):
        """
        Set the API key
        
        Args:
            api_key (str): The API key
        """
        self.api_key = api_key
    
    def get_auth_headers(self):
        """
        Get authorization headers
        
        Returns:
            dict: Headers object with authorization
        
        Raises:
            AuthenticationError: If API key is not provided
        """
        if not self.api_key:
            raise AuthenticationError('API key is required')
        
        return {
            'Authorization': f'Bearer {self.api_key}'
        }
    
    def request(self, method, url, data=None, **options):
        """
        Make an authenticated request to the API
        
        Args:
            method (str): HTTP method
            url (str): Request URL
            data (dict, optional): Request data
            **options: Additional options
        
        Returns:
            dict: Response data
        
        Raises:
            ApiRequestError: If the request fails
        """
        headers = {
            **self.get_auth_headers(),
            **(options.get('headers', {}))
        }
        
        try:
            response = self.session.request(
                method=method,
                url=url,
                json=data,
                headers=headers,
                timeout=self.timeout,
                **{k: v for k, v in options.items() if k != 'headers'}
            )
            
            # Raise exception for error status codes
            response.raise_for_status()
            
            return response.json()
        except requests.exceptions.HTTPError as error:
            # Create a TanoShieldError from the response
            raise create_error_from_response(error.response, 'API request failed')
        except requests.exceptions.RequestException as error:
            # Handle other request exceptions
            if hasattr(error, 'response') and error.response:
                raise create_error_from_response(error.response, 'API request failed')
            elif hasattr(error, 'request') and error.request:
                raise ApiRequestError('No response received from server')
            else:
                raise ApiRequestError(f'Request error: {str(error)}')
        except Exception as error:
            # If error is already a TanoShieldError, rethrow it
            if hasattr(error, '__class__') and error.__class__.__name__.endswith('TanoShieldError'):
                raise error
            
            # Otherwise, create a new error
            raise ApiRequestError(f'Request failed: {str(error)}')
    
    def get(self, url, **options):
        """
        Make a GET request
        
        Args:
            url (str): Request URL
            **options: Request options
        
        Returns:
            dict: Response data
        """
        return self.request('GET', url, None, **options)
    
    def post(self, url, data, **options):
        """
        Make a POST request
        
        Args:
            url (str): Request URL
            data (dict): Request data
            **options: Request options
        
        Returns:
            dict: Response data
        """
        return self.request('POST', url, data, **options)
    
    def put(self, url, data, **options):
        """
        Make a PUT request
        
        Args:
            url (str): Request URL
            data (dict): Request data
            **options: Request options
        
        Returns:
            dict: Response data
        """
        return self.request('PUT', url, data, **options)
    
    def delete(self, url, **options):
        """
        Make a DELETE request
        
        Args:
            url (str): Request URL
            **options: Request options
        
        Returns:
            dict: Response data
        """
        return self.request('DELETE', url, None, **options)