"""
Django Management Command for Stream Processor Setup

This command helps set up the Stream Processor application by creating
default configurations, sample data, and validating the installation.
"""

from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth.models import User
from django.conf import settings
from django.utils import timezone
from django.db import transaction
import os 


class Command(BaseCommand):
    """
    Management command to set up the Stream Processor application.
    
    This command performs initial setup tasks including:
    - Creating default configurations
    - Setting up sample notification templates
    - Validating system requirements
    - Creating sample data for testing
    """
    
    help = 'Set up the Stream Processor application with default configurations'
    
    def add_arguments(self, parser):
        """
        Add command line arguments for the setup command.
        
        Args:
            parser: ArgumentParser instance for adding arguments
        """
        parser.add_argument(
            '--create-superuser',
            action='store_true',
            help='Create a superuser account'
        )
        
        parser.add_argument(
            '--admin-username',
            type=str,
            default='admin',
            help='Username for the admin account (default: admin)'
        )
        
        parser.add_argument(
            '--admin-email',
            type=str,
            default='admin@example.com',
            help='Email for the admin account'
        )
        
        parser.add_argument(
            '--create-sample-data',
            action='store_true',
            help='Create sample channels and configurations'
        )
        
        parser.add_argument(
            '--validate-only',
            action='store_true',
            help='Only validate the installation without making changes'
        )
    
    def handle(self, *args, **options):
        """
        Main command handler.
        
        Args:
            *args: Command arguments
            **options: Command options
        """
        self.stdout.write(
            self.style.SUCCESS('🚀 Setting up Stream Processor Application...\n')
        )
        
        try:
            # Validate system requirements
            self.validate_system()
            
            if options['validate_only']:
                self.stdout.write(
                    self.style.SUCCESS('✅ Validation completed successfully!')
                )
                return
            
            # Perform setup tasks
            with transaction.atomic():
                self.create_directories()
                self.create_default_configurations()
                self.create_notification_templates()
                
                if options['create_superuser']:
                    self.create_superuser(
                        username=options['admin_username'],
                        email=options['admin_email']
                    )
                
                if options['create_sample_data']:
                    self.create_sample_data()
            
            self.stdout.write(
                self.style.SUCCESS('\n🎉 Stream Processor setup completed successfully!')
            )
            self.display_next_steps()
            
        except Exception as e:
            raise CommandError(f'Setup failed: {str(e)}')
    
    def validate_system(self):
        """
        Validate system requirements and configuration.
        
        Raises:
            CommandError: If validation fails
        """
        self.stdout.write('🔍 Validating system requirements...')
        
        # Check Django database connection
        try:
            from django.db import connection
            with connection.cursor() as cursor:
                cursor.execute("SELECT 1")
            self.stdout.write('  ✅ Database connection: OK')
        except Exception as e:
            raise CommandError(f'Database connection failed: {e}')
        
        # Check Redis connection
        try:
            import redis
            r = redis.from_url(settings.CELERY_BROKER_URL)
            r.ping()
            self.stdout.write('  ✅ Redis connection: OK')
        except Exception as e:
            self.stdout.write(
                self.style.WARNING(f'  ⚠️  Redis connection failed: {e}')
            )
        
        # Check FFmpeg availability
        try:
            import subprocess
            result = subprocess.run(['ffmpeg', '-version'], 
                                  capture_output=True, timeout=10)
            if result.returncode == 0:
                self.stdout.write('  ✅ FFmpeg: Available')
            else:
                raise Exception('FFmpeg not working')
        except Exception as e:
            self.stdout.write(
                self.style.WARNING(f'  ⚠️  FFmpeg not available: {e}')
            )
        
        # Check OpenCV availability
        try:
            import cv2
            self.stdout.write(f'  ✅ OpenCV: Version {cv2.__version__}')
        except ImportError:
            self.stdout.write(
                self.style.WARNING('  ⚠️  OpenCV not available')
            )
        
        # Check required directories
        output_dir = settings.STREAM_CONFIG['OUTPUT_DIR']
        if os.path.exists(output_dir):
            self.stdout.write(f'  ✅ Output directory: {output_dir}')
        else:
            self.stdout.write(
                self.style.WARNING(f'  ⚠️  Output directory missing: {output_dir}')
            )
    
    def create_directories(self):
        """Create necessary directories for the application."""
        self.stdout.write('📁 Creating application directories...')
        
        directories = [
            settings.STREAM_CONFIG['OUTPUT_DIR'],
            os.path.join(settings.STREAM_CONFIG['OUTPUT_DIR'], 'jingles'),
            os.path.join(settings.BASE_DIR, 'logs'),
            os.path.join(settings.BASE_DIR, 'media'),
            os.path.join(settings.BASE_DIR, 'static'),
        ]
        
        for directory in directories:
            try:
                os.makedirs(directory, exist_ok=True)
                self.stdout.write(f'  ✅ Created: {directory}')
            except Exception as e:
                self.stdout.write(
                    self.style.WARNING(f'  ⚠️  Failed to create {directory}: {e}')
                )
    
    def create_default_configurations(self):
        """Create default video and audio configurations."""
        self.stdout.write('⚙️  Creating default configurations...')
        
        from streams.models import VideoConfiguration, AudioConfiguration
        
        # Create default video configurations
        video_configs = [
            {
                'name': 'HD 720p',
                'resolution': '1280x720',
                'aspect_ratio': '16:9',
                'frame_rate': 25,
                'min_bitrate': '2000k',
                'max_bitrate': '4000k',
                'codec': 'h264',
                'preset': 'medium',
                'profile': 'main',
                'level': '3.1'
            },
            {
                'name': 'SD 480p',
                'resolution': '854x480',
                'aspect_ratio': '16:9',
                'frame_rate': 25,
                'min_bitrate': '1000k',
                'max_bitrate': '2000k',
                'codec': 'h264',
                'preset': 'fast',
                'profile': 'main',
                'level': '3.0'
            }
        ]
        
        for config_data in video_configs:
            config, created = VideoConfiguration.objects.get_or_create(
                name=config_data['name'],
                defaults=config_data
            )
            if created:
                self.stdout.write(f'  ✅ Created video config: {config.name}')
        
        # Create default audio configurations
        audio_configs = [
            {
                'name': 'Standard AAC',
                'codec': 'aac',
                'bitrate': '128k',
                'sample_rate': 48000,
                'channels': 2,
                'normalize': True
            },
            {
                'name': 'High Quality AAC',
                'codec': 'aac',
                'bitrate': '256k',
                'sample_rate': 48000,
                'channels': 2,
                'normalize': True
            }
        ]
        
        for config_data in audio_configs:
            config, created = AudioConfiguration.objects.get_or_create(
                name=config_data['name'],
                defaults=config_data
            )
            if created:
                self.stdout.write(f'  ✅ Created audio config: {config.name}')
    
    def create_notification_templates(self):
        """Create default notification templates."""
        self.stdout.write('📧 Creating notification templates...')
        
        from notifications.models import NotificationTemplate
        
        templates = [
            {
                'name': 'Jingle Detection Alert',
                'template_type': 'jingle_detected',
                'subject_template': '🎵 Jingle Detected: {jingle_name}',
                'message_template': (
                    '🎵 <b>Jingle Detected</b> 🎵\n\n'
                    '<b>Name:</b> {jingle_name}\n'
                    '<b>Channel:</b> {channel_name}\n'
                    '<b>Confidence:</b> {confidence_score:.3f}\n'
                    '<b>Time:</b> {detection_time}'
                ),
                'variables': ['jingle_name', 'channel_name', 'confidence_score', 'detection_time'],
                'channel_types': ['telegram', 'email']
            },
            {
                'name': 'Ad Break Notification',
                'template_type': 'ad_break_ended',
                'subject_template': '🚨 Ad Break Detected: {channel_name}',
                'message_template': (
                    '🚨 <b>Ad Break Detected</b> 🚨\n\n'
                    '<b>Channel:</b> {channel_name}\n'
                    '<b>Region:</b> {region}\n'
                    '<b>Duration:</b> {duration_seconds} seconds\n'
                    '<b>Start:</b> {start_time}\n'
                    '<b>End:</b> {end_time}'
                ),
                'variables': ['channel_name', 'region', 'duration_seconds', 'start_time', 'end_time'],
                'channel_types': ['telegram', 'email', 'webhook']
            },
            {
                'name': 'Stream Status Alert',
                'template_type': 'stream_error',
                'subject_template': '⚠️ Stream Error: {channel_name}',
                'message_template': (
                    '⚠️ <b>Stream Error</b> ⚠️\n\n'
                    '<b>Channel:</b> {channel_name}\n'
                    '<b>Error:</b> {error_message}\n'
                    '<b>Time:</b> {timestamp}'
                ),
                'variables': ['channel_name', 'error_message', 'timestamp'],
                'channel_types': ['telegram', 'email']
            }
        ]
        
        for template_data in templates:
            template, created = NotificationTemplate.objects.get_or_create(
                name=template_data['name'],
                defaults=template_data
            )
            if created:
                self.stdout.write(f'  ✅ Created template: {template.name}')
    
    def create_superuser(self, username, email):
        """
        Create a superuser account.
        
        Args:
            username (str): Username for the superuser
            email (str): Email for the superuser
        """
        self.stdout.write(f'👤 Creating superuser account: {username}...')
        
        if User.objects.filter(username=username).exists():
            self.stdout.write(f'  ⚠️  User {username} already exists')
            return
        
        try:
            # Use a default password - user should change it immediately
            password = 'changeme123!'
            
            user = User.objects.create_superuser(
                username=username,
                email=email,
                password=password
            )
            
            self.stdout.write(f'  ✅ Created superuser: {username}')
            self.stdout.write(
                self.style.WARNING(
                    f'  🔑 Default password: {password} (CHANGE IMMEDIATELY!)'
                )
            )
            
        except Exception as e:
            self.stdout.write(
                self.style.ERROR(f'  ❌ Failed to create superuser: {e}')
            )
    
    def create_sample_data(self):
        """Create sample data for testing."""
        self.stdout.write('🧪 Creating sample data...')
        
        from streams.models import Channel
        from notifications.models import NotificationChannel
        
        # Create sample channel
        admin_user = User.objects.filter(is_superuser=True).first()
        if not admin_user:
            self.stdout.write('  ⚠️  No admin user found, skipping sample data')
            return
        
        # Sample channel
        channel_data = {
            'name': 'Sample Stream Channel',
            'slug': 'sample-channel',
            'hls_url': 'https://example.com/stream.m3u8',
            'description': 'Sample channel for testing stream processing',
            'output_directory': settings.STREAM_CONFIG['OUTPUT_DIR'],
            'segment_duration': 6,
            'max_segments': 10,
            'retry_attempts': 3,
            'retry_interval': 30,
            'created_by': admin_user
        }
        
        channel, created = Channel.objects.get_or_create(
            slug='sample-channel',
            defaults=channel_data
        )
        if created:
            self.stdout.write(f'  ✅ Created sample channel: {channel.name}')
        
        # Sample notification channel (Telegram)
        if settings.TELEGRAM_CONFIG.get('BOT_TOKEN'):
            notification_channel_data = {
                'name': 'Default Telegram',
                'channel_type': 'telegram',
                'configuration': {
                    'bot_token': settings.TELEGRAM_CONFIG['BOT_TOKEN'],
                    'chat_id': settings.TELEGRAM_CONFIG['CHAT_ID']
                },
                'rate_limit': 30,
                'retry_attempts': 3,
                'timeout_seconds': 30,
                'created_by': admin_user
            }
            
            notification_channel, created = NotificationChannel.objects.get_or_create(
                name='Default Telegram',
                defaults=notification_channel_data
            )
            if created:
                self.stdout.write('  ✅ Created sample notification channel')
    
    def display_next_steps(self):
        """Display next steps for the user."""
        self.stdout.write('\n📋 Next Steps:')
        self.stdout.write('  1. 🔑 Change the default admin password if created')
        self.stdout.write('  2. ⚙️  Review configuration in the admin panel')
        self.stdout.write('  3. 🎵 Upload jingle templates for detection')
        self.stdout.write('  4. 📧 Configure notification channels')
        self.stdout.write('  5. 🎥 Create and start your first stream channel')
        self.stdout.write('')
        self.stdout.write('📚 Access Points:')
        self.stdout.write('  • Admin Panel: http://localhost:8000/admin/')
        self.stdout.write('  • API Docs: http://localhost:8000/api/v1/')
        self.stdout.write('  • Dashboard: http://localhost:8000/')
        self.stdout.write('')
        self.stdout.write('🔧 Management Commands:')
        self.stdout.write('  • python manage.py setup_stream_processor --help')
        self.stdout.write('  • python manage.py migrate')
        self.stdout.write('  • python manage.py collectstatic')
        self.stdout.write('')
        self.stdout.write('📖 Documentation: See README.md for detailed instructions')
