"""macOS launchd service backend.

Writes user-level plist files to ``~/Library/LaunchAgents/`` so no root is
required.  ``KeepAlive`` is false because konstant manages restarts itself.
"""

from __future__ import annotations

import plistlib
import subprocess
import sys
from pathlib import Path
from typing import Optional

from konstant.config import ServiceConfig

_AGENTS_DIR = Path.home() / "Library" / "LaunchAgents"


def _label(service_name: str) -> str:
    return f"com.konstant.{service_name}"


def _plist_path(service_name: str) -> Path:
    return _AGENTS_DIR / f"{_label(service_name)}.plist"


def _effective_config_path(config: ServiceConfig, config_path: Optional[Path]) -> Path:
    if config_path is not None:
        return config_path.resolve()
    return (config.resolved_cwd / "konstant.toml").resolve()


def _build_plist(config: ServiceConfig, config_path: Optional[Path]) -> dict:
    cwd = config.resolved_cwd
    cfg_path = _effective_config_path(config, config_path)
    program_args = [
        sys.executable,
        "-m",
        "konstant.cli",
        "start",
        config.name,
        "--fg",
        "--config",
        str(cfg_path),
    ]

    return {
        "Label": _label(config.name),
        "ProgramArguments": program_args,
        "WorkingDirectory": str(cwd),
        "RunAtLoad": True,
        "KeepAlive": False,
        "StandardOutPath": str(cwd / "logs" / f"{config.name}.stdout.log"),
        "StandardErrorPath": str(cwd / "logs" / f"{config.name}.stderr.log"),
    }


def install_service(
    config: ServiceConfig,
    user: Optional[str] = None,
    password: Optional[str] = None,
    config_path: Optional[Path] = None,
) -> None:
    """Write a launchd plist and load it."""
    _AGENTS_DIR.mkdir(parents=True, exist_ok=True)
    (config.resolved_cwd / "logs").mkdir(parents=True, exist_ok=True)
    plist = _build_plist(config, config_path)
    plist_path = _plist_path(config.name)
    with open(plist_path, "wb") as f:
        plistlib.dump(plist, f)
    subprocess.run(
        ["launchctl", "load", str(plist_path)],
        check=True,
        capture_output=True,
    )


def uninstall_service(service_name: str) -> None:
    """Unload and remove a launchd plist."""
    plist_path = _plist_path(service_name)
    if plist_path.exists():
        try:
            subprocess.run(
                ["launchctl", "unload", str(plist_path)],
                check=True,
                capture_output=True,
            )
        except subprocess.CalledProcessError:
            pass  # may already be unloaded
        plist_path.unlink()
