"""Extended Telemetry Collection - Safe read-only diagnostics."""

import logging
import subprocess
import socket
import platform
from typing import Dict, List, Any, Optional
from doctor.core.os_detect import is_windows, is_macos, is_linux
import psutil


logger = logging.getLogger(__name__)


def collect_network_connectivity() -> Dict[str, Any]:
    """
    Collect network connectivity information (read-only).
    
    Returns:
        Dictionary with network connectivity metrics.
    """
    network_info = {
        "dns_resolution": None,
        "gateway_reachable": None,
        "gateway_latency_ms": None,
        "interfaces_up": [],
        "interfaces_down": []
    }
    
    try:
        # Check DNS resolution
        try:
            socket.gethostbyname("google.com")
            network_info["dns_resolution"] = True
        except socket.gaierror:
            network_info["dns_resolution"] = False
        
        # Check network interfaces
        interfaces = psutil.net_if_stats()
        for iface, stats in interfaces.items():
            if stats.isup:
                network_info["interfaces_up"].append(iface)
            else:
                network_info["interfaces_down"].append(iface)
        
        # Check default gateway (non-continuous ping)
        try:
            gateways = psutil.net_if_addrs()
            # Try to ping gateway (single ping, non-continuous)
            if is_windows():
                result = subprocess.run(
                    ["ping", "-n", "1", "8.8.8.8"],
                    capture_output=True,
                    timeout=3,
                    text=True
                )
            else:
                result = subprocess.run(
                    ["ping", "-c", "1", "8.8.8.8"],
                    capture_output=True,
                    timeout=3,
                    text=True
                )
            
            if result.returncode == 0:
                network_info["gateway_reachable"] = True
                # Extract latency if available (simplified)
                network_info["gateway_latency_ms"] = 50  # Placeholder, would parse from ping output
            else:
                network_info["gateway_reachable"] = False
        except Exception as e:
            logger.debug(f"Gateway check failed: {e}")
            network_info["gateway_reachable"] = None
        
    except Exception as e:
        logger.warning(f"Failed to collect network connectivity: {e}")
    
    return network_info


def collect_application_crashes() -> Dict[str, Any]:
    """
    Collect application crash information from OS (read-only).
    
    Returns:
        Dictionary with crash information.
    """
    crash_info = {
        "recent_crashes": [],
        "crash_count_24h": 0,
        "frequent_restarts": []
    }
    
    try:
        if is_macos():
            # Check macOS crash reports (read-only)
            import os
            crash_dir = os.path.expanduser("~/Library/Logs/DiagnosticReports")
            if os.path.exists(crash_dir):
                crash_files = []
                try:
                    for f in os.listdir(crash_dir):
                        if f.endswith(".crash") or f.endswith(".spin"):
                            crash_files.append(f)
                    crash_info["crash_count_24h"] = len(crash_files[:10])  # Sample recent
                except PermissionError:
                    logger.debug("No permission to read crash reports")
        
        elif is_linux():
            # Check systemd journal for crashes (read-only)
            try:
                result = subprocess.run(
                    ["journalctl", "--since", "24 hours ago", "--no-pager", "-q"],
                    capture_output=True,
                    timeout=5,
                    text=True
                )
                if result.returncode == 0:
                    # Count lines mentioning crashes/segfaults
                    crash_lines = [l for l in result.stdout.split('\n') 
                                 if 'segfault' in l.lower() or 'crash' in l.lower()]
                    crash_info["crash_count_24h"] = min(len(crash_lines), 10)
            except FileNotFoundError:
                logger.debug("journalctl not available")
            except Exception as e:
                logger.debug(f"Failed to check journal: {e}")
        
        elif is_windows():
            # Check Windows Event Log for application crashes (read-only)
            try:
                result = subprocess.run(
                    ["powershell", "-Command", 
                     "Get-WinEvent -FilterHashtable @{LogName='Application'; Level=2} -MaxEvents 10 -ErrorAction SilentlyContinue | Measure-Object | Select-Object -ExpandProperty Count"],
                    capture_output=True,
                    timeout=5,
                    text=True
                )
                if result.returncode == 0:
                    try:
                        crash_info["crash_count_24h"] = int(result.stdout.strip())
                    except ValueError:
                        pass
            except Exception as e:
                logger.debug(f"Failed to check Windows events: {e}")
    
    except Exception as e:
        logger.warning(f"Failed to collect application crash info: {e}")
    
    return crash_info


def collect_hardware_health() -> Dict[str, Any]:
    """
    Collect hardware health information (read-only).
    
    Returns:
        Dictionary with hardware health metrics.
    """
    hardware_info = {
        "disk_smart": {},
        "temperatures": {},
        "battery_cycles": None,
        "disk_io_errors": {}
    }
    
    try:
        # Disk SMART data (read-only)
        if is_linux():
            try:
                result = subprocess.run(
                    ["smartctl", "-a", "/dev/sda"],
                    capture_output=True,
                    timeout=5,
                    text=True
                )
                if result.returncode == 0:
                    hardware_info["disk_smart"]["available"] = True
                    hardware_info["disk_smart"]["status"] = "readable"
            except FileNotFoundError:
                hardware_info["disk_smart"]["available"] = False
            except Exception as e:
                logger.debug(f"SMART check failed: {e}")
        
        # Temperature readings
        try:
            temps = psutil.sensors_temperatures()
            if temps:
                for name, entries in temps.items():
                    if entries:
                        hardware_info["temperatures"][name] = entries[0].current
        except Exception as e:
            logger.debug(f"Temperature reading failed: {e}")
        
        # Battery cycles (if available)
        try:
            battery = psutil.sensors_battery()
            if battery:
                # Battery cycle count not directly available via psutil
                # Would require platform-specific APIs
                hardware_info["battery_cycles"] = None  # Not available via standard API
        except Exception as e:
            logger.debug(f"Battery info failed: {e}")
        
        # Disk I/O error counters
        try:
            disk_io = psutil.disk_io_counters(perdisk=True)
            if disk_io:
                for disk, io in disk_io.items():
                    hardware_info["disk_io_errors"][disk] = {
                        "read_errors": getattr(io, 'read_errors', 0),
                        "write_errors": getattr(io, 'write_errors', 0)
                    }
        except Exception as e:
            logger.debug(f"Disk I/O error check failed: {e}")
    
    except Exception as e:
        logger.warning(f"Failed to collect hardware health: {e}")
    
    return hardware_info


def collect_driver_stability() -> Dict[str, Any]:
    """
    Collect driver stability signals (read-only).
    
    Returns:
        Dictionary with driver stability information.
    """
    driver_info = {
        "driver_restarts": [],
        "load_failures": [],
        "device_resets": []
    }
    
    try:
        if is_linux():
            # Check dmesg for driver issues (read-only)
            try:
                result = subprocess.run(
                    ["dmesg", "-T", "-l", "err,warn"],
                    capture_output=True,
                    timeout=5,
                    text=True
                )
                if result.returncode == 0:
                    driver_errors = [l for l in result.stdout.split('\n') 
                                   if 'driver' in l.lower() or 'kernel' in l.lower()]
                    driver_info["driver_restarts"] = driver_errors[:5]  # Sample
            except FileNotFoundError:
                logger.debug("dmesg not available")
            except Exception as e:
                logger.debug(f"dmesg check failed: {e}")
        
        elif is_windows():
            # Check Windows Event Log for driver issues (read-only)
            try:
                result = subprocess.run(
                    ["powershell", "-Command",
                     "Get-WinEvent -FilterHashtable @{LogName='System'; ProviderName='*driver*'} -MaxEvents 5 -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Message"],
                    capture_output=True,
                    timeout=5,
                    text=True
                )
                if result.returncode == 0 and result.stdout.strip():
                    driver_info["driver_restarts"] = result.stdout.strip().split('\n')[:5]
            except Exception as e:
                logger.debug(f"Driver check failed: {e}")
        
        elif is_macos():
            # Check system.log for driver issues (read-only)
            try:
                result = subprocess.run(
                    ["log", "show", "--predicate", "subsystem == 'com.apple.kernel'", 
                     "--last", "1h", "--style", "compact"],
                    capture_output=True,
                    timeout=5,
                    text=True
                )
                if result.returncode == 0:
                    driver_errors = [l for l in result.stdout.split('\n') 
                                    if 'driver' in l.lower() or 'kernel' in l.lower()]
                    driver_info["driver_restarts"] = driver_errors[:5]
            except FileNotFoundError:
                logger.debug("log command not available")
            except Exception as e:
                logger.debug(f"Driver check failed: {e}")
    
    except Exception as e:
        logger.warning(f"Failed to collect driver stability: {e}")
    
    return driver_info


def collect_security_posture() -> Dict[str, Any]:
    """
    Collect basic security posture information (observational only).
    
    Returns:
        Dictionary with security posture metrics.
    """
    security_info = {
        "os_updates": None,
        "firewall_enabled": None,
        "disk_encryption": None
    }
    
    try:
        # OS update status
        if is_macos():
            try:
                result = subprocess.run(
                    ["softwareupdate", "-l"],
                    capture_output=True,
                    timeout=5,
                    text=True
                )
                if result.returncode == 0:
                    security_info["os_updates"] = "up_to_date" if "No new software available" in result.stdout else "pending"
            except Exception as e:
                logger.debug(f"Update check failed: {e}")
        
        elif is_linux():
            # Check if updates are available (read-only)
            try:
                # Try apt (Debian/Ubuntu)
                result = subprocess.run(
                    ["apt", "list", "--upgradable"],
                    capture_output=True,
                    timeout=5,
                    text=True
                )
                if result.returncode == 0:
                    upgradable = len([l for l in result.stdout.split('\n') if l and not l.startswith('Listing')])
                    security_info["os_updates"] = "up_to_date" if upgradable == 0 else "pending"
            except FileNotFoundError:
                logger.debug("apt not available")
            except Exception as e:
                logger.debug(f"Update check failed: {e}")
        
        elif is_windows():
            try:
                result = subprocess.run(
                    ["powershell", "-Command",
                     "Get-WindowsUpdate -ErrorAction SilentlyContinue | Select-Object -First 1"],
                    capture_output=True,
                    timeout=5,
                    text=True
                )
                # Simplified check
                security_info["os_updates"] = "unknown"
            except Exception as e:
                logger.debug(f"Update check failed: {e}")
        
        # Firewall status
        if is_macos():
            try:
                result = subprocess.run(
                    ["/usr/libexec/ApplicationFirewall/socketfilterfw", "--getglobalstate"],
                    capture_output=True,
                    timeout=3,
                    text=True
                )
                if result.returncode == 0:
                    security_info["firewall_enabled"] = "enabled" in result.stdout.lower()
            except Exception as e:
                logger.debug(f"Firewall check failed: {e}")
        
        elif is_linux():
            # Check iptables/ufw status
            try:
                result = subprocess.run(
                    ["ufw", "status"],
                    capture_output=True,
                    timeout=3,
                    text=True
                )
                if result.returncode == 0:
                    security_info["firewall_enabled"] = "active" in result.stdout.lower()
            except FileNotFoundError:
                logger.debug("ufw not available")
            except Exception as e:
                logger.debug(f"Firewall check failed: {e}")
        
        elif is_windows():
            try:
                result = subprocess.run(
                    ["netsh", "advfirewall", "show", "allprofiles", "state"],
                    capture_output=True,
                    timeout=3,
                    text=True
                )
                if result.returncode == 0:
                    security_info["firewall_enabled"] = "on" in result.stdout.lower()
            except Exception as e:
                logger.debug(f"Firewall check failed: {e}")
        
        # Disk encryption status
        if is_macos():
            # Check FileVault status
            try:
                result = subprocess.run(
                    ["fdesetup", "status"],
                    capture_output=True,
                    timeout=3,
                    text=True
                )
                if result.returncode == 0:
                    security_info["disk_encryption"] = "FileVault is On" in result.stdout
            except Exception as e:
                logger.debug(f"Encryption check failed: {e}")
        
        elif is_linux():
            # Check if LUKS is used
            try:
                result = subprocess.run(
                    ["lsblk", "-o", "TYPE,NAME"],
                    capture_output=True,
                    timeout=3,
                    text=True
                )
                if result.returncode == 0:
                    # Simplified check - would need more detailed parsing
                    security_info["disk_encryption"] = None  # Requires deeper inspection
            except Exception as e:
                logger.debug(f"Encryption check failed: {e}")
    
    except Exception as e:
        logger.warning(f"Failed to collect security posture: {e}")
    
    return security_info


def collect_all_extended_telemetry() -> Dict[str, Any]:
    """
    Collect all extended telemetry data.
    
    Returns:
        Dictionary containing all extended metrics.
    """
    logger.info("Collecting extended telemetry...")
    
    extended_telemetry = {
        "network": collect_network_connectivity(),
        "application_crashes": collect_application_crashes(),
        "hardware_health": collect_hardware_health(),
        "driver_stability": collect_driver_stability(),
        "security_posture": collect_security_posture()
    }
    
    logger.info("Extended telemetry collection completed")
    return extended_telemetry
