"""Helpers for installing the worker as a per-user macOS LaunchAgent."""

from __future__ import annotations

import os
import platform
import plistlib
import re
import shutil
import subprocess
import sys
from pathlib import Path


def service_label_for_worker(worker_id: str) -> str:
    sanitized = re.sub(r"[^A-Za-z0-9._-]+", "-", worker_id).strip("-.") or "worker"
    return f"com.hivecompute.worker.{sanitized}"


def launch_agent_path(worker_id: str) -> Path:
    return launch_agent_dir() / f"{service_label_for_worker(worker_id)}.plist"


def launch_agent_dir() -> Path:
    return Path("~/Library/LaunchAgents").expanduser()


def worker_log_dir() -> Path:
    return Path("~/.ambient/logs").expanduser()


def _resolve_hive_cli() -> str:
    """Find the installed 'hive' entry point, falling back to python -m."""
    found = shutil.which("hive")
    if found:
        return found
    # Fallback: check alongside the running Python (e.g. .venv/bin/hive)
    venv_hive = Path(sys.executable).parent / "hive"
    if venv_hive.exists():
        return str(venv_hive)
    return sys.executable  # last resort


def build_launch_agent_plist(worker_id: str, config_path: str, python_executable: str | None = None) -> dict:
    config = str(Path(config_path).expanduser())
    hive_cli = python_executable or _resolve_hive_cli()
    label = service_label_for_worker(worker_id)
    logs = worker_log_dir()

    # If we found the hive entry point, use it directly; otherwise fall back to python -m
    if hive_cli.endswith("/hive") or hive_cli.endswith("\\hive"):
        program_args = [hive_cli, "start", "--config", config]
    else:
        program_args = [hive_cli, "-m", "hive_compute.cli", "start", "--config", config]

    return {
        "Label": label,
        "ProgramArguments": program_args,
        "RunAtLoad": True,
        "KeepAlive": True,
        "WorkingDirectory": str(Path(config).parent),
        "StandardOutPath": str(logs / f"{label}.out.log"),
        "StandardErrorPath": str(logs / f"{label}.err.log"),
        "EnvironmentVariables": {
            "PYTHONUNBUFFERED": "1",
            "PATH": _build_service_path(),
        },
        "ProcessType": "Background",
    }


def install_launch_agent(worker_id: str, config_path: str, python_executable: str | None = None) -> tuple[str, Path]:
    _ensure_launchd_available()
    label = service_label_for_worker(worker_id)
    plist_path = launch_agent_path(worker_id)

    plist_path.parent.mkdir(parents=True, exist_ok=True)
    worker_log_dir().mkdir(parents=True, exist_ok=True)
    plist_path.write_bytes(plistlib.dumps(build_launch_agent_plist(worker_id, config_path, python_executable)))

    domain = f"gui/{os.getuid()}"
    subprocess.run(
        ["launchctl", "bootout", domain, str(plist_path)],
        check=False,
        capture_output=True,
        text=True,
    )
    subprocess.run(
        ["launchctl", "bootstrap", domain, str(plist_path)],
        check=True,
        capture_output=True,
        text=True,
    )
    return label, plist_path


def uninstall_launch_agent(worker_id: str) -> tuple[str, Path]:
    _ensure_launchd_available()
    label = service_label_for_worker(worker_id)
    plist_path = launch_agent_path(worker_id)
    domain = f"gui/{os.getuid()}"

    subprocess.run(
        ["launchctl", "bootout", domain, str(plist_path)],
        check=False,
        capture_output=True,
        text=True,
    )
    plist_path.unlink(missing_ok=True)
    return label, plist_path


def _build_service_path() -> str:
    """Build a PATH for the LaunchAgent that always includes Homebrew."""
    base = os.environ.get("PATH", "/usr/local/bin:/usr/bin:/bin")
    required = ["/opt/homebrew/bin", "/usr/local/bin"]
    parts = base.split(":")
    for p in required:
        if p not in parts:
            parts.append(p)
    return ":".join(parts)


def _ensure_launchd_available() -> None:
    if platform.system() != "Darwin" or not shutil.which("launchctl"):
        raise RuntimeError("launchd service management requires macOS and the 'launchctl' CLI")
