"""
VPP Connection Management Module

This module provides a clean interface for managing VPP API client connections,
replacing the connection logic scattered throughout the original VRouterClient class.
"""

from typing import Optional
from vrouter.client import ExtendedVPPAPIClient
from loguru import logger as log
import threading
import time


class VPPConnectionManager:
    """
    Manages VPP API client connections with automatic reconnection and health monitoring.
    
    This class encapsulates all VPP connection logic, providing a clean interface
    for other components to use VPP API functionality.
    """
    
    def __init__(self, auto_reconnect: bool = True, health_check_interval: float = 30.0):
        """
        Initialize the VPP connection manager.
        
        Args:
            auto_reconnect: Whether to automatically attempt reconnection on failure
            health_check_interval: Interval in seconds for health checks
        """
        self._client: Optional[ExtendedVPPAPIClient] = None
        self._connected = False
        self._connection_lock = threading.Lock()
        self._auto_reconnect = auto_reconnect
        self._health_check_interval = health_check_interval
        self._health_check_thread: Optional[threading.Thread] = None
        self._shutdown_requested = False
    
    @property
    def client(self) -> ExtendedVPPAPIClient:
        """
        Get the VPP API client, connecting if necessary.
        
        Returns:
            ExtendedVPPAPIClient: The VPP API client instance
            
        Raises:
            ConnectionError: If connection cannot be established
        """
        with self._connection_lock:
            if not self._connected:
                if not self.connect():
                    raise ConnectionError("Failed to establish VPP connection")
            return self._client
    
    
    def connect(self) -> bool:
        """
        Establish connection to VPP.
        
        Returns:
            bool: True if connection successful, False otherwise
        """
        try:
            with self._connection_lock:
                log.info("Attempting to connect to VPP...")
                self._client = ExtendedVPPAPIClient()
                
                # Test the connection by getting configuration
                self._client.get_configuration()
                
                self._connected = True
                log.info("Successfully connected to VPP")
                
                # Start health monitoring if auto-reconnect is enabled
                if self._auto_reconnect and not self._health_check_thread:
                    self._start_health_monitoring()
                
                return True
                
        except Exception as e:
            log.error(f"Failed to connect to VPP: {e}")
            self._connected = False
            self._client = None
            return False
    
    def is_connected(self) -> bool:
        """
        Check if client is connected to VPP.
        
        Returns:
            bool: True if connected and healthy, False otherwise
        """
        if not self._connected or not self._client:
            return False
        
        try:
            # Perform a lightweight operation to test connectivity
            self._client.get_configuration()
            return True
        except Exception as e:
            log.warning(f"Connection health check failed: {e}")
            with self._connection_lock:
                self._connected = False
            return False
    
    def disconnect(self):
        """Close VPP connection and cleanup resources."""
        log.info("Disconnecting from VPP...")
        
        # Stop health monitoring
        self._shutdown_requested = True
        if self._health_check_thread and self._health_check_thread.is_alive():
            self._health_check_thread.join(timeout=5.0)
        
        with self._connection_lock:
            self._connected = False
            if self._client:
                # VPP client doesn't have an explicit close method
                # Just clear the reference
                self._client = None
        
        log.info("Disconnected from VPP")
    
    def ensure_connected(self) -> bool:
        """
        Ensure VPP connection is active, reconnecting if necessary.
        
        Returns:
            bool: True if connection is active, False otherwise
        """
        if self.is_connected():
            return True
        
        if self._auto_reconnect:
            log.info("Connection lost, attempting to reconnect...")
            return self.connect()
        
        return False
    
    def _start_health_monitoring(self):
        """Start background health monitoring thread."""
        if self._health_check_thread and self._health_check_thread.is_alive():
            return
        
        self._shutdown_requested = False
        self._health_check_thread = threading.Thread(
            target=self._health_monitor_loop,
            daemon=True,
            name="VPP-HealthMonitor"
        )
        self._health_check_thread.start()
        log.debug("Started VPP health monitoring thread")
    
    def _health_monitor_loop(self):
        """Background health monitoring loop."""
        while not self._shutdown_requested:
            try:
                time.sleep(self._health_check_interval)
                
                if self._shutdown_requested:
                    break
                
                if not self.is_connected() and self._auto_reconnect:
                    log.warning("Health check failed, attempting reconnection...")
                    self.connect()
                    
            except Exception as e:
                log.error(f"Error in health monitoring loop: {e}")
    
    def get_connection_stats(self) -> dict:
        """
        Get connection statistics and status.
        
        Returns:
            dict: Connection statistics
        """
        return {
            'connected': self._connected,
            'auto_reconnect': self._auto_reconnect,
            'health_check_interval': self._health_check_interval,
            'health_monitor_active': (
                self._health_check_thread is not None and 
                self._health_check_thread.is_alive()
            ),
            'client_available': self._client is not None
        }
    
    def __enter__(self):
        """Context manager entry."""
        if not self.connect():
            raise ConnectionError("Failed to establish VPP connection")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """Context manager exit."""
        self.disconnect()
