"""
Functional tests for Django examples in QUICKSTART.md.

This test module validates that all Django examples from the QUICKSTART guide
work correctly and provide a good user experience.
"""

import os
import sys
from pathlib import Path
from unittest.mock import Mock, patch, MagicMock
import pytest

# Add parent directory to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent.parent))

from storm_logger.integrations.django_config import DjangoStormLoggerConfig
from storm_logger.config import LogLevel


class TestQuickStartDjangoExamples:
    """Test all Django examples from QUICKSTART.md."""
    
    # ==================== Quick Setup (30 seconds) ====================
    
    def test_basic_setup_oneliner(self):
        """Test the one-liner basic setup from QUICKSTART.md lines 23-28."""
        # From QUICKSTART.md:
        # settings.py
        from storm_logger.integrations.django_config import DjangoStormLoggerConfig
        
        # Automatically detects your environment and configures appropriately
        LOGGING = DjangoStormLoggerConfig.for_environment('auto').for_django_settings()
        
        # Verify it returns a proper Django logging config
        assert isinstance(LOGGING, dict)
        assert LOGGING['version'] == 1
        assert 'formatters' in LOGGING
        assert 'handlers' in LOGGING
        assert 'loggers' in LOGGING
    
    def test_quick_production_setup(self):
        """Test quick production setup from QUICKSTART.md lines 32-37."""
        # From QUICKSTART.md:
        # settings.py
        from storm_logger.integrations.django_config import DjangoStormLoggerConfig
        
        # Production-ready configuration with error emails
        LOGGING = DjangoStormLoggerConfig.for_production().for_django_settings()
        
        # Verify production configuration
        assert isinstance(LOGGING, dict)
        assert LOGGING['version'] == 1
        # Should have email handler for production
        assert 'mail_admins' in LOGGING['handlers']
        # Should have error level threshold
        assert LOGGING['handlers']['mail_admins']['level'] == 'ERROR'
    
    def test_quick_development_setup(self):
        """Test quick development setup from QUICKSTART.md lines 41-46."""
        # From QUICKSTART.md:
        # settings.py
        from storm_logger.integrations.django_config import DjangoStormLoggerConfig
        
        # Development configuration with debug output
        LOGGING = DjangoStormLoggerConfig.for_development().for_django_settings()
        
        # Verify development configuration
        assert isinstance(LOGGING, dict)
        assert LOGGING['version'] == 1
        # Should have console handler for development
        assert 'console' in LOGGING['handlers']
        # Should enable Django debug loggers
        assert 'django.db.backends' in LOGGING['loggers']
    
    # ==================== Environment-Based Setup ====================
    
    def test_environment_auto_detection(self):
        """Test environment auto-detection from QUICKSTART.md lines 59-65."""
        # From QUICKSTART.md:
        # settings/base.py - Base settings for all environments
        from storm_logger.integrations.django_config import DjangoStormLoggerConfig
        import os
        
        # Auto-detect environment
        environment = os.getenv('DJANGO_ENVIRONMENT', 'auto')
        LOGGING = DjangoStormLoggerConfig.for_environment(environment).for_django_settings()
        
        # Should work with auto detection
        assert isinstance(LOGGING, dict)
        assert LOGGING['version'] == 1
    
    def test_production_environment_config(self):
        """Test production environment config from QUICKSTART.md lines 69-78."""
        # From QUICKSTART.md:
        # settings/production.py
        from storm_logger.integrations.django_config import DjangoStormLoggerConfig
        
        LOGGING = DjangoStormLoggerConfig.for_production(
            enable_error_emails=True,
            error_email_threshold='ERROR',
            enable_business_metrics=True,
            track_performance_metrics=True,
        ).for_django_settings()
        
        # Verify production features
        assert 'mail_admins' in LOGGING['handlers']
        config = DjangoStormLoggerConfig.for_production(
            enable_error_emails=True,
            error_email_threshold='ERROR',
            enable_business_metrics=True,
            track_performance_metrics=True,
        )
        assert config.enable_error_emails is True
        assert config.enable_business_metrics is True
        assert config.track_performance_metrics is True
    
    def test_development_environment_config(self):
        """Test development environment config from QUICKSTART.md lines 81-88."""
        # From QUICKSTART.md:
        # settings/development.py
        from storm_logger.integrations.django_config import DjangoStormLoggerConfig
        
        LOGGING = DjangoStormLoggerConfig.for_development(
            enable_django_db_logging=True,     # See SQL queries
            enable_django_template_logging=True,  # Template debugging
        ).for_django_settings()
        
        # Verify development features
        config = DjangoStormLoggerConfig.for_development(
            enable_django_db_logging=True,
            enable_django_template_logging=True,
        )
        assert config.enable_django_db_logging is True
        assert config.enable_django_template_logging is True
        # Should have Django backend loggers
        assert 'django.db.backends' in LOGGING['loggers']
    
    def test_testing_environment_config(self):
        """Test testing environment config from QUICKSTART.md lines 91-98."""
        # From QUICKSTART.md:
        # settings/testing.py
        from storm_logger.integrations.django_config import DjangoStormLoggerConfig
        
        LOGGING = DjangoStormLoggerConfig.for_testing(
            separate_test_logs=True,           # Keep test logs separate
            test_log_level='DEBUG',            # Detailed test output
        ).for_django_settings()
        
        # Verify testing features
        config = DjangoStormLoggerConfig.for_testing(
            separate_test_logs=True,
            test_log_level='DEBUG',
        )
        assert config.separate_test_logs is True
        assert config.test_log_level == 'DEBUG'
    
    # ==================== Advanced Configuration ====================
    
    def test_complete_configuration_example(self):
        """Test complete configuration from QUICKSTART.md lines 103-143."""
        # From QUICKSTART.md:
        # settings.py
        from storm_logger.integrations.django_config import DjangoStormLoggerConfig
        from storm_logger.config import LogLevel
        
        # Create sophisticated configuration
        storm_config = DjangoStormLoggerConfig(
            # Core settings
            log_level=LogLevel.INFO,
            log_directory='/var/log/myapp',
            enable_console=True,
            console_colors=True,
            
            # Django features
            enable_django_request_logging=True,    # Log HTTP requests
            enable_django_security_logging=True,   # Security events
            enable_django_db_logging=False,        # SQL queries (dev only)
            enable_django_template_logging=False,  # Template rendering
            
            # Test configuration
            enable_test_logging=True,
            separate_test_logs=True,
            test_log_level=LogLevel.INFO,
            
            # Business intelligence
            enable_business_metrics=True,
            track_user_actions=True,
            track_performance_metrics=True,
            track_request_metrics=True,
            
            # Error handling
            enable_error_emails=True,
            error_email_threshold=LogLevel.ERROR,
            
            # Django integrations
            enable_admin_integration=True,
            django_debug_toolbar_integration=True,
        )
        
        # Apply configuration
        LOGGING = storm_config.for_django_settings()
        
        # Verify all settings were applied
        assert storm_config.log_level == LogLevel.INFO
        assert storm_config.enable_django_request_logging is True
        assert storm_config.enable_django_security_logging is True
        assert storm_config.enable_business_metrics is True
        assert storm_config.enable_error_emails is True
        assert isinstance(LOGGING, dict)
    
    # ==================== App-Specific Logging ====================
    
    def test_per_app_log_levels(self):
        """Test per-app log levels from QUICKSTART.md lines 149-173."""
        # From QUICKSTART.md:
        # settings.py
        from storm_logger.integrations.django_config import DjangoStormLoggerConfig
        from storm_logger.config import LogLevel
        
        config = DjangoStormLoggerConfig(
            # Set specific log levels for each app
            app_log_levels={
                'myapp': LogLevel.DEBUG,
                'myapp.views': LogLevel.INFO,
                'myapp.models': LogLevel.WARNING,
                'django.request': LogLevel.ERROR,
                'django.db.backends': LogLevel.INFO,
                'third_party_app': LogLevel.WARNING,
            },
            
            # Exclude noisy apps entirely
            excluded_apps=[
                'django.contrib.staticfiles',
                'django.contrib.admin',
                'debug_toolbar',
            ],
        )
        
        LOGGING = config.for_django_settings()
        
        # Verify app-specific levels
        assert 'myapp' in LOGGING['loggers']
        assert LOGGING['loggers']['myapp']['level'] == 'DEBUG'
        assert 'myapp.views' in LOGGING['loggers']
        assert LOGGING['loggers']['myapp.views']['level'] == 'INFO'
        
        # Verify excluded apps - they should still have handlers but with ERROR level
        assert 'django.contrib.staticfiles' in LOGGING['loggers']
        # Excluded apps still get handlers but are limited to ERROR level
        assert LOGGING['loggers']['django.contrib.staticfiles']['level'] == 'ERROR'
    
    def test_include_only_specific_apps(self):
        """Test include only specific apps from QUICKSTART.md lines 177-188."""
        # From QUICKSTART.md:
        config = DjangoStormLoggerConfig()
        
        # Only log from these apps (exclude everything else)
        config.include_only_apps([
            'myapp',
            'critical_app',
            'django.security',
        ])
        
        LOGGING = config.for_django_settings()
        
        # Verify included apps configuration
        included_apps = config.included_apps
        assert 'myapp' in included_apps
        assert 'critical_app' in included_apps
        assert 'django.security' in included_apps
    
    def test_dynamic_app_configuration(self):
        """Test dynamic app configuration from QUICKSTART.md lines 191-200."""
        # From QUICKSTART.md:
        # You can also add app configurations dynamically
        config = DjangoStormLoggerConfig.for_development()
        
        # Add specific app configurations
        config.add_app_config('payment_app', LogLevel.DEBUG)
        config.add_app_config('user_auth', LogLevel.INFO)
        config.exclude_app('chatty_third_party')
        
        LOGGING = config.for_django_settings()
        
        # Verify dynamic configurations
        assert 'payment_app' in config.app_log_levels
        assert config.app_log_levels['payment_app'] == LogLevel.DEBUG
        assert 'user_auth' in config.app_log_levels
        assert config.app_log_levels['user_auth'] == LogLevel.INFO
        assert 'chatty_third_party' in config.excluded_apps
    
    # ==================== Using Storm Logger in Django Code ====================
    
    @patch('storm_logger.get_logger')
    def test_basic_usage_in_views(self, mock_get_logger):
        """Test basic usage in views from QUICKSTART.md lines 206-223."""
        # Mock logger
        mock_logger = Mock()
        mock_get_logger.return_value = mock_logger
        
        # From QUICKSTART.md:
        # views.py
        from storm_logger import get_logger
        
        logger = get_logger(__name__)
        
        def my_view(request):
            logger.info("Processing request", extra={"user": request.user.username})
            
            try:
                # Your business logic here
                result = process_payment(request)
                logger.info("Payment processed successfully")
                return JsonResponse({"status": "success"})
            except Exception as e:
                logger.error("Payment processing failed", exc_info=True)
                return JsonResponse({"status": "error"}, status=500)
        
        # Simulate view execution
        request = Mock()
        request.user.username = "testuser"
        
        # Mock successful payment
        def process_payment(req):
            return {"transaction_id": "12345"}
        
        def JsonResponse(data, status=200):
            return {"data": data, "status": status}
        
        # Execute view
        response = my_view(request)
        
        # Verify logging calls
        mock_logger.info.assert_any_call("Processing request", extra={"user": "testuser"})
        mock_logger.info.assert_any_call("Payment processed successfully")
        assert response["data"]["status"] == "success"
    
    @patch('storm_logger.integrations.django.DjangoStormLogger')
    def test_django_specific_logger(self, mock_django_logger_class):
        """Test Django-specific logger from QUICKSTART.md lines 226-237."""
        # Mock logger instance
        mock_logger = Mock()
        mock_django_logger_class.return_value = mock_logger
        
        # From QUICKSTART.md:
        # models.py
        from storm_logger.integrations.django import DjangoStormLogger
        
        logger = DjangoStormLogger(__name__)
        
        class Order:
            def __init__(self, id):
                self.id = id
                
            def process(self):
                logger.info(f"Processing order {self.id}")
                logger.business_metric("orders_processed", 1)
                logger.performance_metric("order_processing_time", 0.5)
        
        # Test the model
        order = Order(12345)
        order.process()
        
        # Verify logger calls
        mock_logger.info.assert_called_with("Processing order 12345")
        mock_logger.business_metric.assert_called_with("orders_processed", 1)
        mock_logger.performance_metric.assert_called_with("order_processing_time", 0.5)
    
    @patch('storm_logger.get_logger')
    def test_business_intelligence_features(self, mock_get_logger):
        """Test business intelligence features from QUICKSTART.md lines 240-263."""
        # Mock logger with performance_tracker context manager
        mock_logger = Mock()
        mock_perf_tracker = MagicMock()
        mock_perf_tracker.__enter__ = Mock(return_value=None)
        mock_perf_tracker.__exit__ = Mock(return_value=None)
        mock_logger.performance_tracker.return_value = mock_perf_tracker
        mock_get_logger.return_value = mock_logger
        
        # From QUICKSTART.md:
        # views.py
        from storm_logger import get_logger
        
        logger = get_logger(__name__)
        
        def checkout_view(request):
            logger.info("Checkout started")
            
            # Track business metrics
            logger.business_metric("checkout_attempts", 1)
            logger.business_metric("cart_value", request.cart.total)
            
            # Track performance
            with logger.performance_tracker("checkout_process"):
                # Process checkout
                order = process_checkout(request)
            
            # Track success
            logger.business_metric("successful_checkouts", 1)
            logger.business_metric("revenue", order.total)
            
            return redirect('order_complete')
        
        # Mock dependencies
        def process_checkout(request):
            order = Mock()
            order.total = 150.00
            return order
        
        def redirect(url):
            return {"redirect": url}
        
        # Create mock request
        request = Mock()
        request.cart = Mock()
        request.cart.total = 150.00
        
        # Execute view
        response = checkout_view(request)
        
        # Verify business metrics
        mock_logger.info.assert_called_with("Checkout started")
        mock_logger.business_metric.assert_any_call("checkout_attempts", 1)
        mock_logger.business_metric.assert_any_call("cart_value", 150.00)
        mock_logger.business_metric.assert_any_call("successful_checkouts", 1)
        mock_logger.business_metric.assert_any_call("revenue", 150.00)
        mock_logger.performance_tracker.assert_called_with("checkout_process")
        assert response["redirect"] == "order_complete"
    
    # ==================== Production Best Practices ====================
    
    def test_separate_log_files_by_type(self):
        """Test separate log files from QUICKSTART.md lines 268-279."""
        # From QUICKSTART.md:
        # settings/production.py
        config = DjangoStormLoggerConfig.for_production(
            log_directory='/var/log/myapp',
            
            # Separate files for different log types
            django_log_file='django.log',
            request_log_file='requests.log',
            security_log_file='security.log',
            test_log_file='tests.log',
        )
        
        # Verify file configurations
        assert str(config.log_directory) == '/var/log/myapp'
        assert config.django_log_file == 'django.log'
        assert config.request_log_file == 'requests.log'
        assert config.security_log_file == 'security.log'
        assert config.test_log_file == 'tests.log'
    
    def test_error_email_configuration(self):
        """Test error email configuration from QUICKSTART.md lines 282-304."""
        # From QUICKSTART.md:
        # Storm Logger configuration
        config = DjangoStormLoggerConfig.for_production(
            enable_error_emails=True,
            error_email_threshold=LogLevel.ERROR,
        )
        
        # Verify email configuration
        assert config.enable_error_emails is True
        assert config.error_email_threshold == LogLevel.ERROR
        
        # The LOGGING dict should have mail_admins handler
        LOGGING = config.for_django_settings()
        assert 'mail_admins' in LOGGING['handlers']
        assert LOGGING['handlers']['mail_admins']['level'] == 'ERROR'
    
    def test_log_rotation_configuration(self):
        """Test log rotation from QUICKSTART.md lines 307-314."""
        # From QUICKSTART.md:
        # Configure log rotation in Storm Logger
        config = DjangoStormLoggerConfig(
            max_file_size=10 * 1024 * 1024,  # 10MB per file
            backup_count=5,                   # Keep 5 backup files
            compression=True,          # Compress old logs
        )
        
        # Verify rotation settings
        assert config.max_file_size == 10 * 1024 * 1024
        assert config.backup_count == 5
        assert config.compression is True
    
    def test_performance_optimization_config(self):
        """Test performance optimization from QUICKSTART.md lines 317-325."""
        # From QUICKSTART.md:
        # Disable expensive logging in production
        config = DjangoStormLoggerConfig.for_production(
            enable_django_db_logging=False,      # No SQL query logging
            enable_django_template_logging=False, # No template logging
            enable_console=False,                # No console output
            log_level=LogLevel.WARNING,          # Higher threshold
        )
        
        # Verify optimizations
        assert config.enable_django_db_logging is False
        assert config.enable_django_template_logging is False
        assert config.enable_console is False
        assert config.log_level == LogLevel.WARNING
    
    # ==================== Testing Configuration ====================
    
    def test_separate_test_logs_config(self):
        """Test separate test logs from QUICKSTART.md lines 330-341."""
        # From QUICKSTART.md:
        # settings/test.py
        config = DjangoStormLoggerConfig.for_testing(
            separate_test_logs=True,
            test_log_file='tests/test_run.log',
            test_log_level=LogLevel.DEBUG,
        )
        
        # Verify test configuration
        assert config.separate_test_logs is True
        assert config.test_log_file == 'tests/test_run.log'
        assert config.test_log_level == LogLevel.DEBUG
        
        # Optionally disable logging during tests for speed
        if os.getenv('FAST_TESTS'):
            config.enable_test_logging = False
        
        # Should handle environment-based configuration
        # (In real tests, FAST_TESTS would control this)
    
    # ==================== Troubleshooting Examples ====================
    
    def test_no_log_output_troubleshooting(self):
        """Test no log output troubleshooting from QUICKSTART.md lines 385-390."""
        # From QUICKSTART.md:
        # Check if Django logging is overriding Storm Logger
        LOGGING_CONFIG = None  # Disable Django's default logging config
        LOGGING = DjangoStormLoggerConfig().for_django_settings()
        
        # Should produce valid config even with LOGGING_CONFIG disabled
        assert isinstance(LOGGING, dict)
        assert LOGGING['version'] == 1
    
    def test_permission_error_handling(self, tmp_path):
        """Test permission error handling from QUICKSTART.md lines 393-401."""
        # From QUICKSTART.md:
        # Ensure log directory exists and is writable
        config = DjangoStormLoggerConfig(
            log_directory='/var/log/myapp',  # Must be writable by Django process
        )
        
        # Create directories before Django starts
        # In test, we'll use tmp_path to simulate
        test_dir = tmp_path / 'test_logs'
        config_test = DjangoStormLoggerConfig(
            log_directory=str(test_dir),
        )
        config_test.create_log_directories()
        
        # Verify directory was created
        assert test_dir.exists()
        assert test_dir.is_dir()
    
    def test_fine_tune_app_log_levels(self):
        """Test fine-tuning app log levels from QUICKSTART.md lines 419-429."""
        # From QUICKSTART.md:
        # Fine-tune app log levels
        config = DjangoStormLoggerConfig(
            app_log_levels={
                'django.db.backends': LogLevel.WARNING,  # Less SQL noise
                'myapp.critical': LogLevel.DEBUG,        # More detail for critical app
                'django.request': LogLevel.ERROR,        # Only errors from requests
            },
            excluded_apps=['django.contrib.staticfiles'],  # Silence static files
        )
        
        # Verify configuration
        assert config.app_log_levels['django.db.backends'] == LogLevel.WARNING
        assert config.app_log_levels['myapp.critical'] == LogLevel.DEBUG
        assert config.app_log_levels['django.request'] == LogLevel.ERROR
        assert 'django.contrib.staticfiles' in config.excluded_apps
    
    def test_log_rotation_and_archiving(self):
        """Test log rotation and archiving from QUICKSTART.md lines 432-441."""
        # From QUICKSTART.md:
        # Configure rotation and archiving
        config = DjangoStormLoggerConfig(
            max_file_size=50 * 1024 * 1024,     # 50MB files
            backup_count=10,                     # Keep 10 backups
            compression=True,             # Compress old logs
            archive_directory='/var/log/archive/myapp',  # Archive directory
        )
        
        # Verify all settings
        assert config.max_file_size == 50 * 1024 * 1024
        assert config.backup_count == 10
        assert config.compression is True
        assert str(config.archive_directory) == '/var/log/archive/myapp'


class TestDjangoCodeUsageExamples:
    """Test actual code usage examples from the Django section."""
    
    def test_import_paths(self):
        """Test import paths from QUICKSTART.md lines 1474-1477."""
        # From QUICKSTART.md:
        # Import paths
        from storm_logger import get_logger  # Get standard logger
        from storm_logger.integrations.django import DjangoStormLogger  # Django-specific
        from storm_logger.integrations.django_config import DjangoStormLoggerConfig  # Config
        
        # All imports should work
        assert get_logger is not None
        assert DjangoStormLogger is not None
        assert DjangoStormLoggerConfig is not None
    
    def test_factory_methods(self):
        """Test factory methods from QUICKSTART.md lines 1479-1484."""
        # From QUICKSTART.md:
        # Factory methods
        auto_config = DjangoStormLoggerConfig.for_environment('auto')  # Auto-detect
        dev_config = DjangoStormLoggerConfig.for_development()        # Dev settings
        staging_config = DjangoStormLoggerConfig.for_staging()        # Staging settings
        prod_config = DjangoStormLoggerConfig.for_production()        # Prod settings
        test_config = DjangoStormLoggerConfig.for_testing()           # Test settings
        
        # All factory methods should return valid configs
        assert isinstance(auto_config, DjangoStormLoggerConfig)
        assert isinstance(dev_config, DjangoStormLoggerConfig)
        assert isinstance(staging_config, DjangoStormLoggerConfig)
        assert isinstance(prod_config, DjangoStormLoggerConfig)
        assert isinstance(test_config, DjangoStormLoggerConfig)


class TestDjangoEnvironmentVariables:
    """Test environment variable handling."""
    
    @patch.dict(os.environ, {'DJANGO_ENVIRONMENT': 'production'})
    def test_django_environment_variable(self):
        """Test DJANGO_ENVIRONMENT variable from QUICKSTART.md."""
        # Should respect environment variable
        config = DjangoStormLoggerConfig.for_environment('auto')
        # In production, certain features should be enabled/disabled
        LOGGING = config.for_django_settings()
        assert 'mail_admins' in LOGGING['handlers']  # Production should have email handler
    
    @patch.dict(os.environ, {'DEBUG': 'false'})
    def test_debug_environment_variable(self):
        """Test DEBUG environment variable from QUICKSTART.md."""
        # Should respect DEBUG setting
        config = DjangoStormLoggerConfig.for_environment('auto')
        # With DEBUG=false, should be in production-like mode
        assert config.production_mode is True or config.log_level != LogLevel.DEBUG


# Run specific test categories with pytest markers
pytestmark = [pytest.mark.functional, pytest.mark.django]