# MOTHER CLASS
from command import Command

# DEPENDANCIES

# UTILS 
from utils import load_classes_from_relative_dir
# OTHER
import variables
import os

class Agents(Command):
    """
    Superclass for managing different types of agents with logging and configuration capabilities.
    """
    
    _instances = {}

    
    def __init__(self, name: str, ip_address: str, category: str,**kwargs):
        """
        Initialize the Agents class.

        Args:
            name (str): The name of the agent.
            ip_address (str): The IP address of the agent.
            category (str): The category of the agent (e.g., 'attacker', 'defender').
        """
        category = category.lower()

        # Dynamically detect valid types based on folder structure

        self.VALID_TYPES = self._detect_valid_types()

        # Assert that the category is valid
        assert category in self.VALID_TYPES, f"Invalid category: {category}. Valid types are: {self.VALID_TYPES}"

        log_file = f"{category}.log"

        super().__init__(log_file=log_file,**kwargs)

        self.name = name
        self.ip_address = ip_address
        self.agent_type = category
        self.is_agent = (self.agent_type != 'manager') # Boolean , is it a manager or a wazuh agent ? 
        
        # HERE : Public dependancies to automatically configure #
        # INFO order matters !
        
        # Dynamically create an instance of the corresponding class : | Attacker , Defender, Manager
        self.category = self._create_instance()

        # Register the instance with the Agents superclass
        self._register_instance(self)

        # HERE : Private class to automatically configure #

    def _detect_valid_types(self) -> list:
        """
        Dynamically detect valid types based on the folder structure.
        """
        base_dir = os.path.dirname(__file__)
        base_dir = os.path.join(base_dir, variables.PATH_TO_AGENT_TYPES_DIR)
        valid_types = []
        for item in os.listdir(base_dir):

            item_path = os.path.join(base_dir, item)
            if os.path.isdir(item_path):
                type_name = item.capitalize().lower()
                valid_types.append(type_name)
        return valid_types

    def _create_instance(self): 
        """
        Dynamically create an instance of the corresponding class based on the self.agent_type.
        """
        module_name = self.agent_type
        class_instance = load_classes_from_relative_dir(__file__,os.path.join(variables.PATH_TO_AGENT_TYPES_DIR,module_name))

        return class_instance[0]
    
    @classmethod
    def _register_instance(cls, instance: 'Agents'):
        """
        Register an agent instance with the Agents superclass.
        """
        cls._instances[instance.agent_type] = instance

    @classmethod
    def get_instance(cls, agent_type:str):
        """
        Get an agent instance by type ['attacker','defender',...].
        """
        return cls._instances.get(agent_type)

    def get_evaluator(self) -> 'Agents':
        """
        Get the Evaluator agent instance.
        """
        return self.get_instance('evaluator')
    
    def get_attacker(self) -> 'Agents':
        """
        Get the Attacker agent instance.
        """
        return self.get_instance('attacker')

    def get_defender(self) -> 'Agents':
        """
        Get the Defender agent instance.
        """
        return self.get_instance('defender')

    def get_manager(self) -> 'Agents':
        """
        Get the Manager agent instance.
        """
        return self.get_instance('manager')

    def get_all_instances(self) -> dict:
        """
        Get all registered agent instances.
        """
        return self._instances

    def initialize(self):
        pass

    def start(self):
        pass

    def stop(self):
        pass

    def interact_with_llm(self):
        pass

    def modify_ossec(self):
        pass