# Copyright (c) 2025 Patrick Motsch
# All rights reserved.
# methodDiscovery.py
# Method discovery and management for workflow execution

import logging
import importlib
import pkgutil
import inspect
from typing import Any, Dict, List
from modules.workflows.methods.methodBase import MethodBase

# Set up logger
logger = logging.getLogger(__name__)

# Global methods catalog - moved from serviceCenter
methods = {}

def discoverMethods(serviceCenter):
    """Dynamically discover all method classes and their actions in modules methods package.
    
    Always creates fresh method instances bound to the given serviceCenter,
    preventing stale or cross-workflow service references.
    """
    global methods
    try:
        methodsPackage = importlib.import_module('modules.workflows.methods')
        
        # Clear and rebuild to prevent cross-workflow state contamination
        methods.clear()
        uniqueCount = 0
        
        for _, name, isPkg in pkgutil.iter_modules(methodsPackage.__path__):
            if name.startswith('method'):
                try:
                    module = importlib.import_module(f'modules.workflows.methods.{name}')
                    
                    for itemName, item in inspect.getmembers(module):
                        if (inspect.isclass(item) and 
                            issubclass(item, MethodBase) and 
                            item != MethodBase):
                            
                            shortName = itemName.replace('Method', '').lower()
                            
                            # Skip if already processed (via another module path)
                            if itemName in methods:
                                continue
                            
                            methodInstance = item(serviceCenter)
                            actions = methodInstance.actions
                            
                            methodInfo = {
                                'instance': methodInstance,
                                'actions': actions,
                                'description': item.__doc__ or f"Method {itemName}"
                            }
                            
                            methods[itemName] = methodInfo
                            methods[shortName] = methodInfo
                            uniqueCount += 1
                            
                            logger.info(f"Discovered method {itemName} (short: {shortName}) with {len(actions)} actions")
                            
                except Exception as e:
                    logger.error(f"Error discovering method {name}: {str(e)}")
                    continue
                    
        logger.info(f"Discovered {uniqueCount} unique methods ({len(methods)} entries with aliases)")
        
    except Exception as e:
        logger.error(f"Error discovering methods: {str(e)}")

def getActionParameterList(methodName: str, actionName: str, methods: Dict[str, Any]) -> str:
    """Get action parameter list from WorkflowActionParameter structure for AI parameter generation (list only)."""
    try:
        if not methods or methodName not in methods:
            return ""
        
        methodInstance = methods[methodName]['instance']
        if actionName not in methodInstance.actions:
            return ""
        
        action_info = methodInstance.actions[actionName]
        # Use structured WorkflowActionParameter objects from new system
        parameters = action_info.get('parameters', {})
        
        param_list = []
        for paramName, paramInfo in parameters.items():
            paramType = paramInfo.get('type', 'Any')
            paramDesc = paramInfo.get('description', '')
            paramRequired = paramInfo.get('required', False)
            
            # Format: paramName (type, required/optional): description
            reqText = "required" if paramRequired else "optional"
            if paramDesc:
                param_list.append(f"- {paramName} ({paramType}, {reqText}): {paramDesc}")
            else:
                param_list.append(f"- {paramName} ({paramType}, {reqText})")
        
        # Return list only, without leading headings or trailing text
        return "\n".join(param_list)
    except Exception as e:
        logger.error(f"Error getting action parameter signature for {methodName}.{actionName}: {str(e)}")
        return ""

