"""
Module d'authentification Microsoft Graph
Gère l'obtention et le renouvellement des tokens
"""
import logging
from msal import ConfidentialClientApplication
from config import GRAPH_CONFIG, EMAIL_CONFIG
import requests

logger = logging.getLogger(__name__)

class GraphAuthenticator:
    """Gestionnaire d'authentification pour Microsoft Graph"""
    
    def __init__(self):
        """Initialise le client MSAL"""
        self.app = ConfidentialClientApplication(
            GRAPH_CONFIG['client_id'],
            authority=GRAPH_CONFIG['authority'],
            client_credential=GRAPH_CONFIG['client_secret']
        )
        self.token = None
        self.headers = None
        
    def get_token(self):
        """
        Obtient un token d'accès pour Microsoft Graph
        
        Returns:
            str: Token d'accès ou None si erreur
        """
        try:
            # Essayer d'obtenir un token depuis le cache
            result = self.app.acquire_token_silent(
                GRAPH_CONFIG['scope'], 
                account=None
            )
            
            # Si pas de token en cache, demander un nouveau
            if not result:
                logger.info("Aucun token en cache, demande d'un nouveau token...")
                result = self.app.acquire_token_for_client(
                    scopes=GRAPH_CONFIG['scope']
                )
            
            if 'access_token' in result:
                self.token = result['access_token']
                self.headers = {
                    'Authorization': f'Bearer {self.token}',
                    'Content-Type': 'application/json'
                }
                logger.info("Token obtenu avec succès")
                return self.token
            else:
                logger.error(f"Erreur lors de l'obtention du token: {result.get('error_description', 'Erreur inconnue')}")
                return None
                
        except Exception as e:
            logger.error(f"Exception lors de l'obtention du token: {str(e)}")
            return None
    
    def get_headers(self):
        """
        Retourne les headers avec le token pour les requêtes
        
        Returns:
            dict: Headers HTTP avec autorisation
        """
        if not self.headers or not self.token:
            self.get_token()
        return self.headers
    
    def test_connection(self):
        """
        Teste la connexion à Microsoft Graph
        
        Returns:
            bool: True si connexion réussie
        """
        try:
            headers = self.get_headers()
            if not headers:
                logger.error("Impossible d'obtenir les headers d'authentification")
                return False
            
            # Test avec l'accès à la boîte mail surveillée
            # Utiliser un endpoint compatible avec l'authentification application-only
            mailbox = EMAIL_CONFIG['monitored_mailbox']
            response = requests.get(
                f'https://graph.microsoft.com/v1.0/users/{mailbox}',
                headers=headers
            )
            
            if response.status_code == 200:
                logger.info("Connexion à Microsoft Graph réussie")
                user_data = response.json()
                logger.info(f"Accès confirmé à la boîte: {user_data.get('userPrincipalName', 'N/A')}")
                return True
            elif response.status_code == 401:
                logger.error("Token invalide ou expiré")
                # Forcer le renouvellement du token
                self.token = None
                self.headers = None
                return False
            else:
                logger.error(f"Erreur de connexion: {response.status_code} - {response.text}")
                return False
                
        except Exception as e:
            logger.error(f"Exception lors du test de connexion: {str(e)}")
            return False
    
    def make_request(self, method, url, **kwargs):
        """
        Effectue une requête HTTP avec gestion automatique du token
        
        Args:
            method: Méthode HTTP (GET, POST, etc.)
            url: URL de l'endpoint
            **kwargs: Arguments supplémentaires pour requests
            
        Returns:
            requests.Response ou None si erreur
        """
        max_retries = 2
        retry_count = 0
        
        while retry_count < max_retries:
            try:
                headers = self.get_headers()
                if not headers:
                    logger.error("Impossible d'obtenir les headers")
                    return None
                
                # Ajouter les headers aux kwargs
                if 'headers' in kwargs:
                    kwargs['headers'].update(headers)
                else:
                    kwargs['headers'] = headers
                
                # Faire la requête
                response = requests.request(method, url, **kwargs)
                
                # Si token expiré, renouveler et réessayer
                if response.status_code == 401:
                    logger.info("Token expiré, renouvellement...")
                    self.token = None
                    self.headers = None
                    retry_count += 1
                    continue
                
                return response
                
            except Exception as e:
                logger.error(f"Erreur lors de la requête: {str(e)}")
                return None
        
        logger.error(f"Échec après {max_retries} tentatives")
        return None

# Instance singleton
graph_auth = GraphAuthenticator()