"""Unit tests for service factory functions."""

import pytest
from unittest.mock import MagicMock, patch
from typing import Dict, Any

from src.services.factories import (
    create_youtube_service,
    create_media_service,
    create_transcription_service,
    create_enhancement_service,
    create_export_service,
    create_batch_processor,
    create_service_container,
    create_minimal_service_container,
    validate_service_container,
    get_service_dependencies,
)


class TestServiceFactories:
    """Test service factory functions."""

    def test_create_youtube_service_basic(self):
        """Test YouTube service factory function basic functionality."""
        # Test that the function can be called without errors
        # We'll use a mock repository to avoid database dependencies
        mock_repository = MagicMock()
        
        with patch('src.services.factories.YouTubeRepository', return_value=mock_repository):
            with patch('src.services.factories.YouTubeMetadataService') as mock_service_class:
                mock_service_instance = MagicMock()
                mock_service_class.return_value = mock_service_instance
                
                service = create_youtube_service()
                
                # Verify service was created
                mock_service_class.assert_called_once()
                assert service == mock_service_instance

    def test_create_media_service_basic(self):
        """Test media service factory function basic functionality."""
        # Test that the function can be called without errors
        with patch('src.services.factories.MediaDownloadService') as mock_download:
            with patch('src.services.factories.MediaPreprocessingService') as mock_preprocessing:
                with patch('src.services.factories.MediaDatabaseService') as mock_database:
                    with patch('src.services.factories.MediaService') as mock_service_class:
                        mock_service_instance = MagicMock()
                        mock_service_class.return_value = mock_service_instance
                        
                        service = create_media_service()
                        
                        # Verify service was created
                        mock_service_class.assert_called_once()
                        assert service == mock_service_instance

    def test_create_transcription_service_basic(self):
        """Test transcription service factory function basic functionality."""
        # Test that the function can be called without errors
        mock_repository = MagicMock()
        
        with patch('src.services.factories.create_transcription_repository', return_value=mock_repository):
            with patch('src.services.factories.TranscriptionService') as mock_service_class:
                mock_service_instance = MagicMock()
                mock_service_class.return_value = mock_service_instance
                
                service = create_transcription_service()
                
                # Verify service was created
                mock_service_class.assert_called_once()
                assert service == mock_service_instance

    def test_create_enhancement_service_basic(self):
        """Test enhancement service factory function basic functionality."""
        # Test that the function can be called without errors
        mock_config = MagicMock()
        
        with patch('src.services.factories.EnhancementConfig', return_value=mock_config):
            with patch('src.services.factories.DeepSeekEnhancementService') as mock_service_class:
                mock_service_instance = MagicMock()
                mock_service_class.return_value = mock_service_instance
                
                service = create_enhancement_service()
                
                # Verify service was created
                mock_service_class.assert_called_once()
                assert service == mock_service_instance

    def test_create_export_service_basic(self):
        """Test export service factory function basic functionality."""
        # Test that the function can be called without errors
        with patch('src.services.factories.ExportService') as mock_service_class:
            mock_service_instance = MagicMock()
            mock_service_class.return_value = mock_service_instance
            
            service = create_export_service()
            
            # Verify service was created
            mock_service_class.assert_called_once()
            assert service == mock_service_instance

    def test_create_batch_processor_basic(self):
        """Test batch processor factory function basic functionality."""
        # Test that the function can be called without errors
        mock_services = {
            'media_service': MagicMock(),
            'transcription_service': MagicMock(),
            'enhancement_service': MagicMock(),
            'export_service': MagicMock(),
        }
        
        with patch('src.services.factories.create_media_service', return_value=mock_services['media_service']):
            with patch('src.services.factories.create_transcription_service', return_value=mock_services['transcription_service']):
                with patch('src.services.factories.create_enhancement_service', return_value=mock_services['enhancement_service']):
                    with patch('src.services.factories.create_export_service', return_value=mock_services['export_service']):
                        with patch('src.services.factories.BatchProcessor') as mock_processor_class:
                            mock_processor_instance = MagicMock()
                            mock_processor_class.return_value = mock_processor_instance
                            
                            processor = create_batch_processor()
                            
                            # Verify processor was created
                            mock_processor_class.assert_called_once()
                            assert processor == mock_processor_instance

    def test_create_service_container_basic(self):
        """Test service container factory function basic functionality."""
        # Test that the function can be called without errors
        mock_services = {
            'youtube_service': MagicMock(),
            'media_service': MagicMock(),
            'transcription_service': MagicMock(),
            'enhancement_service': MagicMock(),
            'export_service': MagicMock(),
            'batch_processor': MagicMock(),
        }
        
        with patch('src.services.factories.YouTubeRepository'):
            with patch('src.services.factories.create_transcription_repository'):
                with patch('src.services.factories.create_media_repository'):
                    with patch('src.services.factories.create_youtube_service', return_value=mock_services['youtube_service']):
                        with patch('src.services.factories.create_media_service', return_value=mock_services['media_service']):
                            with patch('src.services.factories.create_transcription_service', return_value=mock_services['transcription_service']):
                                with patch('src.services.factories.create_enhancement_service', return_value=mock_services['enhancement_service']):
                                    with patch('src.services.factories.create_export_service', return_value=mock_services['export_service']):
                                        with patch('src.services.factories.create_batch_processor', return_value=mock_services['batch_processor']):
                                            services = create_service_container()
                                            
                                            # Verify all services were created
                                            assert len(services) == 6
                                            assert all(key in services for key in mock_services.keys())

    def test_create_minimal_service_container_basic(self):
        """Test minimal service container factory function basic functionality."""
        # Test that the function can be called without errors
        mock_services = {
            'youtube_service': MagicMock(),
            'media_service': MagicMock(),
            'transcription_service': MagicMock(),
        }
        
        with patch('src.services.factories.create_youtube_service', return_value=mock_services['youtube_service']):
            with patch('src.services.factories.create_media_service', return_value=mock_services['media_service']):
                with patch('src.services.factories.create_transcription_service', return_value=mock_services['transcription_service']):
                    services = create_minimal_service_container()
                    
                    # Verify only core services were created
                    assert len(services) == 3
                    assert all(key in services for key in mock_services.keys())


class TestServiceValidation:
    """Test service validation utilities."""

    def test_validate_service_container_with_valid_services(self):
        """Test service container validation with valid services."""
        # Create mock services that implement their protocols
        mock_youtube_service = MagicMock()
        mock_media_service = MagicMock()
        mock_transcription_service = MagicMock()
        
        # Mock the required methods for each service
        mock_youtube_service.extract_metadata = MagicMock()
        mock_youtube_service.batch_extract = MagicMock()
        
        mock_media_service.download_media = MagicMock()
        mock_media_service.preprocess_audio = MagicMock()
        mock_media_service.validate_file_size = MagicMock()
        mock_media_service.check_audio_quality = MagicMock()
        mock_media_service.get_media_info = MagicMock()
        mock_media_service.create_media_file_record = MagicMock()
        mock_media_service.update_media_file_status = MagicMock()
        mock_media_service.get_media_file_by_id = MagicMock()
        mock_media_service.get_pending_media_files = MagicMock()
        mock_media_service.get_ready_media_files = MagicMock()
        mock_media_service.process_media_pipeline = MagicMock()
        mock_media_service.get_telemetry_data = MagicMock()
        mock_media_service.clear_telemetry_data = MagicMock()
        
        mock_transcription_service.transcribe_file = MagicMock()
        mock_transcription_service.transcribe_audio = MagicMock()
        mock_transcription_service.create_transcription_job = MagicMock()
        mock_transcription_service.get_job_status = MagicMock()
        mock_transcription_service.cancel_job = MagicMock()
        
        services = {
            "youtube_service": mock_youtube_service,
            "media_service": mock_media_service,
            "transcription_service": mock_transcription_service,
        }
        
        # Test validation
        result = validate_service_container(services)
        assert result is True

    def test_validate_service_container_with_invalid_services(self):
        """Test service container validation with invalid services."""
        # Create mock services that don't implement their protocols
        mock_invalid_service = MagicMock()
        # Missing required methods
        
        services = {
            "youtube_service": mock_invalid_service,
        }
        
        # Test validation
        result = validate_service_container(services)
        assert result is False

    def test_get_service_dependencies(self):
        """Test getting service dependencies."""
        # Test YouTube service dependencies
        deps = get_service_dependencies("youtube_service")
        assert "repository" in deps
        assert deps["repository"] == "YouTubeRepositoryProtocol"
        
        # Test media service dependencies
        deps = get_service_dependencies("media_service")
        assert "download_service" in deps
        assert "preprocessing_service" in deps
        assert "database_service" in deps
        
        # Test unknown service
        deps = get_service_dependencies("unknown_service")
        assert deps == {}

    def test_get_service_dependencies_all_services(self):
        """Test getting dependencies for all known services."""
        services = [
            "youtube_service",
            "media_service", 
            "transcription_service",
            "enhancement_service",
            "export_service",
            "batch_processor"
        ]
        
        for service_name in services:
            deps = get_service_dependencies(service_name)
            assert isinstance(deps, dict)
            # Each service should have at least some dependencies or config
            assert len(deps) > 0


class TestFactoryIntegration:
    """Test integration between factory functions."""

    def test_factory_functions_work_together(self):
        """Test that factory functions can work together."""
        # Test that we can get dependencies for each service
        service_names = ["youtube_service", "media_service", "transcription_service"]
        
        for service_name in service_names:
            deps = get_service_dependencies(service_name)
            assert isinstance(deps, dict)


if __name__ == "__main__":
    pytest.main([__file__])
