from ..output import debug
from ..exceptions import SysCallError
import subprocess
import shlex
import os

class Aria2Backend:
    def __init__(self, target):
        self.target = target
        self.download_dir = "/tmp/archinstall_pkg_cache"

    def _run_command(self, cmd):
        cmd = shlex.split(cmd)
        try:
            # We don't use archinstall.run_command here to avoid circular dependencies
            process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            stdout, stderr = process.communicate()

            if process.returncode != 0:
                raise SysCallError(f"Command '{' '.join(cmd)}' failed with exit code {process.returncode}", exit_code=process.returncode, stderr=stderr)

            return stdout.decode().strip().split('\n')
        except FileNotFoundError:
            raise SysCallError(f"Command '{cmd[0]}' not found.", exit_code=1)

    def _get_package_urls(self, packages):
        debug(f"Getting package URLs for: {packages}")
        cmd = f"pacman -Sp --noconfirm {' '.join(packages)}"
        urls = self._run_command(cmd)
        return [url for url in urls if url]

    def _download_packages(self, urls):
        debug(f"Downloading packages with aria2c")
        os.makedirs(self.download_dir, exist_ok=True)
        url_string = ' '.join(urls)
        cmd = f"aria2c --dir={self.download_dir} -x 16 -s 16 -k 1M {url_string}"
        self._run_command(cmd)

    def _install_packages(self, package_files):
        debug(f"Installing packages with pacman -U")
        package_files_string = ' '.join(package_files)
        cmd = f"pacman -U --noconfirm --root {self.target} {package_files_string}"
        self._run_command(cmd)

    def install(self, packages):
        debug(f"Using aria2 backend to install packages: {packages}")
        
        urls = self._get_package_urls(packages)
        package_files = [os.path.join(self.download_dir, url.split('/')[-1]) for url in urls]
        
        self._download_packages(urls)
        self._install_packages(package_files)
        
        # Clean up the downloaded packages
        for package_file in package_files:
            os.remove(package_file)
        
        debug("aria2 backend finished.")
        pass
