import logging
from abc import ABC, abstractmethod
from pathlib import Path
from typing import Self

from test_automation_suite.core.config import Config
from test_automation_suite.utility.cmd import execute_cmds

logger = logging.getLogger(__name__)


class Dependency(ABC):
    installation_path: Path
    name: str
    after_install_commands: list[str]

    def __init__(self, name: str, config: Config | None = None) -> None:
        config = config or Config()
        self.installation_path = config.dependency_installation_directory / name
        self.name = name
        self.after_install_commands = []

    @abstractmethod
    def _install(self) -> bool:
        return False

    def install(self) -> bool:
        if self.installed():
            logger.info("Already installed %s. Skipping installation...", self.name)
            return True

        logger.info("Installing %s...", self.name)

        _install_success = self._install()

        after_install_commands_success = execute_cmds(self.after_install_commands)

        installed = self.installed()

        success = _install_success and installed and after_install_commands_success

        if success:
            logger.info("Installed %s successfully.", self.name)
        else:
            logger.error("Installation of %s failed.", self.name)

        return success

    def installed(self) -> bool:
        return self.installation_path.is_dir()

    def add_after_install_command(self, command: str) -> Self:
        self.after_install_commands.append(
            command.replace("{{installation_path}}", str(self.installation_path)),
        )
        return self

    def add_after_install_commands(self, commands: list[str]) -> Self:
        for command in commands:
            self.add_after_install_command(command)
        return self
