"""Factory functions for service instantiation and dependency injection.

This module provides factory functions for creating service instances with proper
dependency injection, ensuring clean service composition and testability.
"""

import logging
from typing import Any, Dict, Optional

from ..base.services import BaseService
from ..database.connection import get_session
from ..repositories.media_repository import MediaRepositoryProtocol, create_media_repository
from ..repositories.transcription_repository import TranscriptionRepositoryProtocol, create_transcription_repository
from ..repositories.youtube_repository import YouTubeRepository, YouTubeRepositoryProtocol

from .protocols import (
    YouTubeServiceProtocol,
    MediaServiceProtocol,
    TranscriptionServiceProtocol,
    EnhancementServiceProtocol,
    ExportServiceProtocol,
    BatchProcessorProtocol,
)

logger = logging.getLogger(__name__)


def create_youtube_service(
    repository: Optional[YouTubeRepositoryProtocol] = None,
    config: Optional[Dict[str, Any]] = None
) -> YouTubeServiceProtocol:
    """Create a YouTube service instance with dependency injection.
    
    Args:
        repository: YouTube repository instance. If None, creates a new one.
        config: Service configuration. If None, uses default config.
        
    Returns:
        YouTubeServiceProtocol: Configured YouTube service instance.
    """
    from .youtube_service import YouTubeMetadataService
    
    if repository is None:
        repository = YouTubeRepository()
    
    service = YouTubeMetadataService(repository=repository, config=config)
    logger.info("Created YouTube service instance")
    return service


def create_media_service(
    download_service: Optional[Any] = None,
    preprocessing_service: Optional[Any] = None,
    database_service: Optional[Any] = None,
    config: Optional[Dict[str, Any]] = None
) -> MediaServiceProtocol:
    """Create a media service instance with dependency injection.
    
    Args:
        download_service: Media download service instance.
        preprocessing_service: Media preprocessing service instance.
        database_service: Media database service instance.
        config: Service configuration. If None, uses default config.
        
    Returns:
        MediaServiceProtocol: Configured media service instance.
    """
    from .media_service import MediaService
    
    # Create default services if not provided
    if download_service is None:
        from .media_download import MediaDownloadService
        download_service = MediaDownloadService()
    
    if preprocessing_service is None:
        from .media_preprocessing import MediaPreprocessingService
        preprocessing_service = MediaPreprocessingService()
    
    if database_service is None:
        from .media_database import MediaDatabaseService
        database_service = MediaDatabaseService()
    
    service = MediaService(
        download_service=download_service,
        preprocessing_service=preprocessing_service,
        database_service=database_service,
        config=config
    )
    logger.info("Created media service instance")
    return service


def create_transcription_service(
    repository: Optional[TranscriptionRepositoryProtocol] = None,
    config: Optional[Dict[str, Any]] = None
) -> TranscriptionServiceProtocol:
    """Create a transcription service instance with dependency injection.
    
    Args:
        repository: Transcription repository instance. If None, creates a new one.
        config: Service configuration. If None, uses default config.
        
    Returns:
        TranscriptionServiceProtocol: Configured transcription service instance.
    """
    from .local_transcription_service import LocalTranscriptionService
    
    if repository is None:
        repository = create_transcription_repository()
    
    service = LocalTranscriptionService(repository=repository, config=config)
    logger.info("Created local transcription service instance")
    return service


def create_enhancement_service(
    config: Optional[Dict[str, Any]] = None
) -> EnhancementServiceProtocol:
    """Create an enhancement service instance with dependency injection.
    
    Args:
        config: Service configuration. If None, uses default config.
        
    Returns:
        EnhancementServiceProtocol: Configured enhancement service instance.
    """
    from .enhancement.service import DeepSeekEnhancementService
    from .enhancement.config import EnhancementConfig
    
    if config is None:
        enhancement_config = EnhancementConfig()
    else:
        enhancement_config = EnhancementConfig(**config)
    
    service = DeepSeekEnhancementService(config=enhancement_config)
    logger.info("Created enhancement service instance")
    return service


def create_export_service(
    config: Optional[Dict[str, Any]] = None
) -> ExportServiceProtocol:
    """Create an export service instance with dependency injection.
    
    Args:
        config: Service configuration. If None, uses default config.
        
    Returns:
        ExportServiceProtocol: Configured export service instance.
    """
    from .export_service import ExportService
    
    service = ExportService(config=config)
    logger.info("Created export service instance")
    return service


def create_batch_processor(
    media_service: Optional[MediaServiceProtocol] = None,
    transcription_service: Optional[TranscriptionServiceProtocol] = None,
    enhancement_service: Optional[EnhancementServiceProtocol] = None,
    export_service: Optional[ExportServiceProtocol] = None,
    config: Optional[Dict[str, Any]] = None
) -> BatchProcessorProtocol:
    """Create a batch processor instance with dependency injection.
    
    Args:
        media_service: Media service instance.
        transcription_service: Transcription service instance.
        enhancement_service: Enhancement service instance.
        export_service: Export service instance.
        config: Service configuration. If None, uses default config.
        
    Returns:
        BatchProcessorProtocol: Configured batch processor instance.
    """
    from .batch_processor import BatchProcessor
    
    # Create default services if not provided
    if media_service is None:
        media_service = create_media_service()
    
    if transcription_service is None:
        transcription_service = create_transcription_service()
    
    if enhancement_service is None:
        enhancement_service = create_enhancement_service()
    
    if export_service is None:
        export_service = create_export_service()
    
    processor = BatchProcessor(
        media_service=media_service,
        transcription_service=transcription_service,
        enhancement_service=enhancement_service,
        export_service=export_service,
        config=config
    )
    logger.info("Created batch processor instance")
    return processor


def create_service_container(
    config: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
    """Create a complete service container with all services.
    
    This function creates all services with proper dependency injection
    and returns them in a dictionary for easy access.
    
    Args:
        config: Global configuration for all services.
        
    Returns:
        Dict containing all service instances:
        - youtube_service: YouTubeServiceProtocol
        - media_service: MediaServiceProtocol
        - transcription_service: TranscriptionServiceProtocol
        - enhancement_service: EnhancementServiceProtocol
        - export_service: ExportServiceProtocol
        - batch_processor: BatchProcessorProtocol
    """
    # Create shared repositories
    youtube_repository = YouTubeRepository()
    transcription_repository = create_transcription_repository()
    media_repository = create_media_repository()
    
    # Create services with dependency injection
    services = {
        "youtube_service": create_youtube_service(
            repository=youtube_repository,
            config=config.get("youtube") if config else None
        ),
        "media_service": create_media_service(
            config=config.get("media") if config else None
        ),
        "transcription_service": create_transcription_service(
            repository=transcription_repository,
            config=config.get("transcription") if config else None
        ),
        "enhancement_service": create_enhancement_service(
            config=config.get("enhancement") if config else None
        ),
        "export_service": create_export_service(
            config=config.get("export") if config else None
        ),
    }
    
    # Create batch processor with all services
    services["batch_processor"] = create_batch_processor(
        media_service=services["media_service"],
        transcription_service=services["transcription_service"],
        enhancement_service=services["enhancement_service"],
        export_service=services["export_service"],
        config=config.get("batch") if config else None
    )
    
    logger.info("Created complete service container with all services")
    return services


def create_minimal_service_container(
    config: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
    """Create a minimal service container with only essential services.
    
    This function creates only the core services needed for basic functionality.
    
    Args:
        config: Global configuration for services.
        
    Returns:
        Dict containing minimal service instances:
        - youtube_service: YouTubeServiceProtocol
        - media_service: MediaServiceProtocol
        - transcription_service: TranscriptionServiceProtocol
    """
    services = {
        "youtube_service": create_youtube_service(
            config=config.get("youtube") if config else None
        ),
        "media_service": create_media_service(
            config=config.get("media") if config else None
        ),
        "transcription_service": create_transcription_service(
            config=config.get("transcription") if config else None
        ),
    }
    
    logger.info("Created minimal service container with core services")
    return services


# Service validation utilities

def validate_service_container(services: Dict[str, Any]) -> bool:
    """Validate that all services in a container implement their protocols correctly.
    
    Args:
        services: Dictionary of service instances.
        
    Returns:
        True if all services are valid, False otherwise.
    """
    from .protocols import validate_protocol_implementation
    
    expected_protocols = {
        "youtube_service": YouTubeServiceProtocol,
        "media_service": MediaServiceProtocol,
        "transcription_service": TranscriptionServiceProtocol,
        "enhancement_service": EnhancementServiceProtocol,
        "export_service": ExportServiceProtocol,
        "batch_processor": BatchProcessorProtocol,
    }
    
    for service_name, service_instance in services.items():
        if service_name in expected_protocols:
            protocol = expected_protocols[service_name]
            if not validate_protocol_implementation(service_instance, protocol):
                logger.error(f"Service {service_name} does not implement {protocol.__name__}")
                return False
    
    logger.info("All services in container validate correctly")
    return True


def get_service_dependencies(service_name: str) -> Dict[str, str]:
    """Get the dependencies for a specific service.
    
    Args:
        service_name: Name of the service.
        
    Returns:
        Dictionary mapping dependency names to their types.
    """
    dependencies = {
        "youtube_service": {
            "repository": "YouTubeRepositoryProtocol"
        },
        "media_service": {
            "download_service": "MediaDownloadService",
            "preprocessing_service": "MediaPreprocessingService", 
            "database_service": "MediaDatabaseService"
        },
        "transcription_service": {
            "repository": "TranscriptionRepositoryProtocol"
        },
        "enhancement_service": {
            "config": "EnhancementConfig"
        },
        "export_service": {
            "config": "Dict[str, Any]"
        },
        "batch_processor": {
            "media_service": "MediaServiceProtocol",
            "transcription_service": "TranscriptionServiceProtocol",
            "enhancement_service": "EnhancementServiceProtocol",
            "export_service": "ExportServiceProtocol"
        }
    }
    
    return dependencies.get(service_name, {})
