import logging
import os
import subprocess
from pathlib import Path

from .config_parser import ConfigEntryType
from .state_manager import mark_installed, is_already_installed

logger = logging.getLogger(__name__)
packages_logger = logging.getLogger(f"{__name__.split('.', 1)[0]}.scripts")

SCRIPT_BASE_PATH = Path("/usr/libexec/tuxedo-tomte")


def manage_scripts(scripts: set[str], package_manager_bin_name: str) -> None:
    logger.info(f"Scripts required by hardware: {sorted(scripts)}")

    found_scripts: set[str] = set()
    for script in scripts:
        if is_already_installed(script, ConfigEntryType.SCRIPT):
            logger.debug(f"Skipping {script}")
            continue
        if script_exists(script):
            found_scripts.add(script)
        else:
            logger.error(
                f"Script '{script}' can not be found and therefore not be installed!"
            )

    for script in found_scripts:
        if execute_script(script, package_manager_bin_name):
            if mark_installed(script, ConfigEntryType.SCRIPT):
                logger.info(f"[OK] Installed {script}")
            else:
                logger.error(f"[FAILED] to mark {script} as installed")
        else:
            logger.error(f"Script '{script}' failed to execute!")


def script_exists(script_name: str) -> bool:
    """Checks whether a script exists and is executable"""
    logger.debug(f"Checking if script exists: {script_name}")

    if Path(script_name).name != script_name:
        logger.error(f"Script does not exist or is not executable: {script_name}")
        return False

    script_path = SCRIPT_BASE_PATH / script_name

    return script_path.is_file() and os.access(script_path, os.X_OK)


def execute_script(script_name: str, package_manager_bin_name: str) -> bool:
    """Execute a script from SCRIPT_BASE_PATH if it exists and is executable."""
    logger.info(f"Executing script: {script_name}")

    if not script_exists(script_name):
        logger.error(f"Script does not exist or is not executable: {script_name}")
        return False

    script_path = SCRIPT_BASE_PATH / script_name

    try:
        result = subprocess.run(
            [str(script_path), package_manager_bin_name],
            check=False,
            capture_output=True,
            text=True,
        )
    except OSError:
        logger.exception(f"Failed to execute script: {script_name}")
        return False

    if result.stdout:
        packages_logger.info(result.stdout.strip())

    if result.stderr:
        packages_logger.warning(result.stderr.strip())

    if result.returncode != 0:
        logger.error(f"Script failed with exit code {result.returncode}: {script_name}")
        return False

    logger.info(f"Script executed successfully: {script_name}")
    return True
