import threading
import time
import subprocess
import logging
from datetime import datetime
from zerotier_client import ZeroTierClient
from config import PING_INTERVAL

logger = logging.getLogger(__name__)

class PingService:
    def __init__(self):
        self.zt_client = ZeroTierClient()
        self.nodes_status = {}
        self.running = False
        self.thread = None
        self.network_id = None
    
    def set_network_id(self, network_id):
        """Imposta l'ID della rete da monitorare"""
        self.network_id = network_id
    
    def ping_node(self, ip_address):
        """Fa il ping a un nodo e ritorna True se online"""
        try:
            result = subprocess.run(
                ['ping', '-c', '1', '-W', '3', ip_address],
                capture_output=True,
                timeout=5
            )
            return result.returncode == 0
        except Exception as e:
            logger.error(f'Ping error for {ip_address}: {e}')
            return False
    
    def update_node_status(self):
        """Aggiorna lo stato di tutti i nodi"""
        if not self.network_id:
            logger.warning('Network ID not set')
            return
        
        peers = self.zt_client.get_peers(self.network_id)
        current_time = datetime.now().isoformat()
        
        for peer in peers:
            peer_id = peer.get('id')
            hostname = peer.get('name', 'Unknown')
            config = peer.get('config', {})
            
            # Estrai IP ZeroTier dal config
            ip_addresses = config.get('ipAssignments', [])
            if not ip_addresses:
                continue
            
            zt_ip = ip_addresses[0]
            
            # Fa il ping
            is_online = self.ping_node(zt_ip)
            
            self.nodes_status[peer_id] = {
                'id': peer_id,
                'hostname': hostname,
                'ip': zt_ip,
                'online': is_online,
                'status': 'online' if is_online else 'offline',
                'last_check': current_time
            }
        
        logger.info(f'Updated status for {len(self.nodes_status)} nodes')
    
    def get_nodes_status(self):
        """Ritorna lo stato di tutti i nodi"""
        return list(self.nodes_status.values())
    
    def start(self, network_id):
        """Avvia il servizio di ping in background"""
        if self.running:
            logger.warning('Service already running')
            return
        
        self.network_id = network_id
        self.running = True
        self.thread = threading.Thread(target=self._run, daemon=True)
        self.thread.start()
        logger.info('Ping service started')
    
    def _run(self):
        """Loop principale del servizio"""
        while self.running:
            try:
                self.update_node_status()
            except Exception as e:
                logger.error(f'Error in ping service: {e}')
            
            time.sleep(PING_INTERVAL)
    
    def stop(self):
        """Arresta il servizio"""
        self.running = False
        if self.thread:
            self.thread.join(timeout=5)
        logger.info('Ping service stopped')
