"""
Classe de base pour tous les handlers gRPC
"""
import threading
import time
from abc import ABC, abstractmethod
from typing import Optional, Dict, Any

from ..exceptions import GrpcError
from ....monitoring.logger import logger

class BaseHandler(ABC):
    """
    Classe de base pour tous les handlers gRPC
    
    Fournit:
    - Cycle de vie commun (start/stop)
    - Gestion d'erreurs de base
    - Statistiques communes
    - Thread-safety
    """
    
    def __init__(self, grpc_client, name: str = None):
        self.grpc_client = grpc_client
        self.name = name or self.__class__.__name__
        
        # État du handler
        self._running = False
        self._stop_event = threading.Event()
        self._lock = threading.RLock()
        
        # Statistiques
        self._stats = {
            'start_time': None,
            'messages_sent': 0,
            'messages_received': 0,
            'errors_count': 0,
            'last_error': None
        }
    
    @abstractmethod
    def run(self):
        """Méthode principale du handler (à implémenter)"""
        pass
    
    def start(self):
        """Démarre le handler"""
        with self._lock:
            if not self._running:
                self._running = True
                self._stop_event.clear()
                self._stats['start_time'] = time.time()
                logger('debug', f"[{self.name}] Démarré")
    
    def stop(self):
        """Arrête le handler"""
        with self._lock:
            if self._running:
                self._running = False
                self._stop_event.set()
                logger('debug', f"[{self.name}] Arrêté")
    
    def is_running(self) -> bool:
        """Vérifie si le handler est en cours d'exécution"""
        with self._lock:
            return self._running and self.grpc_client.is_running()
    
    def is_connected(self) -> bool:
        """Vérifie si la connexion gRPC est active"""
        return self.grpc_client.is_connected()
    
    def wait_for_stop(self, timeout: float = None) -> bool:
        """Attend l'arrêt du handler"""
        return self._stop_event.wait(timeout)
    
    def _handle_error(self, error: Exception, context: str = ""):
        """Gestion d'erreur commune"""
        self._stats['errors_count'] += 1
        self._stats['last_error'] = str(error)
        
        error_msg = f"[{self.name}] Erreur{' ' + context if context else ''}: {error}"
        logger('error', error_msg)
    
    def _update_stats(self, sent: int = 0, received: int = 0):
        """Met à jour les statistiques"""
        self._stats['messages_sent'] += sent
        self._stats['messages_received'] += received
    
    def get_stats(self) -> Dict[str, Any]:
        """Retourne les statistiques du handler"""
        with self._lock:
            stats = dict(self._stats)
            stats.update({
                'is_running': self._running,
                'uptime': time.time() - (self._stats['start_time'] or time.time())
            })
            return stats
    
    @property
    def stub(self):
        """Raccourci vers le stub gRPC"""
        return self.grpc_client.stub