import base64
import httpx
from typing import Dict, Any
from ..libraries.crypto import decrypt_data

class AuthenticationHandler:

    async def construct_auth_headers(self, auth_config: Dict[str, str]) -> Dict[str, str]:
        headers = {}
        credentials = auth_config.get('credentials', {})
        auth_header_value = auth_config.get('auth_header_value')

        # OAuth handling
        if 'client_id' in auth_config and 'client_secret' in credentials:
            access_token = await self.handle_oauth(auth_config)
            headers['Authorization'] = f'{auth_header_value} {access_token}'

        # Handle other authentication methods
        elif 'auth_token' in auth_config:
            headers['Authorization'] = f"{auth_header_value}  {auth_config['auth_token']}"

        elif 'username' in auth_config and 'password' in auth_config:
            basic_auth = base64.b64encode(f"{auth_config['username']}:{auth_config['password']}".encode()).decode()
            headers['Authorization'] = f"{auth_header_value} {basic_auth}"

        elif 'api_key' in auth_config:
            #headers['X-API-KEY'] = auth_config['api_key']
            headers['Authorization'] = f"{auth_header_value} {auth_config['api_key']}"

        elif 'email' in auth_config and 'api_token' in credentials: #Zendesk
            basic_auth_credentials = f"{auth_config['email']}:{credentials['api_token']}"
            basic_auth_encoded = base64.b64encode(basic_auth_credentials.encode()).decode()
            headers['Authorization'] = f"{auth_header_value} {basic_auth_encoded}"

        return headers

    async def handle_oauth(self, auth_config: Dict[str, str]) -> str:

        credentials = auth_config.get('credentials', {})

        # Refresh token if available
        refresh_token = credentials.get('refresh_token')
        client_id = credentials['client_id']
        client_secret = credentials['client_secret']

        token_url = auth_config.get('token_url')

        if refresh_token:
            token_response = await self.refresh_oauth_token(client_id, client_secret, refresh_token, token_url)
            new_access_token = token_response.get('access_token') or token_response.get('accesstoken') or token_response
            return new_access_token

        raise Exception("OAuth token could not be obtained.")

    async def refresh_oauth_token(self, client_id: str, client_secret: str, 
                                  refresh_token: str, token_url: str) -> Dict[str, Any]:
        payload = {
            'grant_type': 'refresh_token',
            'refresh_token': refresh_token,
            'client_id': client_id,
            'client_secret': client_secret
        }
        async with httpx.AsyncClient() as client:
            response = await client.post(token_url, data=payload)
            if response.status_code == 200:
                return response.json()
            else:
                raise Exception(f"Failed to refresh token: {response.text}")


# Example usage
# auth_handler = AuthenticationHandler()
# headers = await auth_handler.get_auth_headers(app_integration_dict)
