#!/usr/bin/env python3
"""Privileged Apt action helper for the Update Manager.

Installed path: /usr/libexec/um-actions-apt"""

from __future__ import annotations

import os
import subprocess
import sys
from pathlib import Path

APT_ENV = {
    **os.environ,
    "DEBIAN_FRONTEND": "noninteractive",
}

APT_DPKG_OPTIONS = [
    "-o", "Dpkg::Options::=--force-confdef",
    "-o", "Dpkg::Options::=--force-confold",
]


def run(argv: list[str], *, env: dict[str, str] | None = None) -> int:
    """Run argv directly without a shell."""
    try:
        return subprocess.run(argv, env=env, check=False).returncode
    except OSError as exc:
        print(f"Failed to run {' '.join(argv)}: {exc}", file=sys.stderr)
        return 1


def refresh() -> int:
    """Refresh APT package lists."""
    return run(["apt-get", "update", "-q"], env=APT_ENV)


def upgrade() -> int:
    """Run a full system upgrade."""
    return run(
        ["apt-get", "-y", *APT_DPKG_OPTIONS, "full-upgrade"],
        env=APT_ENV,
    )


def install(packages: list[str]) -> int:
    """Install or upgrade selected packages."""
    if not packages:
        return upgrade()

    return run(
        ["apt-get", "-y", *APT_DPKG_OPTIONS, "install", *packages],
        env=APT_ENV,
    )


def install_deb(path: str) -> int:
    """Install a local Debian package file."""
    deb_path = Path(path)

    if not deb_path.is_file():
        print(f"File not found: {path}", file=sys.stderr)
        return 1

    if deb_path.suffix.lower() != ".deb":
        print(f"Not a Debian package: {path}", file=sys.stderr)
        return 1

    return run(
        ["apt-get", "-y", *APT_DPKG_OPTIONS, "install", str(deb_path)],
        env=APT_ENV,
    )


def require_root() -> int:
    """Return 0 if running as root, otherwise non-zero."""
    if os.geteuid() == 0:
        return 0

    print("This helper must be run as root.", file=sys.stderr)
    return 1


def hold(package: str) -> int:
    """Mark a package as held."""
    return run(["apt-mark", "hold", package])


def unhold(package: str) -> int:
    """Remove hold from a package."""
    return run(["apt-mark", "unhold", package])


def reboot() -> int:
    """Reboot the system."""
    return run(["systemctl", "reboot"])


def usage() -> int:
    """Print usage and return failure."""
    print(
        "Usage:\n"
        "  um-actions-apt refresh\n"
        "  um-actions-apt upgrade\n"
        "  um-actions-apt install [PACKAGE ...]\n"
        "  um-actions-apt install-deb PATH\n"
        "  um-actions-apt hold PACKAGE\n"
        "  um-actions-apt unhold PACKAGE\n"
        "  um-actions-apt reboot",
        file=sys.stderr,
    )
    return 2


def main(argv: list[str]) -> int:
    """Dispatch privileged helper commands."""
    if require_root() != 0:
        return 1

    if len(argv) < 2:
        return usage()

    command = argv[1]
    args = argv[2:]

    if command == "refresh" and not args:
        return refresh()

    if command == "upgrade" and not args:
        return upgrade()

    if command == "install":
        return install(args)

    if command == "install-deb" and len(args) == 1:
        return install_deb(args[0])

    if command == "hold" and len(args) == 1:
        return hold(args[0])

    if command == "unhold" and len(args) == 1:
        return unhold(args[0])

    if command == "reboot" and not args:
        return reboot()

    return usage()


if __name__ == "__main__":
    raise SystemExit(main(sys.argv))
