"""Daemon and service-management helpers for the Bamboo Claw client CLI."""

from __future__ import annotations

import os
import platform
import shlex
import shutil
import subprocess
import sys
from pathlib import Path


SERVICE_NAME = "bamboo-claw.service"
SYSTEMD_UNIT_PATH = Path("/etc/systemd/system") / SERVICE_NAME


class DaemonError(RuntimeError):
    """Raised when daemon management operations cannot be completed."""


def render_systemd_unit(exec_start: str, working_dir: str) -> str:
    return "\n".join(
        [
            "[Unit]",
            "Description=Bamboo Claw Client Agent",
            "After=network-online.target",
            "Wants=network-online.target",
            "",
            "[Service]",
            "Type=simple",
            f"WorkingDirectory={working_dir}",
            f"ExecStart={exec_start}",
            "Restart=always",
            "RestartSec=5",
            "",
            "[Install]",
            "WantedBy=multi-user.target",
            "",
        ]
    )


def _ensure_systemd(require_root: bool) -> None:
    if platform.system() != "Linux":
        raise DaemonError("Daemon commands currently support Linux systemd only.")
    if shutil.which("systemctl") is None:
        raise DaemonError("systemctl is not available. Linux systemd is required.")
    if require_root and hasattr(os, "geteuid") and os.geteuid() != 0:
        raise DaemonError("Daemon install/uninstall requires root privileges (use sudo).")


def _run(cmd: list[str], check: bool = True) -> subprocess.CompletedProcess[str]:
    return subprocess.run(cmd, check=check, capture_output=True, text=True)


def install_service(config_path: Path | None = None) -> Path:
    _ensure_systemd(require_root=True)

    exec_start = f"{shlex.quote(sys.executable)} -m bamboo_claw_client.cli run"
    if config_path is not None:
        exec_start += f" --config {shlex.quote(str(config_path))}"
    unit_content = render_systemd_unit(exec_start=exec_start, working_dir=str(Path.cwd()))

    try:
        SYSTEMD_UNIT_PATH.parent.mkdir(parents=True, exist_ok=True)
        SYSTEMD_UNIT_PATH.write_text(unit_content, encoding="utf-8")
    except PermissionError as exc:
        raise DaemonError(
            f"Permission denied writing {SYSTEMD_UNIT_PATH}. Run command with sudo/root."
        ) from exc

    _run(["systemctl", "daemon-reload"])
    _run(["systemctl", "enable", "--now", SERVICE_NAME])
    return SYSTEMD_UNIT_PATH


def status_service() -> str:
    _ensure_systemd(require_root=False)
    result = _run(["systemctl", "status", SERVICE_NAME, "--no-pager", "--lines=12"], check=False)
    output = (result.stdout or "") + (result.stderr or "")
    return output.strip() or f"systemctl exited with code {result.returncode}"


def uninstall_service() -> None:
    _ensure_systemd(require_root=True)
    _run(["systemctl", "disable", "--now", SERVICE_NAME], check=False)
    if SYSTEMD_UNIT_PATH.exists():
        try:
            SYSTEMD_UNIT_PATH.unlink()
        except PermissionError as exc:
            raise DaemonError(
                f"Permission denied removing {SYSTEMD_UNIT_PATH}. Run command with sudo/root."
            ) from exc
    _run(["systemctl", "daemon-reload"])


def render_windows_bat(
    working_dir: str | None = None,
    venv_activate_path: str | None = None,
    config_path: str | None = None,
) -> str:
    wd = working_dir or str(Path.cwd())
    venv_activate = venv_activate_path or r"%~dp0\.venv\Scripts\activate.bat"
    run_cmd = "bambooclaw run"
    if config_path:
        run_cmd += f' --config "{config_path}"'

    lines = [
        "@echo off",
        "setlocal",
        f'cd /d "{wd}"',
        "",
        "REM Optional virtual environment activation",
        f'if exist "{venv_activate}" call "{venv_activate}"',
        "",
        run_cmd,
    ]
    return "\n".join(lines) + "\n"


def write_windows_bat(
    output_path: Path,
    working_dir: str | None = None,
    venv_activate_path: str | None = None,
    config_path: str | None = None,
) -> Path:
    content = render_windows_bat(
        working_dir=working_dir,
        venv_activate_path=venv_activate_path,
        config_path=config_path,
    )
    output_path.parent.mkdir(parents=True, exist_ok=True)
    output_path.write_text(content, encoding="utf-8")
    return output_path
