"""Systemd service definitions for the Pi Multi-FX Pedal.

Defines the pedal.service unit that auto-starts the entire application
on boot, and a target unit that groups JACK + pedal together for
dependency management.
"""

from __future__ import annotations

import logging
from pathlib import Path

logger = logging.getLogger(__name__)

# ── Paths ─────────────────────────────────────────────────────────────────────

PEDAL_SERVICE_PATH = Path("/etc/systemd/system/pi-multifx-pedal.service")
PEDAL_TARGET_PATH = Path("/etc/systemd/system/multi-fx-pedal.target")
JACK_SERVICE_PATH = Path("/etc/systemd/system/jackd.service")

PEDAL_USER = "pi"
PEDAL_GROUP = "audio"
PEDAL_INSTALL_DIR = Path("/opt/pi-multifx-pedal")
PEDAL_CONFIG_PATH = Path.home() / ".pedal" / "config.yaml"


# ── Service unit content ───────────────────────────────────────────────────────


def pedal_service_content(
    install_dir: str | Path = PEDAL_INSTALL_DIR,
    user: str = PEDAL_USER,
    group: str = PEDAL_GROUP,
) -> str:
    """Generate the pi-multifx-pedal.service unit content.

    Args:
        install_dir:  Installation directory (where main.py lives).
        user:         System user to run the service as.
        group:        System group (usually 'audio' for JACK/permissions).

    Returns:
        Complete systemd unit file as a string.
    """
    python_bin = f"{install_dir}/.venv/bin/python3"
    main_script = f"{install_dir}/main.py"

    return f"""# Pi Multi-FX Pedal — main application service
# Installed by scripts/install_service.sh
# Do not edit directly — regenerate from src/system/services.py

[Unit]
Description=Pi Multi-FX Pedal — real-time guitar multi-effects
Documentation=https://gitea.ourpad.casa/shawn/pi-multifx-pedal
After=jackd.service sound.target network.target
Wants=jackd.service
BindsTo=multi-fx-pedal.target

[Service]
Type=simple
User={user}
Group={group}
WorkingDirectory={install_dir}
ExecStartPre={python_bin} -c "from src.system.audio import _jack_is_running; import sys; sys.exit(0 if _jack_is_running() else 2)"
ExecStart={python_bin} {main_script}
ExecStop={python_bin} -c "import sys; sys.path.insert(0, '{install_dir}'); from main import PedalApp; PedalApp().shutdown()" 2>/dev/null || true
Restart=on-failure
RestartSec=3
TimeoutStartSec=30
TimeoutStopSec=10
KillMode=process

# Real-time audio priority
LimitRTPRIO=99
LimitMEMLOCK=infinity
LimitNICE=-20

# Environment
Environment=PYTHONUNBUFFERED=1
Environment=PEDAL_CONFIG={PEDAL_CONFIG_PATH}

[Install]
WantedBy=multi-fx-pedal.target
multi-user.target
"""


def pedal_target_content() -> str:
    """Generate the multi-fx-pedal.target unit content.

    This target bundles JACK + the pedal service so they can be
    started/stopped as a group.
    """
    return """# Pi Multi-FX Pedal — systemd target
# Groups JACK audio server + pedal application

[Unit]
Description=Pi Multi-FX Pedal — audio processing target
Documentation=https://gitea.ourpad.casa/shawn/pi-multifx-pedal
BindsTo=jackd.service pi-multifx-pedal.service
After=jackd.service pi-multifx-pedal.service

[Install]
WantedBy=multi-user.target
"""


# ── Service installation ──────────────────────────────────────────────────────


def install_services(install_dir: str | Path = PEDAL_INSTALL_DIR) -> bool:
    """Write service units to /etc/systemd/system and enable them.

    Requires root. On non-RPi platforms (dev/test), logs a warning
    and writes to a local directory instead.

    Args:
        install_dir:  Installation directory for ExecStart paths.

    Returns:
        True if services were installed and enabled.
    """
    import subprocess

    content = pedal_service_content(install_dir=install_dir)
    target_content = pedal_target_content()

    try:
        PEDAL_SERVICE_PATH.write_text(content)
        logger.info("Wrote %s", PEDAL_SERVICE_PATH)
    except PermissionError:
        logger.warning(
            "Need root to write %s. "
            "Run: sudo scripts/install_service.sh",
            PEDAL_SERVICE_PATH,
        )
        return False
    except OSError as exc:
        logger.error("Failed to write %s: %s", PEDAL_SERVICE_PATH, exc)
        return False

    try:
        PEDAL_TARGET_PATH.write_text(target_content)
        logger.info("Wrote %s", PEDAL_TARGET_PATH)
    except PermissionError:
        logger.warning("Need root to write %s", PEDAL_TARGET_PATH)
        return False
    except OSError as exc:
        logger.error("Failed to write %s: %s", PEDAL_TARGET_PATH, exc)
        return False

    try:
        subprocess.run(
            ["systemctl", "daemon-reload"],
            capture_output=True, timeout=10, check=True,
        )
        subprocess.run(
            ["systemctl", "enable", "pi-multifx-pedal.service"],
            capture_output=True, timeout=10, check=True,
        )
        subprocess.run(
            ["systemctl", "enable", "multi-fx-pedal.target"],
            capture_output=True, timeout=10, check=True,
        )
        logger.info("Services enabled: pi-multifx-pedal.service + multi-fx-pedal.target")
    except subprocess.CalledProcessError as exc:
        logger.warning("systemctl command failed: %s", exc)
        return False
    except FileNotFoundError:
        logger.warning("systemctl not found — not on a systemd system")
        return False

    return True


def uninstall_services() -> bool:
    """Disable and remove service units.

    Returns:
        True if services were removed.
    """
    import subprocess

    try:
        subprocess.run(
            ["systemctl", "disable", "pi-multifx-pedal.service"],
            capture_output=True, timeout=10,
        )
        subprocess.run(
            ["systemctl", "disable", "multi-fx-pedal.target"],
            capture_output=True, timeout=10,
        )
    except FileNotFoundError:
        pass

    for path in [PEDAL_SERVICE_PATH, PEDAL_TARGET_PATH]:
        if path.exists():
            try:
                path.unlink()
                logger.info("Removed %s", path)
            except OSError as exc:
                logger.warning("Could not remove %s: %s", path, exc)

    try:
        subprocess.run(
            ["systemctl", "daemon-reload"],
            capture_output=True, timeout=10,
        )
    except FileNotFoundError:
        pass

    return True