"""
AI Provider Factory (Factory Pattern)
"""

import logging
from typing import Dict, Type, Optional

from core import AIProcessingError
from .base_provider import AIProvider
from .claude_provider import ClaudeProvider
from .gemini_provider import GeminiProvider
from .parallel_provider import ParallelAIProvider


class AIProviderFactory:
    """Factory for creating AI providers with fallback and parallel execution"""

    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self._providers: Dict[str, AIProvider] = {
            "claude": ClaudeProvider(),
            "gemini": GeminiProvider(),
        }
        self._parallel_provider: Optional[ParallelAIProvider] = None

    def get_provider(self, preferred: str = "gemini") -> AIProvider:
        """Get available provider with fallback"""
        # Try preferred provider first
        if preferred in self._providers:
            provider = self._providers[preferred]
            if provider.is_available():
                self.logger.info(f"Using {preferred} provider")
                return provider

        # Fallback to any available provider
        for name, provider in self._providers.items():
            if provider.is_available():
                self.logger.info(f"Falling back to {name} provider")
                return provider

        raise AIProcessingError("No AI providers available")

    def get_all_available(self) -> Dict[str, AIProvider]:
        """Get all available providers"""
        return {
            name: provider
            for name, provider in self._providers.items()
            if provider.is_available()
        }

    def get_best_provider(self) -> AIProvider:
        """Get the best available provider (Claude > Gemini)"""
        return self.get_provider("claude")

    def get_parallel_provider(self, max_workers: int = 4) -> ParallelAIProvider:
        """Get parallel provider for racing multiple AI providers"""
        available = self.get_all_available()

        if not available:
            raise AIProcessingError("No providers available for parallel execution")

        if self._parallel_provider is None:
            self._parallel_provider = ParallelAIProvider(
                providers=available,
                max_workers=max_workers
            )
            self.logger.info(
                f"Created parallel provider with {len(available)} workers: "
                f"{', '.join(available.keys())}"
            )

        return self._parallel_provider

    def use_parallel(self) -> bool:
        """Check if parallel execution should be used (multiple providers available)"""
        return len(self.get_all_available()) > 1


# Global instance
ai_provider_factory = AIProviderFactory()
