"""
Unified Toolkit Factory for Pixel Agents
This module provides a centralized way to manage and register tools and skills for agents.
"""

import logging
import os
from pathlib import Path
from typing import List, Optional, Dict, Any
from agentscope.tool import Toolkit

logger = logging.getLogger(__name__)

class ToolkitFactory:
    """
    Factory for creating configured Toolkits for agents.
    Supports caching and dynamic skill loading.
    """
    
    # Removed caching to prevent tool registration conflicts when multiple agents 
    # use the same toolkit configuration but register their own instance-specific tools (e.g. PlanNotebook)
    # _instances: Dict[tuple, Toolkit] = {}

    @classmethod
    def clear_cache(cls):
        """Clear all cached Toolkit instances."""
        # Cache disabled
        pass

    @classmethod
    def get_toolkit(cls, skill_domains: Optional[List[str]] = None, user_id: Optional[str] = None) -> Toolkit:
        """
        Get a new Toolkit instance configured with the specified skill domains.

        Args:
            skill_domains: List of skill domains to load (e.g. ['general', 'film_production']).
                           If None, loads all available skills.
            user_id: Current user ID for tools that need API key access.

        Returns:
            A configured Toolkit instance.
        """
        # Cache disabled to ensure each agent gets a unique toolkit instance
        # This is critical because agents may register instance-specific tools (like PlanNotebook)
        # which would conflict if the toolkit was shared.

        logger.info(f"Initializing Toolkit for domains: {skill_domains or 'ALL'}")
        toolkit = Toolkit()

        # 1. Register Core Tools
        cls._register_core_tools(toolkit, user_id)

        # 2. Register Skills
        cls._register_skills(toolkit, skill_domains)

        return toolkit

    @staticmethod
    def list_skills() -> List[str]:
        """
        List all available skills in 'domain/skill_name' format.
        """
        skills = []
        skills_root = Path(__file__).parent / "skills"
        
        if not skills_root.exists():
            return []
            
        # Scan all subdirectories in skills_root
        domain_dirs = [d for d in skills_root.iterdir() if d.is_dir()]
        
        for domain_dir in domain_dirs:
            domain = domain_dir.name
            # Recursive search for SKILL.md files
            for skill_file in domain_dir.rglob("SKILL.md"):
                skill_dir = skill_file.parent
                skill_name = skill_dir.name
                # The controller expects "domain/skill_name"
                skills.append(f"{domain}/{skill_name}")
                
        return sorted(skills)

    @staticmethod
    def _register_core_tools(toolkit: Toolkit, user_id: Optional[str] = None):
        """Register core python function tools."""
        try:
            # Import tools from the tools package
            from src.services.agent_engine.tools.canvas_tools import (
                create_workflow_chain,
                create_node_group,
                update_node_properties,
                connect_nodes,
                delete_nodes,
                batch_generate,
                apply_template,
                get_canvas_state,
                find_nodes_by_type,
                auto_layout_nodes,
                duplicate_workflow,
            )
            from src.services.agent_engine.tools.generation_tools import (
                generate_image,
                generate_video,
            )
            from src.services.agent_engine.tools.project_tools import (
                list_projects,
                get_project,
                create_project,
                create_project_from_novel,
                extract_assets,
                split_text_into_chapters,
            )
            from src.services.agent_engine.tools.file_tools import (
                read_file,
                list_directory,
            )
            from functools import partial

            # List of all tool functions
            all_tools = [
                # Canvas Tools
                create_workflow_chain,
                create_node_group,
                update_node_properties,
                connect_nodes,
                delete_nodes,
                batch_generate,
                apply_template,
                get_canvas_state,
                find_nodes_by_type,
                auto_layout_nodes,
                duplicate_workflow,

                # Project Tools
                list_projects,
                get_project,
                create_project,
                create_project_from_novel,
                extract_assets,
                split_text_into_chapters,

                # File Tools
                read_file,
                list_directory,
            ]

            # Generation tools with user_id binding
            if user_id:
                all_tools.extend([
                    partial(generate_image, user_id=user_id),
                    partial(generate_video, user_id=user_id),
                ])
            else:
                all_tools.extend([
                    generate_image,
                    generate_video,
                ])

            # Add tools to toolkit
            for tool_func in all_tools:
                # Update: Use register_tool_function instead of add (deprecated/removed)
                if hasattr(toolkit, 'register_tool_function'):
                    toolkit.register_tool_function(tool_func)
                else:
                    # Fallback or older version support if needed, but current env requires register_tool_function
                    # Checking if 'add' exists just in case, but logs show it doesn't
                    if hasattr(toolkit, 'add'):
                        toolkit.add(tool_func)
                    else:
                         # Try 'register' as another potential alias in some versions
                        if hasattr(toolkit, 'register'):
                             toolkit.register(tool_func)
                        else:
                             logger.error(f"Toolkit has no method to register tool: {tool_func.__name__}")

            logger.info(f"Registered {len(all_tools)} core tools")

        except ImportError as e:
            logger.error(f"Failed to import core tools: {e}")
            raise

    @staticmethod
    def _register_skills(toolkit: Toolkit, skill_domains: Optional[List[str]] = None):
        """
        Register skills from the skills directory.
        
        Args:
            toolkit: The Toolkit instance to add skills to.
            skill_domains: specific domains to load (e.g. 'general', 'film_production').
        """
        # Base skills directory: current_file_dir/skills
        skills_root = Path(__file__).parent / "skills"
        
        if not skills_root.exists():
            logger.warning(f"Skills directory not found: {skills_root}")
            return

        # Determine which directories to scan
        if skill_domains:
            # Only scan specified domains
            dirs_to_scan = [skills_root / domain for domain in skill_domains]
        else:
            # Scan all subdirectories in skills_root
            dirs_to_scan = [d for d in skills_root.iterdir() if d.is_dir()]

        count = 0
        for domain_dir in dirs_to_scan:
            if not domain_dir.exists():
                logger.warning(f"Skill domain not found: {domain_dir}")
                continue
                
            # Scan for skill sub-folders (e.g. skills/general/canvas_workflow)
            # A valid skill folder must contain a SKILL.md file (AgentScope convention)
            # Or we can just treat any subfolder as a potential skill
            
            # Recursive search for SKILL.md files
            for skill_file in domain_dir.rglob("SKILL.md"):
                skill_dir = skill_file.parent
                skill_name = skill_dir.name
                
                try:
                    # Use AgentScope's register_agent_skill method
                    # This method parses the SKILL.md and adds the skill to the toolkit
                    # It expects the directory path containing SKILL.md
                    if hasattr(toolkit, 'register_agent_skill'):
                        toolkit.register_agent_skill(str(skill_dir))
                        logger.info(f"Registered skill: {skill_name} from {skill_dir}")
                    else:
                        # Fallback if method doesn't exist (e.g. older AgentScope version)
                        # We just log it for now
                        logger.warning(f"Toolkit.register_agent_skill not found. Skill {skill_name} not registered properly.")
                        
                    count += 1
                except Exception as e:
                    logger.error(f"Error loading skill {skill_name}: {e}")

        logger.info(f"Scanned {count} skills in domains: {skill_domains or 'ALL'}")
