"""
Praison AI Agents - A package for hierarchical AI agent task execution

This module uses lazy loading to minimize import time and memory usage.
Heavy dependencies like litellm are only loaded when actually needed.
"""

# Apply warning patch BEFORE any imports to intercept warnings at the source
from . import _warning_patch  # noqa: F401

# Import centralized logging configuration FIRST
from . import _logging

# Configure root logger after logging is initialized
_logging.configure_root_logger()

# Import configuration (lightweight, no heavy deps)
from . import _config

# Lightweight imports that don't trigger heavy dependency chains
from .tools.tools import Tools
from .tools.base import BaseTool, ToolResult, ToolValidationError, validate_tool
from .tools.decorator import tool, FunctionTool
from .tools.registry import get_registry, register_tool, get_tool, ToolRegistry
from .db import db
from .obs import obs

# Workflows - lightweight module
from .workflows import (
    Workflow, WorkflowStep, WorkflowContext, StepResult,
    Route, Parallel, Loop, Repeat,
    route, parallel, loop, repeat,
    Pipeline  # Alias for Workflow
)
from .guardrails import GuardrailResult, LLMGuardrail

# Handoff - lightweight
from .agent.handoff import Handoff, handoff, handoff_filters, RECOMMENDED_PROMPT_PREFIX, prompt_with_handoff_instructions

# Flow display (optional)
try:
    from .flow_display import FlowDisplay, track_workflow
except ImportError:
    FlowDisplay = None
    track_workflow = None

# Main display utilities - these are used frequently so import directly
# but they don't pull in litellm
from .main import (
    TaskOutput,
    ReflectionOutput,
    display_interaction,
    display_self_reflection,
    display_instruction,
    display_tool_call,
    display_error,
    display_generating,
    clean_triple_backticks,
    error_logs,
    register_display_callback,
    sync_display_callbacks,
    async_display_callbacks,
)

# Module-level caches for lazy-loaded classes
_lazy_cache = {}

# Flags for optional modules
_mcp_available = None
_planning_available = None
_telemetry_available = None
_agui_available = None
_a2a_available = None


def __getattr__(name):
    """
    Lazy load heavy modules to avoid impacting package load time.
    
    This function is called when an attribute is not found in the module.
    It enables deferred loading of heavy dependencies like litellm.
    """
    global _mcp_available, _planning_available, _telemetry_available
    global _agui_available, _a2a_available
    
    # Return cached values if available
    if name in _lazy_cache:
        return _lazy_cache[name]
    
    # Agent and related classes (triggers litellm import chain)
    if name == "Agent":
        from .agent.agent import Agent
        _lazy_cache[name] = Agent
        return Agent
    elif name == "ImageAgent":
        from .agent.image_agent import ImageAgent
        _lazy_cache[name] = ImageAgent
        return ImageAgent
    elif name == "ContextAgent":
        from .agent.context_agent import ContextAgent
        _lazy_cache[name] = ContextAgent
        return ContextAgent
    elif name == "create_context_agent":
        from .agent.context_agent import create_context_agent
        _lazy_cache[name] = create_context_agent
        return create_context_agent
    elif name == "DeepResearchAgent":
        from .agent.deep_research_agent import DeepResearchAgent
        _lazy_cache[name] = DeepResearchAgent
        return DeepResearchAgent
    elif name == "DeepResearchResponse":
        from .agent.deep_research_agent import DeepResearchResponse
        _lazy_cache[name] = DeepResearchResponse
        return DeepResearchResponse
    elif name == "Citation":
        from .agent.deep_research_agent import Citation
        _lazy_cache[name] = Citation
        return Citation
    elif name == "ReasoningStep":
        from .agent.deep_research_agent import ReasoningStep
        _lazy_cache[name] = ReasoningStep
        return ReasoningStep
    elif name == "WebSearchCall":
        from .agent.deep_research_agent import WebSearchCall
        _lazy_cache[name] = WebSearchCall
        return WebSearchCall
    elif name == "CodeExecutionStep":
        from .agent.deep_research_agent import CodeExecutionStep
        _lazy_cache[name] = CodeExecutionStep
        return CodeExecutionStep
    elif name == "MCPCall":
        from .agent.deep_research_agent import MCPCall
        _lazy_cache[name] = MCPCall
        return MCPCall
    elif name == "FileSearchCall":
        from .agent.deep_research_agent import FileSearchCall
        _lazy_cache[name] = FileSearchCall
        return FileSearchCall
    elif name == "Provider":
        from .agent.deep_research_agent import Provider
        _lazy_cache[name] = Provider
        return Provider
    elif name == "QueryRewriterAgent":
        from .agent.query_rewriter_agent import QueryRewriterAgent
        _lazy_cache[name] = QueryRewriterAgent
        return QueryRewriterAgent
    elif name == "RewriteStrategy":
        from .agent.query_rewriter_agent import RewriteStrategy
        _lazy_cache[name] = RewriteStrategy
        return RewriteStrategy
    elif name == "RewriteResult":
        from .agent.query_rewriter_agent import RewriteResult
        _lazy_cache[name] = RewriteResult
        return RewriteResult
    elif name == "PromptExpanderAgent":
        from .agent.prompt_expander_agent import PromptExpanderAgent
        _lazy_cache[name] = PromptExpanderAgent
        return PromptExpanderAgent
    elif name == "ExpandStrategy":
        from .agent.prompt_expander_agent import ExpandStrategy
        _lazy_cache[name] = ExpandStrategy
        return ExpandStrategy
    elif name == "ExpandResult":
        from .agent.prompt_expander_agent import ExpandResult
        _lazy_cache[name] = ExpandResult
        return ExpandResult
    
    # PraisonAIAgents and Agents alias
    elif name == "PraisonAIAgents":
        from .agents.agents import PraisonAIAgents
        _lazy_cache[name] = PraisonAIAgents
        _lazy_cache["Agents"] = PraisonAIAgents  # Also cache alias
        return PraisonAIAgents
    elif name == "Agents":
        from .agents.agents import PraisonAIAgents
        _lazy_cache["PraisonAIAgents"] = PraisonAIAgents
        _lazy_cache[name] = PraisonAIAgents
        return PraisonAIAgents
    
    # Task
    elif name == "Task":
        from .task.task import Task
        _lazy_cache[name] = Task
        return Task
    
    # AutoAgents
    elif name == "AutoAgents":
        from .agents.autoagents import AutoAgents
        _lazy_cache[name] = AutoAgents
        return AutoAgents
    
    # Session (imports requests)
    elif name == "Session":
        from .session import Session
        _lazy_cache[name] = Session
        return Session
    
    # MCP support (optional)
    elif name == "MCP":
        if _mcp_available is None:
            try:
                from .mcp.mcp import MCP as _MCP
                _lazy_cache[name] = _MCP
                return _MCP
            except ImportError:
                return None
        return _lazy_cache.get(name)
    
    # Knowledge module (imports chromadb, mem0)
    elif name == "Knowledge":
        from overai.knowledge.knowledge import Knowledge
        _lazy_cache[name] = Knowledge
        return Knowledge
    elif name == "Chunking":
        from overai.knowledge.chunking import Chunking
        _lazy_cache[name] = Chunking
        return Chunking
    
    # FastContext support
    elif name == "FastContext":
        from overai.context.fast import FastContext
        _lazy_cache[name] = FastContext
        return FastContext
    elif name == "FastContextResult":
        from overai.context.fast import FastContextResult
        _lazy_cache[name] = FastContextResult
        return FastContextResult
    elif name == "FileMatch":
        from overai.context.fast import FileMatch
        _lazy_cache[name] = FileMatch
        return FileMatch
    elif name == "LineRange":
        from overai.context.fast import LineRange
        _lazy_cache[name] = LineRange
        return LineRange
    
    # Agent Skills support (lazy loaded for zero performance impact)
    elif name == "SkillManager":
        from overai.skills import SkillManager
        _lazy_cache[name] = SkillManager
        return SkillManager
    elif name == "SkillProperties":
        from overai.skills import SkillProperties
        _lazy_cache[name] = SkillProperties
        return SkillProperties
    elif name == "SkillMetadata":
        from overai.skills import SkillMetadata
        _lazy_cache[name] = SkillMetadata
        return SkillMetadata
    elif name == "SkillLoader":
        from overai.skills import SkillLoader
        _lazy_cache[name] = SkillLoader
        return SkillLoader
    
    # Memory module (imports chromadb)
    elif name == "Memory":
        from overai.memory.memory import Memory
        _lazy_cache[name] = Memory
        return Memory
    
    # Planning mode support (lazy)
    elif name in ("Plan", "PlanStep", "TodoList", "TodoItem", "PlanStorage", 
                  "PlanningAgent", "ApprovalCallback", "READ_ONLY_TOOLS", 
                  "RESTRICTED_TOOLS"):
        try:
            from . import planning as _planning
            result = getattr(_planning, name)
            _lazy_cache[name] = result
            return result
        except ImportError:
            if name in ("READ_ONLY_TOOLS", "RESTRICTED_TOOLS"):
                return []
            return None
    
    # Telemetry support (lazy loaded)
    elif name in ("get_telemetry", "enable_telemetry", "disable_telemetry",
                  "enable_performance_mode", "disable_performance_mode",
                  "cleanup_telemetry_resources", "MinimalTelemetry", "TelemetryCollector"):
        try:
            from . import telemetry as _telemetry
            result = getattr(_telemetry, name)
            _lazy_cache[name] = result
            return result
        except ImportError:
            # Provide stub functions
            if name == "get_telemetry":
                return lambda: None
            elif name == "enable_telemetry":
                import logging
                def _stub(*args, **kwargs):
                    logging.warning(
                        "Telemetry not available. Install with: pip install overai[telemetry]"
                    )
                    return None
                return _stub
            elif name in ("disable_telemetry", "enable_performance_mode", 
                         "disable_performance_mode", "cleanup_telemetry_resources"):
                return lambda: None
            return None
    
    # AG-UI support (optional, lazy loaded)
    elif name == "AGUI":
        try:
            from overai.ui.agui import AGUI
            _lazy_cache[name] = AGUI
            return AGUI
        except ImportError:
            return None
    
    # A2A support (optional, lazy loaded)
    elif name == "A2A":
        try:
            from overai.ui.a2a import A2A
            _lazy_cache[name] = A2A
            return A2A
        except ImportError:
            return None
    
    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


# Initialize telemetry only if explicitly enabled via config
def _init_telemetry():
    """Initialize telemetry if enabled via environment variable."""
    if not _config.TELEMETRY_ENABLED:
        return
    
    try:
        from .telemetry import get_telemetry
        from .telemetry.integration import auto_instrument_all
        
        _telemetry = get_telemetry()
        if _telemetry and _telemetry.enabled:
            use_performance_mode = _config.PERFORMANCE_MODE and not (
                _config.FULL_TELEMETRY or _config.AUTO_INSTRUMENT
            )
            auto_instrument_all(_telemetry, performance_mode=use_performance_mode)
            
            # Track package import for basic usage analytics
            try:
                _telemetry.track_feature_usage("package_import")
            except Exception:
                pass
    except Exception:
        # Silently fail if there are any issues - never break user applications
        pass


# Only initialize telemetry if explicitly enabled
_init_telemetry()


__all__ = [
    # Core classes (lazy loaded)
    'Agent',
    'ImageAgent',
    'ContextAgent',
    'create_context_agent',
    'PraisonAIAgents',
    'Agents',
    'Tools',
    'Task',
    # Plugin system
    'BaseTool',
    'ToolResult',
    'ToolValidationError',
    'validate_tool',
    'tool',
    'FunctionTool',
    'ToolRegistry',
    'get_registry',
    'register_tool',
    'get_tool',
    'TaskOutput',
    'ReflectionOutput',
    'AutoAgents',
    'Session',
    'Memory',
    'db',
    'obs',
    'display_interaction',
    'display_self_reflection',
    'display_instruction',
    'display_tool_call',
    'display_error',
    'display_generating',
    'clean_triple_backticks',
    'error_logs',
    'register_display_callback',
    'sync_display_callbacks',
    'async_display_callbacks',
    'Knowledge',
    'Chunking',
    'GuardrailResult',
    'LLMGuardrail',
    'Handoff',
    'handoff',
    'handoff_filters',
    'RECOMMENDED_PROMPT_PREFIX',
    'prompt_with_handoff_instructions',
    'get_telemetry',
    'enable_telemetry',
    'disable_telemetry',
    'enable_performance_mode',
    'disable_performance_mode',
    'cleanup_telemetry_resources',
    'MinimalTelemetry',
    'TelemetryCollector',
    'DeepResearchAgent',
    'DeepResearchResponse',
    'Citation',
    'ReasoningStep',
    'WebSearchCall',
    'CodeExecutionStep',
    'MCPCall',
    'FileSearchCall',
    'Provider',
    'QueryRewriterAgent',
    'RewriteStrategy',
    'RewriteResult',
    'PromptExpanderAgent',
    'ExpandStrategy',
    'ExpandResult',
    # Workflows
    'Workflow',
    'WorkflowStep', 
    'WorkflowContext',
    'StepResult',
    'Route',
    'Parallel',
    'Loop',
    'Repeat',
    'route',
    'parallel',
    'loop',
    'repeat',
    'Pipeline',
    # MCP
    'MCP',
    # Flow display
    'FlowDisplay',
    'track_workflow',
    # FastContext
    'FastContext',
    'FastContextResult',
    'FileMatch',
    'LineRange',
    # Agent Skills
    'SkillManager',
    'SkillProperties',
    'SkillMetadata',
    'SkillLoader',
    # Planning
    'Plan',
    'PlanStep',
    'TodoList',
    'TodoItem',
    'PlanStorage',
    'PlanningAgent',
    'ApprovalCallback',
    'READ_ONLY_TOOLS',
    'RESTRICTED_TOOLS',
    # UI
    'AGUI',
    'A2A',
]
