"""Rails framework adapters for seamless integration with popular agent frameworks.

This package provides adapters that allow Rails conditional message injection
to work seamlessly with various agent frameworks like LangChain, SmolAgents,
and more. Each adapter maintains the framework-agnostic nature of Rails while
providing framework-specific optimizations.

Usage Examples:

LangChain Integration:
    from rails import Rails
    from rails.adapters import LangChainAdapter
    from langchain_openai import ChatOpenAI
    
    rails = Rails()
    rails.when(lambda s: s.get_counter_sync('turns') >= 3).inject({
        "role": "system",
        "content": "Let's wrap up this conversation."
    })
    
    llm = ChatOpenAI()
    adapter = LangChainAdapter(rails, llm)
    
    result = await adapter.run([
        {"role": "user", "content": "Hello!"}
    ])

SmolAgents Integration:
    from rails import Rails
    from rails.adapters import SmolAgentsAdapter
    from smolagents import CodeAgent
    
    rails = Rails()
    rails.when(lambda s: s.get_counter_sync('tool_calls') >= 2).inject({
        "role": "system",
        "content": "You've used tools. Consider explaining your approach."
    })
    
    agent = CodeAgent(tools=[], model="gpt-4")
    adapter = SmolAgentsAdapter(rails, agent)
    
    result = await adapter.run("Create a data visualization")

Custom Framework Integration:
    from rails.adapters import BaseRailsAdapter
    
    class MyFrameworkAdapter(BaseRailsAdapter):
        async def process_messages(self, messages, **kwargs):
            # Your framework-specific logic here
            return my_framework.process(messages)
    
    adapter = MyFrameworkAdapter(rails)
    result = await adapter.run(messages)
"""

from .base import BaseRailsAdapter, SimpleRailsAdapter, ProcessorAdapter, create_adapter

# Import adapters with graceful degradation for optional dependencies
try:
    from .langchain import LangChainAdapter, create_langchain_adapter
    from .langchain import with_rails as langchain_with_rails
    LANGCHAIN_AVAILABLE = True
except ImportError:
    LANGCHAIN_AVAILABLE = False

try:
    from .smolagents import SmolAgentsAdapter, CodeAgentAdapter, create_smolagents_adapter
    from .smolagents import with_rails as smolagents_with_rails
    SMOLAGENTS_AVAILABLE = True
except ImportError:
    SMOLAGENTS_AVAILABLE = False


__all__ = [
    # Base adapter classes
    "BaseRailsAdapter",
    "SimpleRailsAdapter",
    "ProcessorAdapter", 
    "create_adapter",
]

# Add framework-specific exports if available
if LANGCHAIN_AVAILABLE:
    __all__.extend([
        "LangChainAdapter",
        "create_langchain_adapter",
        "langchain_with_rails",
    ])

if SMOLAGENTS_AVAILABLE:
    __all__.extend([
        "SmolAgentsAdapter",
        "CodeAgentAdapter", 
        "create_smolagents_adapter",
        "smolagents_with_rails",
    ])


def get_available_adapters() -> dict:
    """Get information about available framework adapters.
    
    Returns:
        Dictionary mapping framework names to adapter availability and classes
        
    Example:
        available = get_available_adapters()
        if available['langchain']['available']:
            adapter_class = available['langchain']['adapter']
    """
    adapters = {
        'base': {
            'available': True,
            'adapter': BaseRailsAdapter,
            'description': 'Base adapter pattern for custom frameworks'
        },
        'simple': {
            'available': True,
            'adapter': SimpleRailsAdapter,
            'description': 'Simple adapter for framework-agnostic usage'
        }
    }
    
    if LANGCHAIN_AVAILABLE:
        adapters['langchain'] = {
            'available': True,
            'adapter': LangChainAdapter,
            'description': 'Adapter for LangChain chains, agents, and chat models'
        }
    else:
        adapters['langchain'] = {
            'available': False,
            'adapter': None,
            'description': 'LangChain adapter (requires: pip install langchain-core)',
            'install_hint': 'pip install langchain-core'
        }
    
    if SMOLAGENTS_AVAILABLE:
        adapters['smolagents'] = {
            'available': True,
            'adapter': SmolAgentsAdapter,
            'description': 'Adapter for SmolAgents agents'
        }
    else:
        adapters['smolagents'] = {
            'available': False,
            'adapter': None,
            'description': 'SmolAgents adapter (requires: pip install smolagents)',
            'install_hint': 'pip install smolagents'
        }
    
    return adapters


def print_adapter_status():
    """Print the status of all available adapters."""
    adapters = get_available_adapters()
    
    print("Rails Framework Adapters:")
    print("=" * 50)
    
    for name, info in adapters.items():
        status = "✓ Available" if info['available'] else "✗ Not Available"
        print(f"{name:12} {status:15} - {info['description']}")
        
        if not info['available'] and 'install_hint' in info:
            print(f"{'':12} {'':15}   Install: {info['install_hint']}")
    
    print()


# Convenience function for quick adapter creation
def auto_adapter(framework_object, rails=None):
    """Automatically create the appropriate adapter for a framework object.
    
    This function inspects the provided framework object and returns the
    appropriate Rails adapter.
    
    Args:
        framework_object: Framework-specific object (chain, agent, etc.)
        rails: Optional Rails instance
        
    Returns:
        Appropriate Rails adapter
        
    Example:
        from langchain_openai import ChatOpenAI
        from rails import Rails
        from rails.adapters import auto_adapter
        
        rails = Rails()
        llm = ChatOpenAI()
        
        # Automatically creates LangChainAdapter
        adapter = auto_adapter(llm, rails)
    """
    obj_type = str(type(framework_object))
    
    # LangChain detection
    if LANGCHAIN_AVAILABLE and 'langchain' in obj_type.lower():
        return LangChainAdapter(rails, framework_object)
    
    # SmolAgents detection
    if SMOLAGENTS_AVAILABLE and ('smolagents' in obj_type.lower() or 'agent' in obj_type.lower()):
        return create_smolagents_adapter(framework_object, rails)
    
    # Default to simple adapter
    return SimpleRailsAdapter(rails)