# Copyright 2025 Vijaykumar Singh <singhvjd@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Service provider for orchestrator dependencies.

Registers all services required by AgentOrchestrator with the DI container.
This enables:
- Centralized service configuration
- Consistent lifecycle management
- Easy testing via override_services
- Type-safe service resolution

Design Pattern: Service Provider
- Groups related service registrations
- Separates singleton vs scoped lifetimes
- Provides factory functions for complex service creation

Usage:
    from victor.core.container import ServiceContainer
    from victor.agent.service_provider import (
        OrchestratorServiceProvider,
        configure_orchestrator_services,
    )

    # Option 1: Full registration
    container = ServiceContainer()
    configure_orchestrator_services(container, settings)

    # Option 2: Selective registration
    provider = OrchestratorServiceProvider(settings)
    provider.register_singleton_services(container)  # Only singletons
"""

from __future__ import annotations

import logging
from typing import TYPE_CHECKING, Any, Optional

from victor.core.container import ServiceContainer, ServiceLifetime

if TYPE_CHECKING:
    from victor.config.settings import Settings

logger = logging.getLogger(__name__)


class OrchestratorServiceProvider:
    """Service provider for orchestrator dependencies.

    Manages registration of all services required by AgentOrchestrator.
    Services are categorized by lifetime:

    Singleton Services (application lifetime):
        - ToolRegistry: Shared tool definitions
        - ObservabilityIntegration: Event bus
        - TaskAnalyzer: Shared analysis
        - IntentClassifier: Semantic classification
        - ComplexityClassifier: Task complexity
        - ActionAuthorizer: Action authorization
        - SearchRouter: Search routing
        - ResponseSanitizer: Response cleanup
        - ArgumentNormalizer: Argument normalization
        - ProjectContext: Project-specific instructions

    Scoped Services (per-session):
        - ConversationStateMachine: Per-session state
        - UnifiedTaskTracker: Per-session tracking
        - MessageHistory: Per-session messages

    Attributes:
        _settings: Application settings for service configuration

    Example:
        container = ServiceContainer()
        provider = OrchestratorServiceProvider(settings)
        provider.register_services(container)

        # Resolve singletons directly
        sanitizer = container.get(ResponseSanitizerProtocol)

        # Resolve scoped services within a scope
        with container.create_scope() as scope:
            state_machine = scope.get(ConversationStateMachineProtocol)
    """

    def __init__(self, settings: "Settings"):
        """Initialize the service provider.

        Args:
            settings: Application settings for service configuration
        """
        self._settings = settings

    def register_services(self, container: ServiceContainer) -> None:
        """Register all orchestrator services.

        Registers both singleton and scoped services. Call this method
        during application bootstrap to set up all orchestrator dependencies.

        Args:
            container: DI container to register services in
        """
        # Store container reference for factory methods
        self.container = container
        self.register_singleton_services(container)
        self.register_scoped_services(container)
        logger.info("Registered all orchestrator services")

    def register_singleton_services(self, container: ServiceContainer) -> None:
        """Register singleton (application-lifetime) services.

        These services are created once and shared across all sessions.
        Use for stateless services or those with expensive initialization.

        Args:
            container: DI container to register services in
        """
        from victor.agent.protocols import (
            ComplexityClassifierProtocol,
            ActionAuthorizerProtocol,
            SearchRouterProtocol,
            ResponseSanitizerProtocol,
            ArgumentNormalizerProtocol,
            TaskAnalyzerProtocol,
            ObservabilityProtocol,
            ToolRegistryProtocol,
            ToolRegistrarProtocol,
            ProjectContextProtocol,
            RecoveryHandlerProtocol,
            CodeExecutionManagerProtocol,
            WorkflowRegistryProtocol,
            UsageAnalyticsProtocol,
            ToolSequenceTrackerProtocol,
            ContextCompactorProtocol,
            ModeControllerProtocol,
            ToolDeduplicationTrackerProtocol,
            # Utility service protocols
            DebugLoggerProtocol,
            TaskTypeHinterProtocol,
            ReminderManagerProtocol,
            RLCoordinatorProtocol,
            SafetyCheckerProtocol,
            AutoCommitterProtocol,
            MCPBridgeProtocol,
            # Infrastructure service protocols
            ToolDependencyGraphProtocol,
            ToolPluginRegistryProtocol,
            SemanticToolSelectorProtocol,
            ProviderRegistryProtocol,
            # Analytics & observability protocols
            ConversationEmbeddingStoreProtocol,
            MetricsCollectorProtocol,
            ToolCacheProtocol,
            UsageLoggerProtocol,
            StreamingMetricsCollectorProtocol,
            IntentClassifierProtocol,
            # Helper/adapter service protocols
            SystemPromptBuilderProtocol,
            ToolSelectorProtocol,
            ToolExecutorProtocol,
            ToolOutputFormatterProtocol,
            ParallelExecutorProtocol,
            ResponseCompleterProtocol,
            StreamingHandlerProtocol,
            RecoveryCoordinatorProtocol,
            ChunkGeneratorProtocol,
            ToolPlannerProtocol,
            TaskCoordinatorProtocol,
        )

        # ToolRegistry - shared tool definitions
        self._register_tool_registry(container)

        # ObservabilityIntegration - event bus
        self._register_observability(container)

        # TaskAnalyzer - shared analysis facade
        self._register_task_analyzer(container)

        # IntentClassifier - singleton by design (ML model)
        self._register_intent_classifier(container)

        # ComplexityClassifier - stateless
        container.register(
            ComplexityClassifierProtocol,
            lambda c: self._create_complexity_classifier(),
            ServiceLifetime.SINGLETON,
        )

        # ActionAuthorizer - stateless
        container.register(
            ActionAuthorizerProtocol,
            lambda c: self._create_action_authorizer(),
            ServiceLifetime.SINGLETON,
        )

        # SearchRouter - stateless
        container.register(
            SearchRouterProtocol,
            lambda c: self._create_search_router(),
            ServiceLifetime.SINGLETON,
        )

        # ResponseSanitizer - stateless
        container.register(
            ResponseSanitizerProtocol,
            lambda c: self._create_response_sanitizer(),
            ServiceLifetime.SINGLETON,
        )

        # ArgumentNormalizer - stateless
        container.register(
            ArgumentNormalizerProtocol,
            lambda c: self._create_argument_normalizer(),
            ServiceLifetime.SINGLETON,
        )

        # ProjectContext - shared project instructions
        container.register(
            ProjectContextProtocol,
            lambda c: self._create_project_context(),
            ServiceLifetime.SINGLETON,
        )

        # RecoveryHandler - model failure recovery with Q-learning
        self._register_recovery_handler(container)

        # CodeExecutionManager - manages code execution sandboxes
        container.register(
            CodeExecutionManagerProtocol,
            lambda c: self._create_code_execution_manager(),
            ServiceLifetime.SINGLETON,
        )

        # WorkflowRegistry - shared workflow definitions
        container.register(
            WorkflowRegistryProtocol,
            lambda c: self._create_workflow_registry(),
            ServiceLifetime.SINGLETON,
        )

        # UsageAnalytics - singleton for data-driven optimization
        container.register(
            UsageAnalyticsProtocol,
            lambda c: self._create_usage_analytics(),
            ServiceLifetime.SINGLETON,
        )

        # ToolSequenceTracker - singleton for pattern learning
        container.register(
            ToolSequenceTrackerProtocol,
            lambda c: self._create_tool_sequence_tracker(),
            ServiceLifetime.SINGLETON,
        )

        # ContextCompactor - singleton for context window management
        container.register(
            ContextCompactorProtocol,
            lambda c: self._create_context_compactor(),
            ServiceLifetime.SINGLETON,
        )

        # ModeController - singleton for agent mode management
        container.register(
            ModeControllerProtocol,
            lambda c: self._create_mode_controller(),
            ServiceLifetime.SINGLETON,
        )

        # ToolDeduplicationTracker - singleton for call deduplication
        container.register(
            ToolDeduplicationTrackerProtocol,
            lambda c: self._create_tool_deduplication_tracker(),
            ServiceLifetime.SINGLETON,
        )

        # =========================================================================
        # Utility Services
        # =========================================================================

        # DebugLogger - singleton for clean debug output
        container.register(
            DebugLoggerProtocol,
            lambda c: self._create_debug_logger(),
            ServiceLifetime.SINGLETON,
        )

        # TaskTypeHinter - singleton for task-specific hints
        container.register(
            TaskTypeHinterProtocol,
            lambda c: self._create_task_type_hinter(),
            ServiceLifetime.SINGLETON,
        )

        # ReminderManager - scoped per session, but registered as factory
        container.register(
            ReminderManagerProtocol,
            lambda c: self._create_reminder_manager(),
            ServiceLifetime.SCOPED,
        )

        # RLCoordinator - singleton for RL data management
        container.register(
            RLCoordinatorProtocol,
            lambda c: self._create_rl_coordinator(),
            ServiceLifetime.SINGLETON,
        )

        # SafetyChecker - singleton for operation safety
        container.register(
            SafetyCheckerProtocol,
            lambda c: self._create_safety_checker(),
            ServiceLifetime.SINGLETON,
        )

        # AutoCommitter - singleton for git commits
        container.register(
            AutoCommitterProtocol,
            lambda c: self._create_auto_committer(),
            ServiceLifetime.SINGLETON,
        )

        # MCPBridge - singleton for MCP tool integration
        container.register(
            MCPBridgeProtocol,
            lambda c: self._create_mcp_bridge(),
            ServiceLifetime.SINGLETON,
        )

        # =========================================================================
        # Infrastructure Services
        # =========================================================================

        # ToolDependencyGraph - singleton for tool dependency management
        container.register(
            ToolDependencyGraphProtocol,
            lambda c: self._create_tool_dependency_graph(),
            ServiceLifetime.SINGLETON,
        )

        # ToolPluginRegistry - singleton for plugin management
        container.register(
            ToolPluginRegistryProtocol,
            lambda c: self._create_tool_plugin_registry(),
            ServiceLifetime.SINGLETON,
        )

        # SemanticToolSelector - singleton for semantic tool selection
        container.register(
            SemanticToolSelectorProtocol,
            lambda c: self._create_semantic_tool_selector(),
            ServiceLifetime.SINGLETON,
        )

        # ProviderRegistry - singleton for provider management
        container.register(
            ProviderRegistryProtocol,
            lambda c: self._create_provider_registry(),
            ServiceLifetime.SINGLETON,
        )

        # =========================================================================
        # Analytics & Observability Services
        # =========================================================================

        # ConversationEmbeddingStore - singleton for semantic search over history
        container.register(
            ConversationEmbeddingStoreProtocol,
            lambda c: self._create_conversation_embedding_store(),
            ServiceLifetime.SINGLETON,
        )

        # MetricsCollector - singleton for metrics aggregation
        container.register(
            MetricsCollectorProtocol,
            lambda c: self._create_metrics_collector(),
            ServiceLifetime.SINGLETON,
        )

        # ToolCache - singleton for tool result caching
        container.register(
            ToolCacheProtocol,
            lambda c: self._create_tool_cache(),
            ServiceLifetime.SINGLETON,
        )

        # UsageLogger - singleton for usage logging
        container.register(
            UsageLoggerProtocol,
            lambda c: self._create_usage_logger(),
            ServiceLifetime.SINGLETON,
        )

        # StreamingMetricsCollector - scoped per session
        container.register(
            StreamingMetricsCollectorProtocol,
            lambda c: self._create_streaming_metrics_collector(),
            ServiceLifetime.SCOPED,
        )

        # IntentClassifier - singleton for ML-based intent classification
        container.register(
            IntentClassifierProtocol,
            lambda c: self._create_intent_classifier(),
            ServiceLifetime.SINGLETON,
        )

        # =========================================================================
        # Helper/Adapter Services
        # =========================================================================

        # SystemPromptBuilder - factory for prompt construction
        container.register(
            SystemPromptBuilderProtocol,
            lambda c: self._create_system_prompt_builder(),
            ServiceLifetime.SINGLETON,
        )

        # ToolSelector - singleton for tool selection logic
        container.register(
            ToolSelectorProtocol,
            lambda c: self._create_tool_selector(),
            ServiceLifetime.SINGLETON,
        )

        # ToolExecutor - singleton for tool execution
        container.register(
            ToolExecutorProtocol,
            lambda c: self._create_tool_executor(),
            ServiceLifetime.SINGLETON,
        )

        # ToolOutputFormatter - singleton for formatting tool outputs
        container.register(
            ToolOutputFormatterProtocol,
            lambda c: self._create_tool_output_formatter(),
            ServiceLifetime.SINGLETON,
        )

        # ParallelExecutor - factory for parallel execution
        container.register(
            ParallelExecutorProtocol,
            lambda c: self._create_parallel_executor(),
            ServiceLifetime.SINGLETON,
        )

        # ResponseCompleter - factory for response completion
        container.register(
            ResponseCompleterProtocol,
            lambda c: self._create_response_completer(),
            ServiceLifetime.SINGLETON,
        )

        # StreamingHandler - scoped per session
        container.register(
            StreamingHandlerProtocol,
            lambda c: self._create_streaming_handler(),
            ServiceLifetime.SCOPED,
        )

        # RecoveryCoordinator - singleton for recovery coordination
        container.register(
            RecoveryCoordinatorProtocol,
            lambda c: self._create_recovery_coordinator(),
            ServiceLifetime.SINGLETON,
        )

        # ChunkGenerator - singleton for chunk generation
        container.register(
            ChunkGeneratorProtocol,
            lambda c: self._create_chunk_generator(),
            ServiceLifetime.SINGLETON,
        )

        # ToolPlanner - singleton for tool planning
        container.register(
            ToolPlannerProtocol,
            lambda c: self._create_tool_planner(),
            ServiceLifetime.SINGLETON,
        )

        # TaskCoordinator - singleton for task coordination
        container.register(
            TaskCoordinatorProtocol,
            lambda c: self._create_task_coordinator(),
            ServiceLifetime.SINGLETON,
        )

        # PathResolver - singleton for centralized path resolution
        self._register_path_resolver(container)

        logger.debug("Registered singleton orchestrator services")

    def register_scoped_services(self, container: ServiceContainer) -> None:
        """Register scoped (per-session) services.

        These services are created fresh for each orchestrator session.
        Use for stateful services that need isolation between sessions.

        Args:
            container: DI container to register services in
        """
        from victor.agent.protocols import (
            ConversationStateMachineProtocol,
            TaskTrackerProtocol,
            MessageHistoryProtocol,
        )

        # ConversationStateMachine - per-session state
        container.register(
            ConversationStateMachineProtocol,
            lambda c: self._create_conversation_state_machine(),
            ServiceLifetime.SCOPED,
        )

        # UnifiedTaskTracker - per-session tracking
        container.register(
            TaskTrackerProtocol,
            lambda c: self._create_unified_task_tracker(),
            ServiceLifetime.SCOPED,
        )

        # MessageHistory - per-session messages
        container.register(
            MessageHistoryProtocol,
            lambda c: self._create_message_history(),
            ServiceLifetime.SCOPED,
        )

        # ToolAccessController - per-session tool access control
        self._register_tool_access_controller(container)

        # BudgetManager - per-session budget management
        self._register_budget_manager(container)

        logger.debug("Registered scoped orchestrator services")

    # =========================================================================
    # Factory methods for singleton services
    # =========================================================================

    def _register_tool_registry(self, container: ServiceContainer) -> None:
        """Register ToolRegistry as singleton."""
        from victor.agent.protocols import ToolRegistryProtocol, ToolRegistrarProtocol
        from victor.tools.base import ToolRegistry

        container.register(
            ToolRegistryProtocol,
            lambda c: ToolRegistry(),
            ServiceLifetime.SINGLETON,
        )

        # ToolRegistrar - manages tool registration, plugins, and MCP integration
        container.register(
            ToolRegistrarProtocol,
            lambda c: self._create_tool_registrar(c),
            ServiceLifetime.SINGLETON,
        )

    def _create_tool_registrar(self, container: ServiceContainer) -> Any:
        """Create ToolRegistrar instance.

        ToolRegistrar manages:
        - Dynamic tool discovery from victor/tools directory
        - Plugin system management
        - MCP (Model Context Protocol) integration
        - Tool dependency graph setup

        Args:
            container: DI container for resolving dependencies

        Returns:
            ToolRegistrar instance
        """
        from victor.agent.tool_registrar import ToolRegistrar, ToolRegistrarConfig
        from victor.agent.protocols import ToolRegistryProtocol

        # Get ToolRegistry from container
        tool_registry = container.get(ToolRegistryProtocol)

        # Build config from settings
        config = ToolRegistrarConfig(
            enable_plugins=getattr(self._settings, "enable_plugins", True),
            enable_mcp=getattr(self._settings, "use_mcp_tools", False),
            enable_tool_graph=getattr(self._settings, "enable_tool_graph", True),
            airgapped_mode=getattr(self._settings, "airgapped_mode", False),
        )

        return ToolRegistrar(
            tools=tool_registry,
            settings=self._settings,
            provider=None,  # Will be set later by orchestrator
            model=getattr(self._settings, "model", None),
            config=config,
        )

    def _register_observability(self, container: ServiceContainer) -> None:
        """Register ObservabilityIntegration as singleton."""
        from victor.agent.protocols import ObservabilityProtocol

        def create_observability(_: ServiceContainer) -> Any:
            enable = getattr(self._settings, "enable_observability", True)
            if not enable:
                return _NullObservability()

            try:
                from victor.observability.integration import ObservabilityIntegration

                return ObservabilityIntegration()
            except ImportError:
                logger.warning("ObservabilityIntegration not available")
                return _NullObservability()

        container.register(
            ObservabilityProtocol,
            create_observability,
            ServiceLifetime.SINGLETON,
        )

    def _register_task_analyzer(self, container: ServiceContainer) -> None:
        """Register TaskAnalyzer as singleton."""
        from victor.agent.protocols import TaskAnalyzerProtocol

        def create_task_analyzer(_: ServiceContainer) -> Any:
            try:
                from victor.agent.task_analyzer import get_task_analyzer

                return get_task_analyzer()
            except ImportError:
                logger.warning("TaskAnalyzer not available")
                return _NullTaskAnalyzer()

        container.register(
            TaskAnalyzerProtocol,
            create_task_analyzer,
            ServiceLifetime.SINGLETON,
        )

    def _register_intent_classifier(self, container: ServiceContainer) -> None:
        """Register IntentClassifier as singleton."""
        from victor.embeddings.intent_classifier import IntentClassifier

        container.register(
            IntentClassifier,
            lambda c: IntentClassifier.get_instance(),
            ServiceLifetime.SINGLETON,
        )

    def _create_complexity_classifier(self) -> Any:
        """Create ComplexityClassifier instance."""
        from victor.agent.complexity_classifier import ComplexityClassifier

        return ComplexityClassifier()

    def _create_action_authorizer(self) -> Any:
        """Create ActionAuthorizer instance."""
        from victor.agent.action_authorizer import ActionAuthorizer

        return ActionAuthorizer()

    def _create_search_router(self) -> Any:
        """Create SearchRouter instance."""
        from victor.agent.search_router import SearchRouter

        return SearchRouter()

    def _create_response_sanitizer(self) -> Any:
        """Create ResponseSanitizer instance."""
        from victor.agent.response_sanitizer import ResponseSanitizer

        return ResponseSanitizer()

    def _create_argument_normalizer(self) -> Any:
        """Create ArgumentNormalizer instance."""
        from victor.agent.argument_normalizer import ArgumentNormalizer

        # Provider name will be updated when orchestrator is created
        return ArgumentNormalizer(provider_name="unknown")

    def _create_project_context(self) -> Any:
        """Create ProjectContext instance."""
        from victor.context.project_context import ProjectContext

        context = ProjectContext()
        context.load()
        return context

    def _register_recovery_handler(self, container: ServiceContainer) -> None:
        """Register RecoveryHandler as singleton.

        The RecoveryHandler integrates with:
        - Q-learning for adaptive recovery strategy selection
        - UsageAnalytics for telemetry
        - ContextCompactor for proactive context management

        Note: Session-specific state (recent_responses, consecutive_failures)
        is reset via set_session_id() when orchestrator creates a new session.
        """
        from victor.agent.protocols import RecoveryHandlerProtocol

        def create_recovery_handler(_: ServiceContainer) -> Any:
            enabled = getattr(self._settings, "enable_recovery_system", True)
            if not enabled:
                return _NullRecoveryHandler()

            try:
                from victor.agent.recovery import RecoveryHandler

                return RecoveryHandler.create(settings=self._settings)
            except ImportError as e:
                logger.warning(f"RecoveryHandler not available: {e}")
                return _NullRecoveryHandler()
            except Exception as e:
                logger.warning(f"RecoveryHandler creation failed: {e}")
                return _NullRecoveryHandler()

        container.register(
            RecoveryHandlerProtocol,
            create_recovery_handler,
            ServiceLifetime.SINGLETON,
        )

    # =========================================================================
    # Factory methods for scoped services
    # =========================================================================

    def _create_conversation_state_machine(self) -> Any:
        """Create ConversationStateMachine instance."""
        from victor.agent.conversation_state import ConversationStateMachine

        return ConversationStateMachine()

    def _create_unified_task_tracker(self) -> Any:
        """Create UnifiedTaskTracker instance."""
        from victor.agent.unified_task_tracker import UnifiedTaskTracker

        return UnifiedTaskTracker()

    def _create_message_history(self) -> Any:
        """Create MessageHistory instance."""
        from victor.agent.message_history import MessageHistory

        return MessageHistory(
            system_prompt="",  # Will be set by orchestrator
            max_history_messages=getattr(self._settings, "max_conversation_history", 100),
        )

    # =========================================================================
    # Factory methods for new framework services
    # =========================================================================

    def _register_path_resolver(self, container: ServiceContainer) -> None:
        """Register PathResolver as singleton."""
        from victor.protocols.path_resolver import PathResolver, IPathResolver

        container.register(
            IPathResolver,
            lambda c: PathResolver(),
            ServiceLifetime.SINGLETON,
        )

    def _register_tool_access_controller(self, container: ServiceContainer) -> None:
        """Register ToolAccessController as scoped service."""
        from victor.agent.protocols import IToolAccessController
        from victor.agent.tool_access_controller import (
            create_tool_access_controller,
        )

        container.register(
            IToolAccessController,
            lambda c: create_tool_access_controller(
                registry=c.get_or_none("ToolRegistryProtocol"),
            ),
            ServiceLifetime.SCOPED,
        )

    def _register_budget_manager(self, container: ServiceContainer) -> None:
        """Register BudgetManager as scoped service."""
        from victor.agent.protocols import IBudgetManager, BudgetConfig
        from victor.agent.budget_manager import create_budget_manager

        # Get budget settings from settings
        base_tool_calls = getattr(self._settings, "tool_budget", 30)
        base_iterations = getattr(self._settings, "max_iterations", 50)
        base_exploration = getattr(self._settings, "max_exploration_iterations", 8)
        base_action = getattr(self._settings, "max_action_iterations", 12)

        config = BudgetConfig(
            base_tool_calls=base_tool_calls,
            base_iterations=base_iterations,
            base_exploration=base_exploration,
            base_action=base_action,
        )

        container.register(
            IBudgetManager,
            lambda c: create_budget_manager(config=config),
            ServiceLifetime.SCOPED,
        )

    # =========================================================================
    # Infrastructure service factory methods
    # =========================================================================

    def _create_code_execution_manager(self) -> Any:
        """Create CodeExecutionManager instance."""
        from victor.tools.code_executor_tool import CodeExecutionManager

        manager = CodeExecutionManager()
        manager.start()
        return manager

    def _create_workflow_registry(self) -> Any:
        """Create WorkflowRegistry instance."""
        from victor.workflows.base import WorkflowRegistry

        return WorkflowRegistry()

    def _create_usage_analytics(self) -> Any:
        """Create UsageAnalytics singleton instance."""
        from victor.agent.usage_analytics import UsageAnalytics, AnalyticsConfig
        from pathlib import Path

        # Use settings cache_dir if available
        analytics_cache_dir = (
            Path(self._settings.cache_dir)
            if hasattr(self._settings, "cache_dir") and self._settings.cache_dir
            else None
        )

        return UsageAnalytics.get_instance(
            AnalyticsConfig(
                cache_dir=analytics_cache_dir,
                enable_prometheus_export=getattr(self._settings, "enable_prometheus_export", True),
            )
        )

    def _create_tool_sequence_tracker(self) -> Any:
        """Create ToolSequenceTracker instance."""
        from victor.agent.tool_sequence_tracker import create_sequence_tracker

        return create_sequence_tracker(
            use_predefined=getattr(self._settings, "use_predefined_patterns", True),
            learning_rate=getattr(self._settings, "sequence_learning_rate", 0.3),
        )

    def _create_context_compactor(self) -> Any:
        """Create ContextCompactor instance.

        Note: This is a placeholder that will be replaced when the orchestrator
        creates the actual compactor with a ConversationController instance.
        The DI container registration is primarily for protocol compliance.
        """
        # ContextCompactor requires a ConversationController which is not available
        # at container initialization time. Return None and let the orchestrator
        # create it via the factory method when the controller is available.
        return None

    def _create_mode_controller(self) -> Any:
        """Create AgentModeController instance."""
        from victor.agent.mode_controller import AgentModeController, AgentMode

        initial_mode_str = getattr(self._settings, "default_agent_mode", "build")
        try:
            initial_mode = AgentMode(initial_mode_str.lower())
        except ValueError:
            initial_mode = AgentMode.BUILD

        return AgentModeController(initial_mode=initial_mode)

    def _create_tool_deduplication_tracker(self) -> Any:
        """Create ToolDeduplicationTracker instance."""
        from victor.agent.tool_deduplication import ToolDeduplicationTracker

        window_size = getattr(self._settings, "dedup_window_size", 10)
        similarity_threshold = getattr(self._settings, "dedup_similarity_threshold", 0.7)

        return ToolDeduplicationTracker(
            window_size=window_size,
            similarity_threshold=similarity_threshold,
        )

    # =========================================================================
    # Utility service factory methods
    # =========================================================================

    def _create_debug_logger(self) -> Any:
        """Create DebugLogger instance."""
        from victor.agent.debug_logger import get_debug_logger

        return get_debug_logger()

    def _create_task_type_hinter(self) -> Any:
        """Create TaskTypeHinter wrapper."""
        from victor.verticals.coding.prompts import get_task_type_hint

        class TaskTypeHinter:
            """Wrapper for task type hint retrieval."""

            def get_hint(self, task_type: str) -> str:
                """Get prompt hint for a specific task type."""
                return get_task_type_hint(task_type)

        return TaskTypeHinter()

    def _create_reminder_manager(self) -> Any:
        """Create ContextReminderManager instance."""
        from victor.agent.context_reminder import create_reminder_manager

        provider = getattr(self._settings, "provider", "unknown")
        task_complexity = "medium"
        tool_budget = getattr(self._settings, "tool_budget", 10)

        return create_reminder_manager(
            provider=provider,
            task_complexity=task_complexity,
            tool_budget=tool_budget,
        )

    def _create_rl_coordinator(self) -> Any:
        """Create RLCoordinator instance."""
        from victor.agent.rl.coordinator import get_rl_coordinator

        return get_rl_coordinator()

    def _create_safety_checker(self) -> Any:
        """Create SafetyChecker instance."""
        from victor.agent.safety import get_safety_checker

        return get_safety_checker()

    def _create_auto_committer(self) -> Any:
        """Create AutoCommitter instance."""
        from victor.agent.auto_commit import get_auto_committer

        return get_auto_committer()

    def _create_mcp_bridge(self) -> Any:
        """Create MCP bridge wrapper."""
        from victor.tools.mcp_bridge_tool import configure_mcp_client, get_mcp_tool_definitions

        class MCPBridge:
            """Wrapper for MCP bridge functionality."""

            def configure_client(self, client: Any, prefix: str = "mcp") -> None:
                """Configure the MCP client."""
                configure_mcp_client(client, prefix)

            def get_tool_definitions(self) -> list:
                """Return MCP tools as Victor tool definitions."""
                return get_mcp_tool_definitions()

        return MCPBridge()

    # =========================================================================
    # Infrastructure service factory methods
    # =========================================================================

    def _create_tool_dependency_graph(self) -> Any:
        """Create ToolDependencyGraph instance."""
        from victor.tools.dependency_graph import ToolDependencyGraph

        return ToolDependencyGraph()

    def _create_tool_plugin_registry(self) -> Any:
        """Create ToolPluginRegistry instance."""
        from victor.tools.plugin_registry import ToolPluginRegistry

        return ToolPluginRegistry()

    def _create_semantic_tool_selector(self) -> Any:
        """Create SemanticToolSelector instance."""
        from victor.tools.semantic_selector import SemanticToolSelector

        # Get embedding model from settings
        embedding_model = getattr(self._settings, "embedding_model", "all-MiniLM-L12-v2")
        use_semantic_selection = getattr(self._settings, "use_semantic_tool_selection", True)

        if not use_semantic_selection:
            # Return a no-op selector that just returns all tools
            class NoOpSelector:
                def select_tools(
                    self,
                    query: str,
                    available_tools: list,
                    max_tools: int = 10,
                    threshold: float = 0.3,
                ) -> list:
                    return available_tools[:max_tools]

                def compute_similarity(self, query: str, tool_description: str) -> float:
                    return 1.0

            return NoOpSelector()

        return SemanticToolSelector(embedding_model=embedding_model)

    def _create_provider_registry(self) -> Any:
        """Create ProviderRegistry wrapper.

        Note: ProviderRegistry is a class with class methods,
        so we return the class itself, not an instance.
        """
        from victor.providers.registry import ProviderRegistry

        # Return the class itself - it's used as a class with class methods
        return ProviderRegistry

    # =========================================================================
    # Analytics & observability service factory methods
    # =========================================================================

    def _create_conversation_embedding_store(self) -> Any:
        """Create ConversationEmbeddingStore instance."""
        from victor.agent.conversation_embedding_store import ConversationEmbeddingStore
        from victor.embeddings.service import EmbeddingService
        from pathlib import Path

        embedding_model = getattr(self._settings, "embedding_model", "all-MiniLM-L12-v2")
        cache_dir = Path(getattr(self._settings, "cache_dir", ".victor/cache"))

        # Create embedding service
        embedding_service = EmbeddingService(model_name=embedding_model)

        # Create embedding store with SQLite backend
        sqlite_path = cache_dir / "embeddings" / "conversation.db"

        return ConversationEmbeddingStore(
            embedding_service=embedding_service,
            sqlite_db_path=sqlite_path,
        )

    def _create_metrics_collector(self) -> Any:
        """Create MetricsCollector instance."""
        from victor.agent.metrics_collector import MetricsCollector, MetricsCollectorConfig
        from victor.analytics.logger import UsageLogger
        from pathlib import Path

        # Create config with provider/model info
        model = getattr(self._settings, "model", "unknown")
        provider = getattr(self._settings, "provider", "unknown")
        analytics_enabled = getattr(self._settings, "enable_analytics", True)

        config = MetricsCollectorConfig(
            model=model,
            provider=provider,
            analytics_enabled=analytics_enabled,
        )

        # Create usage logger
        log_file = Path(getattr(self._settings, "usage_log_path", ".victor/logs/usage.log"))
        usage_logger = UsageLogger(log_file=log_file)

        return MetricsCollector(
            config=config,
            usage_logger=usage_logger,
        )

    def _create_tool_cache(self) -> Any:
        """Create ToolCache instance."""
        from victor.cache.tool_cache import ToolCache

        enabled = getattr(self._settings, "enable_tool_cache", True)
        ttl = getattr(self._settings, "tool_cache_ttl", 300)

        if not enabled:
            # Return a no-op cache
            class NoOpCache:
                def get(self, key: str) -> Any:
                    return None

                def set(self, key: str, value: Any, ttl: int = None) -> None:
                    pass

                def invalidate(self, key: str) -> None:
                    pass

                def clear(self) -> None:
                    pass

            return NoOpCache()

        return ToolCache(ttl=ttl)

    def _create_usage_logger(self) -> Any:
        """Create UsageLogger instance."""
        from victor.analytics.logger import UsageLogger
        from pathlib import Path

        log_file = Path(getattr(self._settings, "usage_log_path", ".victor/logs/usage.log"))
        enabled = getattr(self._settings, "enable_usage_logging", True)

        return UsageLogger(log_file=log_file, enabled=enabled)

    def _create_streaming_metrics_collector(self) -> Any:
        """Create StreamingMetricsCollector instance."""
        from victor.analytics.streaming_metrics import StreamingMetricsCollector
        from pathlib import Path

        enabled = getattr(self._settings, "streaming_metrics_enabled", True)
        max_history = getattr(self._settings, "streaming_metrics_history_size", 100)

        if not enabled:
            # Return a no-op collector
            class NoOpStreamingMetrics:
                def record_chunk(self, chunk_size: int, timestamp: float, **metadata: Any) -> None:
                    pass

                def get_metrics(self) -> dict:
                    return {}

                def reset(self) -> None:
                    pass

            return NoOpStreamingMetrics()

        export_path = (
            Path(getattr(self._settings, "cache_dir", ".victor/cache")) / "streaming_metrics.json"
        )

        return StreamingMetricsCollector(max_history=max_history, export_path=export_path)

    def _create_intent_classifier(self) -> Any:
        """Create IntentClassifier instance."""
        from victor.embeddings.intent_classifier import IntentClassifier
        from victor.embeddings.service import EmbeddingService
        from pathlib import Path

        embedding_model = getattr(self._settings, "embedding_model", "all-MiniLM-L12-v2")
        cache_dir = (
            Path(getattr(self._settings, "cache_dir", ".victor/cache")) / "intent_classifier"
        )

        # Create embedding service
        embedding_service = EmbeddingService(model_name=embedding_model)

        return IntentClassifier(
            cache_dir=cache_dir,
            embedding_service=embedding_service,
        )

    # =========================================================================
    # Helper/adapter service factory methods
    # =========================================================================

    def _create_system_prompt_builder(self) -> Any:
        """Create SystemPromptBuilder instance."""
        from victor.agent.prompt_builder import SystemPromptBuilder

        provider_name = getattr(self._settings, "provider", "anthropic")
        model = getattr(self._settings, "model", "claude-opus-4")

        return SystemPromptBuilder(
            provider_name=provider_name,
            model=model,
        )

    def _create_tool_selector(self) -> Any:
        """Create ToolSelector instance."""
        from victor.agent.tool_selection import ToolSelector
        from victor.tools.registry import ToolRegistry

        # Create a ToolRegistry instance for the ToolSelector
        tools = ToolRegistry()
        model = getattr(self._settings, "model", "claude-opus-4")
        provider_name = getattr(self._settings, "provider", "anthropic")
        fallback_max_tools = getattr(self._settings, "fallback_max_tools", 8)

        return ToolSelector(
            tools=tools,
            model=model,
            provider_name=provider_name,
            fallback_max_tools=fallback_max_tools,
        )

    def _create_tool_executor(self) -> Any:
        """Create ToolExecutor instance."""
        from victor.agent.tool_executor import ToolExecutor
        from victor.tools.registry import ToolRegistry

        # Create a ToolRegistry instance for the ToolExecutor
        tool_registry = ToolRegistry()

        return ToolExecutor(tool_registry=tool_registry)

    def _create_tool_output_formatter(self) -> Any:
        """Create ToolOutputFormatter instance."""
        from victor.agent.tool_output_formatter import create_tool_output_formatter

        # Factory function handles all defaults
        return create_tool_output_formatter()

    def _create_parallel_executor(self) -> Any:
        """Create ParallelExecutor instance."""
        from victor.agent.parallel_executor import create_parallel_executor
        from victor.agent.tool_executor import ToolExecutor
        from victor.tools.registry import ToolRegistry

        # Create ToolExecutor instance needed by parallel executor
        tool_registry = ToolRegistry()
        tool_executor = ToolExecutor(tool_registry=tool_registry)

        max_concurrent = getattr(self._settings, "max_concurrent_tools", 5)
        enable = getattr(self._settings, "enable_parallel_execution", True)

        return create_parallel_executor(
            tool_executor=tool_executor,
            max_concurrent=max_concurrent,
            enable=enable,
        )

    def _create_response_completer(self) -> Any:
        """Create ResponseCompleter instance.

        Note: This returns a no-op completer since we don't have access to the provider
        instance here. The actual ResponseCompleter should be created when the provider
        is available.
        """
        from victor.agent.response_completer import create_response_completer

        # Create a mock provider for now - in practice, this would need the actual provider
        class MockProvider:
            """Mock provider for ResponseCompleter."""

            async def chat(self, *args, **kwargs):
                return {"content": "", "model": "mock"}

        mock_provider = MockProvider()
        max_retries = getattr(self._settings, "max_response_retries", 3)
        force_response = getattr(self._settings, "force_response", True)

        return create_response_completer(
            provider=mock_provider,
            max_retries=max_retries,
            force_response=force_response,
        )

    def _create_streaming_handler(self) -> Any:
        """Create StreamingHandler instance."""
        from victor.agent.streaming import StreamingChatHandler

        # Create a mock message adder for now
        class MockMessageAdder:
            """Mock message adder for StreamingChatHandler."""

            def add_message(self, role: str, content: str):
                pass

        message_adder = MockMessageAdder()
        session_idle_timeout = getattr(self._settings, "session_idle_timeout", 180.0)

        return StreamingChatHandler(
            settings=self._settings,
            message_adder=message_adder,
            session_idle_timeout=session_idle_timeout,
        )

    def _create_recovery_coordinator(self) -> Any:
        """Create RecoveryCoordinator instance.

        The RecoveryCoordinator centralizes all recovery and error handling logic
        for streaming chat sessions, including condition checking, action handling,
        and recovery integration.

        Returns:
            RecoveryCoordinator instance
        """
        from victor.agent.recovery_coordinator import RecoveryCoordinator
        from victor.agent.protocols import (
            RecoveryHandlerProtocol,
            StreamingHandlerProtocol,
            ContextCompactorProtocol,
            TaskTrackerProtocol,
        )

        # Get recovery handler from DI container (optional)
        recovery_handler = self.container.get_optional(RecoveryHandlerProtocol)

        # Get recovery integration (optional)
        # Note: OrchestratorRecoveryIntegration is not in DI yet, will be None for now
        recovery_integration = None

        # Get streaming handler from DI container
        streaming_handler = self.container.get(StreamingHandlerProtocol)

        # Get context compactor from DI container (optional)
        context_compactor = self.container.get_optional(ContextCompactorProtocol)

        # Get unified tracker from DI container
        unified_tracker = self.container.get(TaskTrackerProtocol)

        return RecoveryCoordinator(
            recovery_handler=recovery_handler,
            recovery_integration=recovery_integration,
            streaming_handler=streaming_handler,
            context_compactor=context_compactor,
            unified_tracker=unified_tracker,
            settings=self._settings,
        )

    def _create_chunk_generator(self) -> Any:
        """Create ChunkGenerator instance.

        The ChunkGenerator provides a centralized interface for generating streaming
        chunks for various purposes (tool execution, status updates, metrics, content).

        Returns:
            ChunkGenerator instance
        """
        from victor.agent.chunk_generator import ChunkGenerator
        from victor.agent.protocols import StreamingHandlerProtocol

        # Get streaming handler from DI container
        streaming_handler = self.container.get(StreamingHandlerProtocol)

        return ChunkGenerator(
            streaming_handler=streaming_handler,
            settings=self._settings,
        )

    def _create_tool_planner(self) -> Any:
        """Create ToolPlanner instance.

        The ToolPlanner provides a centralized interface for tool planning operations,
        including goal inference, tool sequence planning, and intent-based filtering.

        Returns:
            ToolPlanner instance
        """
        from victor.agent.tool_planner import ToolPlanner
        from victor.agent.protocols import ToolRegistrarProtocol

        # Get tool registrar from DI container
        tool_registrar = self.container.get(ToolRegistrarProtocol)

        return ToolPlanner(
            tool_registrar=tool_registrar,
            settings=self._settings,
        )

    def _create_task_coordinator(self) -> Any:
        """Create TaskCoordinator instance.

        The TaskCoordinator provides a centralized interface for task coordination,
        including task preparation, intent detection, and task-specific guidance.

        Note: ConversationController is not injected as it hasn't been migrated
        to DI yet. It's passed as a parameter when calling TaskCoordinator methods.

        Returns:
            TaskCoordinator instance
        """
        from victor.agent.task_coordinator import TaskCoordinator
        from victor.agent.protocols import (
            TaskAnalyzerProtocol,
            TaskTrackerProtocol,
            SystemPromptBuilderProtocol,
        )

        # Get dependencies from DI container
        task_analyzer = self.container.get(TaskAnalyzerProtocol)
        unified_tracker = self.container.get(TaskTrackerProtocol)
        prompt_builder = self.container.get(SystemPromptBuilderProtocol)

        return TaskCoordinator(
            task_analyzer=task_analyzer,
            unified_tracker=unified_tracker,
            prompt_builder=prompt_builder,
            settings=self._settings,
        )


# =============================================================================
# Null implementations for graceful degradation
# =============================================================================


class _NullObservability:
    """No-op observability implementation."""

    def on_tool_start(self, tool_name: str, arguments: dict, tool_id: str) -> None:
        pass

    def on_tool_end(
        self,
        tool_name: str,
        result: Any,
        success: bool,
        tool_id: str,
        error: Optional[str] = None,
    ) -> None:
        pass

    def wire_state_machine(self, state_machine: Any) -> None:
        pass

    def on_error(self, error: Exception, context: dict) -> None:
        pass


class _NullTaskAnalyzer:
    """No-op task analyzer implementation."""

    def analyze(self, prompt: str) -> dict:
        return {"complexity": "unknown", "intent": "unknown"}

    def classify_complexity(self, prompt: str) -> Any:
        return None

    def detect_intent(self, prompt: str) -> Any:
        return None


class _NullRecoveryHandler:
    """No-op recovery handler implementation for disabled mode."""

    @property
    def enabled(self) -> bool:
        return False

    @property
    def consecutive_failures(self) -> int:
        return 0

    def detect_failure(self, *args: Any, **kwargs: Any) -> None:
        return None

    async def recover(self, *args: Any, **kwargs: Any) -> Any:
        # Return a no-op outcome
        from dataclasses import dataclass, field
        from enum import Enum, auto

        class _RecoveryAction(Enum):
            CONTINUE = auto()

        @dataclass
        class _RecoveryResult:
            action: _RecoveryAction = _RecoveryAction.CONTINUE
            success: bool = True
            strategy_name: str = "disabled"
            reason: str = "Recovery system disabled"

        @dataclass
        class _RecoveryOutcome:
            result: _RecoveryResult = field(default_factory=_RecoveryResult)

        return _RecoveryOutcome()

    def record_outcome(self, success: bool, quality_improvement: float = 0.0) -> None:
        pass

    def track_response(self, content: str) -> None:
        pass

    def reset_session(self, session_id: str) -> None:
        pass

    def set_context_compactor(self, compactor: Any) -> None:
        pass

    def set_session_id(self, session_id: str) -> None:
        pass

    def get_diagnostics(self) -> dict:
        return {"enabled": False}


# =============================================================================
# Convenience function
# =============================================================================


def configure_orchestrator_services(
    container: ServiceContainer,
    settings: "Settings",
) -> None:
    """Configure all orchestrator services in one call.

    Convenience function for application bootstrap. Creates a service
    provider and registers all services.

    Args:
        container: DI container to register services in
        settings: Application settings

    Example:
        from victor.core.container import ServiceContainer
        from victor.agent.service_provider import configure_orchestrator_services

        container = ServiceContainer()
        configure_orchestrator_services(container, settings)
    """
    provider = OrchestratorServiceProvider(settings)
    provider.register_services(container)


__all__ = [
    "OrchestratorServiceProvider",
    "configure_orchestrator_services",
]
