"""
Module: skill_catalog.py

Description:
This module builds and maintains a catalog of available skills within the Genesis system.
It provides a centralized location to discover and access skill metadata, including
their names, descriptions, capabilities, input parameters, and output formats.

This catalog is crucial for skill discovery, orchestration, and automated task execution
within the Genesis system.
"""

import logging
import json
import os
from typing import Dict, Any, List

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

class SkillCatalog:
    """
    A catalog of available skills within the Genesis system.
    """

    def __init__(self, catalog_file: str = "/mnt/e/genesis-system/core/knowledge/skill_catalog.json"):
        """
        Initializes the SkillCatalog.

        Args:
            catalog_file (str, optional): The path to the JSON file containing the skill catalog data.
                                           Defaults to "/mnt/e/genesis-system/core/knowledge/skill_catalog.json".
        """
        self.catalog_file = catalog_file
        self.skills: Dict[str, Dict[str, Any]] = {}
        self.load_catalog()

    def load_catalog(self) -> None:
        """
        Loads the skill catalog from the JSON file.
        """
        try:
            if not os.path.exists(self.catalog_file):
                logging.warning(f"Skill catalog file not found: {self.catalog_file}. Creating an empty catalog.")
                self.skills = {}
                self.save_catalog()  # Save an empty catalog to the file
                return

            with open(self.catalog_file, 'r') as f:
                self.skills = json.load(f)
            logging.info(f"Skill catalog loaded successfully from {self.catalog_file}")

        except FileNotFoundError:
            logging.error(f"Skill catalog file not found: {self.catalog_file}")
        except json.JSONDecodeError as e:
            logging.error(f"Error decoding skill catalog JSON: {e}")
        except Exception as e:
            logging.error(f"Error loading skill catalog: {e}")

    def save_catalog(self) -> None:
        """
        Saves the skill catalog to the JSON file.
        """
        try:
            # Ensure the directory exists
            os.makedirs(os.path.dirname(self.catalog_file), exist_ok=True)

            with open(self.catalog_file, 'w') as f:
                json.dump(self.skills, f, indent=4)
            logging.info(f"Skill catalog saved successfully to {self.catalog_file}")

        except Exception as e:
            logging.error(f"Error saving skill catalog: {e}")

    def add_skill(self, skill_name: str, skill_data: Dict[str, Any]) -> None:
        """
        Adds a skill to the catalog.

        Args:
            skill_name (str): The name of the skill.
            skill_data (Dict[str, Any]): The skill's metadata (description, capabilities, etc.).
        """
        if skill_name in self.skills:
            logging.warning(f"Skill '{skill_name}' already exists in the catalog. Overwriting.")
        self.skills[skill_name] = skill_data
        self.save_catalog()
        logging.info(f"Skill '{skill_name}' added to the catalog.")

    def remove_skill(self, skill_name: str) -> None:
        """
        Removes a skill from the catalog.

        Args:
            skill_name (str): The name of the skill to remove.
        """
        if skill_name in self.skills:
            del self.skills[skill_name]
            self.save_catalog()
            logging.info(f"Skill '{skill_name}' removed from the catalog.")
        else:
            logging.warning(f"Skill '{skill_name}' not found in the catalog.")

    def get_skill(self, skill_name: str) -> Dict[str, Any]:
        """
        Retrieves a skill from the catalog.

        Args:
            skill_name (str): The name of the skill to retrieve.

        Returns:
            Dict[str, Any]: The skill's metadata, or an empty dictionary if the skill is not found.
        """
        if skill_name in self.skills:
            return self.skills[skill_name]
        else:
            logging.warning(f"Skill '{skill_name}' not found in the catalog.")
            return {}

    def list_skills(self) -> List[str]:
        """
        Lists all skill names in the catalog.

        Returns:
            List[str]: A list of skill names.
        """
        return list(self.skills.keys())

    def update_skill(self, skill_name: str, skill_data: Dict[str, Any]) -> None:
          """
          Updates a skill's metadata in the catalog.

          Args:
              skill_name (str): The name of the skill to update.
              skill_data (Dict[str, Any]): The updated skill metadata.
          """
          if skill_name in self.skills:
              self.skills[skill_name].update(skill_data)
              self.save_catalog()
              logging.info(f"Skill '{skill_name}' updated in the catalog.")
          else:
              logging.warning(f"Skill '{skill_name}' not found in the catalog. Cannot update.")

if __name__ == '__main__':
    # Example usage
    catalog = SkillCatalog()

    # Add a skill
    skill_data = {
        "description": "A skill that greets the user.",
        "capabilities": ["greeting"],
        "input_parameters": {"name": "string"},
        "output_format": "string"
    }
    catalog.add_skill("greet_user", skill_data)

    # Get a skill
    greet_skill = catalog.get_skill("greet_user")
    print(f"Greet skill: {greet_skill}")

    # List all skills
    all_skills = catalog.list_skills()
    print(f"All skills: {all_skills}")

    # Update a skill
    updated_skill_data = {"description": "A skill that greets the user by their full name."}
    catalog.update_skill("greet_user", updated_skill_data)
    greet_skill = catalog.get_skill("greet_user")
    print(f"Updated greet skill: {greet_skill}")

    # Remove a skill
    catalog.remove_skill("greet_user")
    all_skills = catalog.list_skills()
    print(f"All skills after removing greet_user: {all_skills}")

    # Save the catalog
    catalog.save_catalog()