import subprocess
import time
import urllib.request
import urllib.error
import logging
from typing import Dict, List

logger = logging.getLogger(__name__)

class AutoHealer:
    def __init__(self, config=None, *, ollama_url: str = "http://localhost:11434"):
        if config is not None:
            self.ollama_url = getattr(config, "ollama_url", ollama_url)
        else:
            self.ollama_url = ollama_url
        self._stop = False

    def start_monitoring(self, interval: int = 30):
        """Run health checks in a loop. Designed to run in a daemon thread."""
        self._stop = False
        while not self._stop:
            self.check_and_restart_ollama()
            time.sleep(interval)

    def stop_monitoring(self):
        """Signal the monitoring loop to stop."""
        self._stop = True

    def check_and_restart_ollama(self) -> bool:
        """
        Checks if Ollama is running, and attempts to restart it if not.
        Returns True if it was running or successfully restarted, False otherwise.
        """
        is_running = False
        try:
            req = urllib.request.Request(self.ollama_url)
            with urllib.request.urlopen(req, timeout=2) as response:
                if response.status == 200:
                    is_running = True
        except (urllib.error.URLError, ConnectionError, ValueError):
            pass

        if not is_running:
            logger.warning("Ollama is not responding. Attempting to restart...")
            return self._restart_ollama()
        
        return True

    def _restart_ollama(self) -> bool:
        """
        Mocks the restart of Ollama.
        """
        try:
            # In a real scenario, this might be `systemctl restart ollama` or similar.
            # We mock the restart command here.
            subprocess.run(["echo", "Restarting Ollama..."], check=True, capture_output=True)
            logger.info("Ollama restart command issued successfully.")
            return True
        except subprocess.CalledProcessError as e:
            logger.error(f"Failed to restart Ollama: {e}")
            return False

    def verify_mcp_connections(self, endpoints: List[str]) -> Dict[str, bool]:
        """
        Pings MCP endpoints and "reboots" if failed.
        """
        results = {}
        for endpoint in endpoints:
            is_up = False
            try:
                # Dummy ping, simulating an HTTP check
                req = urllib.request.Request(endpoint)
                with urllib.request.urlopen(req, timeout=2) as response:
                    # Treat any valid HTTP response as up
                    is_up = True
            except (urllib.error.HTTPError, urllib.error.URLError, ConnectionError, ValueError) as e:
                if isinstance(e, urllib.error.HTTPError):
                    # HTTP error (e.g., 404, 500) still means the server is responding to some extent, 
                    # but we can consider a 5xx as failed. We'll be conservative and assume only network errors trigger reboot
                    is_up = True
                else:
                    is_up = False
            
            if not is_up:
                logger.warning(f"MCP endpoint {endpoint} failed. Issuing reboot...")
                success = self._reboot_mcp(endpoint)
                results[endpoint] = success
            else:
                results[endpoint] = True
                
        return results

    def _reboot_mcp(self, endpoint: str) -> bool:
        """
        Mocks the reboot of an MCP endpoint.
        """
        try:
            subprocess.run(["echo", f"Rebooting MCP {endpoint}..."], check=True, capture_output=True)
            logger.info(f"Rebooted MCP {endpoint}")
            return True
        except subprocess.CalledProcessError as e:
            logger.error(f"Failed to reboot MCP {endpoint}: {e}")
            return False
