#!/usr/bin/env python3
"""
Handle packages

Author: Arjen Balfoort
Date: 2026-02-24
"""

import os
import sys
import subprocess

# If set to True, no changes will be made
DEBUG = False


def run_command(command: list):
    """
    Run a command and print its output.
    The print is flushed to ensure that the output is immediately
    visible and can be used by the PackageManagerThread class.
    """
    print(f"Running command: {' '.join(command)}", flush=True)

    # stdbuf -oL forces line buffering for the output of apt-get.
    command = ["stdbuf", "-oL"] + command

    try:
        # Get the current environment and update it
        env = os.environ.copy()
        env['DEBIAN_FRONTEND'] = 'noninteractive'

        with subprocess.Popen(
            command,
            env=env,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            universal_newlines=True,
            bufsize=1
        ) as process:
            for line in process.stdout:
                print(line.strip(), flush=True)
            process.wait()
            if process.returncode != 0:
                print(f"Error: Command failed with return code {process.returncode}", flush=True)
                sys.exit(1)
    except Exception as e:
        print(f"Error: {e}", flush=True)
        sys.exit(1)

def main():
    if len(sys.argv) < 2:
        print("Usage: python3 packages_sudo.py <install/remove/hold/unhold> <package01> <package02>", flush=True)
        sys.exit(1)

    action = sys.argv[1]
    packages = sys.argv[2:]
    debug = ["--dry-run"] if DEBUG else []

    script_dir = os.path.dirname(os.path.abspath(__file__))
    external_dir = os.path.join(script_dir, "external")
    for package in packages:
        external = os.path.join(external_dir, f"{package}.sh")
        if os.path.exists(external):
            run_command(["bash", external])
            packages.remove(package)
            if not packages:
                return

    # Build and run the command
    apt_options = ['--yes',
                   '-o',
                   'Dpkg::Options::=--force-confdef',
                   '-o',
                   'Dpkg::Options::=--force-confold']
    if action == 'install':
        run_command(["apt-get", "install"] + apt_options + debug + packages)
    elif action == 'remove':
        run_command(["apt-get", "purge"] + apt_options + debug + packages)
        run_command(["apt-get", "autoremove"] + apt_options + debug)
    elif action == 'hold':
        run_command(["apt-mark", "hold"] + packages)
    elif action == 'unhold':
        run_command(["apt-mark", "unhold"] + packages)

if __name__ == "__main__":
    main()
