# -*- coding: utf-8 -*-
"""
Management command for importing channels from CSV files.
"""

import csv
import os
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.utils import timezone

from ...models import Channel, ChannelCodec, ChannelZone


class Command(BaseCommand):
    """
    Management command to import channels from CSV file.
    """
    help = 'Import channels from CSV file'
    
    def add_arguments(self, parser):
        parser.add_argument(
            'csv_file',
            type=str,
            help='Path to the CSV file containing channel data'
        )
        parser.add_argument(
            '--dry-run',
            action='store_true',
            help='Perform a dry run without actually creating channels'
        )
        parser.add_argument(
            '--update-existing',
            action='store_true',
            help='Update existing channels if they already exist'
        )
        parser.add_argument(
            '--skip-errors',
            action='store_true',
            help='Skip rows with errors and continue processing'
        )
    
    def handle(self, *args, **options):
        csv_file = options['csv_file']
        dry_run = options['dry_run']
        update_existing = options['update_existing']
        skip_errors = options['skip_errors']
        
        if not os.path.exists(csv_file):
            raise CommandError(f'CSV file "{csv_file}" does not exist.')
        
        self.stdout.write(
            self.style.SUCCESS(f'Starting import from {csv_file}')
        )
        
        if dry_run:
            self.stdout.write(
                self.style.WARNING('DRY RUN MODE - No changes will be made')
            )
        
        created_count = 0
        updated_count = 0
        error_count = 0
        errors = []
        
        try:
            with open(csv_file, 'r', encoding='utf-8') as file:
                reader = csv.DictReader(file)
                
                # Validate required columns
                required_columns = ['name', 'channel_number']
                missing_columns = [col for col in required_columns if col not in reader.fieldnames]
                
                if missing_columns:
                    raise CommandError(
                        f'Missing required columns: {", ".join(missing_columns)}'
                    )
                
                with transaction.atomic():
                    for row_num, row in enumerate(reader, start=2):
                        try:
                            result = self.process_row(row, update_existing, dry_run)
                            if result == 'created':
                                created_count += 1
                            elif result == 'updated':
                                updated_count += 1
                                
                        except Exception as e:
                            error_count += 1
                            error_msg = f'Row {row_num}: {str(e)}'
                            errors.append(error_msg)
                            
                            if skip_errors:
                                self.stdout.write(
                                    self.style.ERROR(f'Error: {error_msg} (skipped)')
                                )
                            else:
                                raise CommandError(error_msg)
                    
                    if dry_run:
                        # Rollback transaction in dry run mode
                        transaction.set_rollback(True)
        
        except Exception as e:
            raise CommandError(f'Error processing CSV file: {str(e)}')
        
        # Print summary
        self.stdout.write('\n' + '='*50)
        self.stdout.write(self.style.SUCCESS('IMPORT SUMMARY'))
        self.stdout.write('='*50)
        
        if dry_run:
            self.stdout.write(
                self.style.WARNING(f'Would create: {created_count} channels')
            )
            self.stdout.write(
                self.style.WARNING(f'Would update: {updated_count} channels')
            )
        else:
            self.stdout.write(
                self.style.SUCCESS(f'Created: {created_count} channels')
            )
            self.stdout.write(
                self.style.SUCCESS(f'Updated: {updated_count} channels')
            )
        
        if error_count > 0:
            self.stdout.write(
                self.style.ERROR(f'Errors: {error_count}')
            )
            for error in errors:
                self.stdout.write(self.style.ERROR(f'  - {error}'))
        
        self.stdout.write('='*50)
    
    def process_row(self, row, update_existing, dry_run):
        """
        Process a single row from the CSV file.
        """
        # Extract and validate required fields
        name = row.get('name', '').strip()
        channel_number = row.get('channel_number', '').strip()
        
        if not name:
            raise ValueError('Channel name is required')
        if not channel_number:
            raise ValueError('Channel number is required')
        
        # Check if channel already exists
        existing_channel = None
        try:
            existing_channel = Channel.objects.get(
                channel_number=channel_number
            )
        except Channel.DoesNotExist:
            pass
        
        if existing_channel and not update_existing:
            raise ValueError(
                f'Channel with number {channel_number} already exists. '
                'Use --update-existing to update it.'
            )
        
        # Prepare channel data
        channel_data = {
            'name': name,
            'channel_number': channel_number,
            'description': row.get('description', '').strip(),
            'category': row.get('category', 'entertainment').strip(),
            'status': row.get('status', 'active').strip(),
            'stream_url': row.get('stream_url', '').strip(),
            'language': row.get('language', 'en').strip(),
            'country': row.get('country', 'US').strip(),
            'is_hd': self.parse_boolean(row.get('is_hd', 'false')),
            'is_encrypted': self.parse_boolean(row.get('is_encrypted', 'false')),
        }
        
        # Handle codec
        codec_name = row.get('codec', '').strip()
        if codec_name:
            codec, created = ChannelCodec.objects.get_or_create(
                name=codec_name,
                defaults={
                    'codec_type': 'h264',
                    'is_active': True,
                    'description': f'Auto-created codec for {codec_name}'
                }
            )
            channel_data['codec'] = codec
        
        # Handle zones
        zone_names = row.get('zones', '').strip()
        zones = []
        if zone_names:
            for zone_name in zone_names.split(','):
                zone_name = zone_name.strip()
                if zone_name:
                    zone, created = ChannelZone.objects.get_or_create(
                        name=zone_name,
                        defaults={
                            'is_active': True,
                            'description': f'Auto-created zone for {zone_name}'
                        }
                    )
                    zones.append(zone)
        
        if dry_run:
            # In dry run mode, just validate the data
            if existing_channel:
                self.stdout.write(
                    self.style.WARNING(
                        f'Would update channel: {name} ({channel_number})'
                    )
                )
                return 'updated'
            else:
                self.stdout.write(
                    self.style.SUCCESS(
                        f'Would create channel: {name} ({channel_number})'
                    )
                )
                return 'created'
        
        # Create or update channel
        if existing_channel:
            # Update existing channel
            for key, value in channel_data.items():
                setattr(existing_channel, key, value)
            existing_channel.updated_at = timezone.now()
            existing_channel.save()
            
            # Update zones
            if zones:
                existing_channel.zones.set(zones)
            
            self.stdout.write(
                self.style.SUCCESS(
                    f'Updated channel: {name} ({channel_number})'
                )
            )
            return 'updated'
        else:
            # Create new channel
            channel = Channel.objects.create(**channel_data)
            
            # Add zones
            if zones:
                channel.zones.set(zones)
            
            self.stdout.write(
                self.style.SUCCESS(
                    f'Created channel: {name} ({channel_number})'
                )
            )
            return 'created'
    
    def parse_boolean(self, value):
        """
        Parse boolean value from string.
        """
        if isinstance(value, bool):
            return value
        
        if isinstance(value, str):
            return value.lower() in ('true', '1', 'yes', 'on')
        
        return bool(value)