import os
import platform
import abc
import subprocess
import sys

class BaseServiceManager(abc.ABC):
    """Abstract Base Class for Platform-Specific Service Management."""
    
    @abc.abstractmethod
    def install(self, python_path, script_path, working_dir) -> bool:
        """Installs the agent as a background service/daemon."""
        pass

    @abc.abstractmethod
    def uninstall(self) -> bool:
        """Removes the agent service."""
        pass

    @abc.abstractmethod
    def is_installed(self) -> bool:
        """Checks if the service is currently registered."""
        pass

    @abc.abstractmethod
    def start(self) -> bool:
        """Starts the service."""
        pass

    @abc.abstractmethod
    def stop(self) -> bool:
        """Stops the service."""
        pass


class LaunchdManager(BaseServiceManager):
    """macOS implementation using launchd."""
    LABEL = "com.jerxie.cortex.agent"
    
    def _get_plist_path(self):
        return os.path.expanduser(f"~/Library/LaunchAgents/{self.LABEL}.plist")

    def install(self, python_path, script_path, working_dir) -> bool:
        plist_content = f"""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>{self.LABEL}</string>
    <key>ProgramArguments</key>
    <array>
        <string>{python_path}</string>
        <string>{script_path}</string>
    </array>
    <key>WorkingDirectory</key>
    <string>{working_dir}</string>
    <key>KeepAlive</key>
    <true/>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardErrorPath</key>
    <string>{os.path.expanduser("~")}/.cortex/agent.err.log</string>
    <key>StandardOutPath</key>
    <string>{os.path.expanduser("~")}/.cortex/agent.out.log</string>
</dict>
</plist>
"""
        path = self._get_plist_path()
        os.makedirs(os.path.dirname(path), exist_ok=True)
        with open(path, "w") as f:
            f.write(plist_content)
        
        try:
            subprocess.run(["launchctl", "load", path], check=True)
            return True
        except:
            return False

    def uninstall(self) -> bool:
        path = self._get_plist_path()
        if os.path.exists(path):
            subprocess.run(["launchctl", "unload", path], capture_output=True)
            os.remove(path)
            return True
        return False

    def is_installed(self) -> bool:
        return os.path.exists(self._get_plist_path())

    def start(self) -> bool:
        try:
            subprocess.run(["launchctl", "load", self._get_plist_path()], check=True)
            return True
        except:
            return False

    def stop(self) -> bool:
        try:
            subprocess.run(["launchctl", "unload", self._get_plist_path()], check=True)
            return True
        except:
            return False


class SystemdManager(BaseServiceManager):
    """Linux implementation using systemd user services."""
    SERVICE_NAME = "cortex-agent"
    
    def _get_service_path(self):
        return os.path.expanduser(f"~/.config/systemd/user/{self.SERVICE_NAME}.service")

    def install(self, python_path, script_path, working_dir) -> bool:
        content = f"""[Unit]
Description=Cortex Agent Node
After=network.target

[Service]
Type=simple
ExecStart={python_path} {script_path}
WorkingDirectory={working_dir}
Restart=always
RestartSec=5
StandardOutput=append:{os.path.expanduser("~")}/.cortex/agent.out.log
StandardError=append:{os.path.expanduser("~")}/.cortex/agent.err.log

[Install]
WantedBy=default.target
"""
        path = self._get_service_path()
        os.makedirs(os.path.dirname(path), exist_ok=True)
        with open(path, "w") as f:
            f.write(content)
            
        try:
            subprocess.run(["systemctl", "--user", "daemon-reload"], check=True)
            subprocess.run(["systemctl", "--user", "enable", self.SERVICE_NAME], check=True)
            subprocess.run(["systemctl", "--user", "start", self.SERVICE_NAME], check=True)
            return True
        except:
            return False

    def uninstall(self) -> bool:
        try:
            subprocess.run(["systemctl", "--user", "stop", self.SERVICE_NAME], capture_output=True)
            subprocess.run(["systemctl", "--user", "disable", self.SERVICE_NAME], capture_output=True)
            path = self._get_service_path()
            if os.path.exists(path):
                os.remove(path)
            return True
        except:
            return False

    def is_installed(self) -> bool:
        return os.path.exists(self._get_service_path())

    def start(self) -> bool:
        return subprocess.run(["systemctl", "--user", "start", self.SERVICE_NAME]).returncode == 0

    def stop(self) -> bool:
        return subprocess.run(["systemctl", "--user", "stop", self.SERVICE_NAME]).returncode == 0


class SchtasksManager(BaseServiceManager):
    """Windows implementation using Task Scheduler (schtasks)."""
    TASK_NAME = "CortexAgent"

    def install(self, python_path, script_path, working_dir) -> bool:
        ps_cmd = f"""
        $Action = New-ScheduledTaskAction -Execute '{python_path}' -Argument '"{script_path}"' -WorkingDirectory '{working_dir}'
        $Trigger = New-ScheduledTaskTrigger -AtStartup
        Register-ScheduledTask -TaskName '{self.TASK_NAME}' -Action $Action -Trigger $Trigger -User "SYSTEM" -RunLevel Highest -Force
        """
        try:
            subprocess.run(["powershell", "-Command", ps_cmd], check=True, capture_output=True)
            # Start it immediately
            subprocess.run(["schtasks", "/Run", "/TN", self.TASK_NAME], check=True, capture_output=True)
            return True
        except Exception as e:
            if hasattr(e, "stderr") and e.stderr:
                print(f"Error installing Windows task: {e.stderr.decode('utf-8', errors='ignore')}")
            else:
                print(f"Error installing Windows task: {e}")
            return False

    def uninstall(self) -> bool:
        try:
            subprocess.run(["schtasks", "/Delete", "/TN", self.TASK_NAME, "/F"], capture_output=True)
            return True
        except:
            return False

    def is_installed(self) -> bool:
        r = subprocess.run(["schtasks", "/Query", "/TN", self.TASK_NAME], capture_output=True)
        return r.returncode == 0

    def start(self) -> bool:
        return subprocess.run(["schtasks", "/Run", "/TN", self.TASK_NAME]).returncode == 0

    def stop(self) -> bool:
        return subprocess.run(["schtasks", "/End", "/TN", self.TASK_NAME]).returncode == 0


def get_service_manager() -> BaseServiceManager:
    """Factory to get the platform-appropriate service manager."""
    sys_type = platform.system().lower()
    if sys_type == "darwin":
        return LaunchdManager()
    elif sys_type == "windows":
        return SchtasksManager()
    else:
        # Fallback to systemd for Linux
        return SystemdManager()
