"""Creative Management Asynchronous Tasks

Celery tasks for creative asset processing and management.
Handles file processing, optimization, compliance checking, and notifications.

Task Categories:
- File Processing: Upload, conversion, optimization
- Compliance: Automated compliance checking
- Performance: Analytics and reporting
- Notifications: Email and system notifications
- Cleanup: File cleanup and maintenance
- Batch Operations: Bulk processing tasks

Tasks:
- process_creative_file: Process uploaded creative files
- optimize_creative: Optimize creative assets
- check_compliance: Check creative compliance
- generate_thumbnails: Generate preview thumbnails
- extract_metadata: Extract file metadata
- send_approval_notification: Send approval notifications
- cleanup_old_versions: Clean up old file versions
- batch_process_creatives: Process multiple creatives
- update_performance_metrics: Update performance data
- generate_creative_report: Generate performance reports

Integrations:
- FFmpeg for video processing
- Pillow for image processing
- External compliance APIs
- Email services
- Cloud storage services
"""

from celery import shared_task
from django.core.mail import send_mail
from django.conf import settings
from django.utils import timezone
from django.core.files.base import ContentFile
from django.core.files.storage import default_storage
from django.template.loader import render_to_string
from django.contrib.auth import get_user_model

import os
import json
import logging
import subprocess
from datetime import datetime, timedelta
from PIL import Image, ImageOps
from io import BytesIO
import requests
import hashlib
import mimetypes

from .models import (
    Creative, CreativeVersion, CreativeAsset, CreativeApproval,
    CreativePerformance, CreativeCompliance, CreativeFormat
)
from .utils import (
    get_file_metadata, validate_creative_file,
    generate_thumbnail, optimize_image, compress_video
)

User = get_user_model()
logger = logging.getLogger(__name__)


# File Processing Tasks
@shared_task(bind=True, max_retries=3)
def process_creative_file(self, creative_id):
    """
    Process uploaded creative file.
    
    Args:
        creative_id (int): Creative instance ID
        
    Returns:
        dict: Processing results
    """
    try:
        creative = Creative.objects.get(id=creative_id)
        
        if not creative.primary_file:
            raise ValueError("No file to process")
        
        logger.info(f"Processing creative file: {creative.name} (ID: {creative_id})")
        
        # Update status
        creative.creative_status = 'processing'
        creative.save()
        
        results = {
            'creative_id': creative_id,
            'file_path': creative.primary_file.path,
            'processing_steps': []
        }
        
        # Extract metadata
        metadata_task = extract_metadata.delay(creative_id)
        results['processing_steps'].append('metadata_extraction')
        
        # Generate thumbnails
        thumbnail_task = generate_thumbnails.delay(creative_id)
        results['processing_steps'].append('thumbnail_generation')
        
        # Validate file
        validation_result = validate_creative_file(creative.primary_file.path)
        if not validation_result['is_valid']:
            creative.creative_status = 'rejected'
            creative.save()
            raise ValueError(f"File validation failed: {validation_result['errors']}")
        
        results['processing_steps'].append('file_validation')
        
        # Optimize file based on type
        if creative.creative_type == 'image':
            optimize_task = optimize_image_task.delay(creative_id)
            results['processing_steps'].append('image_optimization')
        elif creative.creative_type == 'video':
            optimize_task = optimize_video_task.delay(creative_id)
            results['processing_steps'].append('video_optimization')
        
        # Check compliance
        compliance_task = check_compliance.delay(creative_id)
        results['processing_steps'].append('compliance_check')
        
        # Update status to pending review
        creative.creative_status = 'pending_review'
        creative.save()
        
        # Send notification
        send_processing_notification.delay(
            creative_id, 
            'completed', 
            'File processing completed successfully'
        )
        
        logger.info(f"Creative file processing completed: {creative.name}")
        return results
        
    except Creative.DoesNotExist:
        logger.error(f"Creative not found: {creative_id}")
        raise
    except Exception as exc:
        logger.error(f"Error processing creative file {creative_id}: {str(exc)}")
        
        # Update creative status
        try:
            creative = Creative.objects.get(id=creative_id)
            creative.creative_status = 'draft'
            creative.save()
        except Creative.DoesNotExist:
            pass
        
        # Retry task
        if self.request.retries < self.max_retries:
            logger.info(f"Retrying creative processing: {creative_id}")
            raise self.retry(countdown=60 * (self.request.retries + 1))
        
        # Send error notification
        send_processing_notification.delay(
            creative_id, 
            'failed', 
            f'File processing failed: {str(exc)}'
        )
        
        raise


@shared_task
def extract_metadata(creative_id):
    """
    Extract metadata from creative file.
    
    Args:
        creative_id (int): Creative instance ID
        
    Returns:
        dict: Extracted metadata
    """
    try:
        creative = Creative.objects.get(id=creative_id)
        
        if not creative.primary_file:
            return {'error': 'No file to process'}
        
        logger.info(f"Extracting metadata for creative: {creative.name}")
        
        # Get file metadata
        metadata = get_file_metadata(creative.primary_file.path)
        
        # Update creative with metadata
        if 'file_size' in metadata:
            creative.file_size = metadata['file_size']
        
        if 'duration' in metadata:
            creative.duration = metadata['duration']
        
        if 'dimensions' in metadata:
            creative.dimensions = metadata['dimensions']
        
        creative.save()
        
        logger.info(f"Metadata extracted for creative: {creative.name}")
        return metadata
        
    except Creative.DoesNotExist:
        logger.error(f"Creative not found: {creative_id}")
        return {'error': 'Creative not found'}
    except Exception as exc:
        logger.error(f"Error extracting metadata for creative {creative_id}: {str(exc)}")
        return {'error': str(exc)}


@shared_task
def generate_thumbnails(creative_id):
    """
    Generate thumbnails for creative.
    
    Args:
        creative_id (int): Creative instance ID
        
    Returns:
        dict: Thumbnail generation results
    """
    try:
        creative = Creative.objects.get(id=creative_id)
        
        if not creative.primary_file:
            return {'error': 'No file to process'}
        
        logger.info(f"Generating thumbnails for creative: {creative.name}")
        
        # Generate thumbnail based on file type
        thumbnail_path = None
        
        if creative.creative_type == 'image':
            thumbnail_path = generate_image_thumbnail(creative.primary_file.path)
        elif creative.creative_type == 'video':
            thumbnail_path = generate_video_thumbnail(creative.primary_file.path)
        
        if thumbnail_path:
            # Save thumbnail to creative
            with open(thumbnail_path, 'rb') as thumb_file:
                creative.thumbnail.save(
                    f'thumb_{creative.id}.jpg',
                    ContentFile(thumb_file.read()),
                    save=True
                )
            
            # Clean up temporary file
            os.remove(thumbnail_path)
            
            logger.info(f"Thumbnail generated for creative: {creative.name}")
            return {'success': True, 'thumbnail_path': creative.thumbnail.url}
        
        return {'error': 'Could not generate thumbnail'}
        
    except Creative.DoesNotExist:
        logger.error(f"Creative not found: {creative_id}")
        return {'error': 'Creative not found'}
    except Exception as exc:
        logger.error(f"Error generating thumbnails for creative {creative_id}: {str(exc)}")
        return {'error': str(exc)}


def generate_image_thumbnail(image_path, size=(300, 300)):
    """
    Generate thumbnail for image file.
    
    Args:
        image_path (str): Path to image file
        size (tuple): Thumbnail size
        
    Returns:
        str: Path to generated thumbnail
    """
    try:
        with Image.open(image_path) as img:
            # Convert to RGB if necessary
            if img.mode in ('RGBA', 'LA', 'P'):
                img = img.convert('RGB')
            
            # Generate thumbnail
            img.thumbnail(size, Image.Resampling.LANCZOS)
            
            # Save thumbnail
            thumb_path = f"/tmp/thumb_{hashlib.md5(image_path.encode()).hexdigest()}.jpg"
            img.save(thumb_path, 'JPEG', quality=85)
            
            return thumb_path
            
    except Exception as exc:
        logger.error(f"Error generating image thumbnail: {str(exc)}")
        return None


def generate_video_thumbnail(video_path, time_offset='00:00:01'):
    """
    Generate thumbnail for video file using FFmpeg.
    
    Args:
        video_path (str): Path to video file
        time_offset (str): Time offset for thumbnail
        
    Returns:
        str: Path to generated thumbnail
    """
    try:
        thumb_path = f"/tmp/thumb_{hashlib.md5(video_path.encode()).hexdigest()}.jpg"
        
        # Use FFmpeg to extract frame
        cmd = [
            'ffmpeg',
            '-i', video_path,
            '-ss', time_offset,
            '-vframes', '1',
            '-vf', 'scale=300:300:force_original_aspect_ratio=decrease',
            '-y',  # Overwrite output file
            thumb_path
        ]
        
        result = subprocess.run(cmd, capture_output=True, text=True)
        
        if result.returncode == 0 and os.path.exists(thumb_path):
            return thumb_path
        else:
            logger.error(f"FFmpeg error: {result.stderr}")
            return None
            
    except Exception as exc:
        logger.error(f"Error generating video thumbnail: {str(exc)}")
        return None


@shared_task
def optimize_image_task(creative_id):
    """
    Optimize image creative.
    
    Args:
        creative_id (int): Creative instance ID
        
    Returns:
        dict: Optimization results
    """
    try:
        creative = Creative.objects.get(id=creative_id)
        
        if not creative.primary_file or creative.creative_type != 'image':
            return {'error': 'Invalid file for image optimization'}
        
        logger.info(f"Optimizing image creative: {creative.name}")
        
        # Optimize image
        optimized_path = optimize_image(creative.primary_file.path)
        
        if optimized_path:
            # Replace original file with optimized version
            with open(optimized_path, 'rb') as opt_file:
                creative.primary_file.save(
                    creative.primary_file.name,
                    ContentFile(opt_file.read()),
                    save=True
                )
            
            # Clean up temporary file
            os.remove(optimized_path)
            
            # Update file size
            creative.file_size = creative.primary_file.size
            creative.save()
            
            logger.info(f"Image optimization completed for creative: {creative.name}")
            return {'success': True, 'optimized': True}
        
        return {'success': True, 'optimized': False, 'message': 'No optimization needed'}
        
    except Creative.DoesNotExist:
        logger.error(f"Creative not found: {creative_id}")
        return {'error': 'Creative not found'}
    except Exception as exc:
        logger.error(f"Error optimizing image creative {creative_id}: {str(exc)}")
        return {'error': str(exc)}


@shared_task
def optimize_video_task(creative_id):
    """
    Optimize video creative.
    
    Args:
        creative_id (int): Creative instance ID
        
    Returns:
        dict: Optimization results
    """
    try:
        creative = Creative.objects.get(id=creative_id)
        
        if not creative.primary_file or creative.creative_type != 'video':
            return {'error': 'Invalid file for video optimization'}
        
        logger.info(f"Optimizing video creative: {creative.name}")
        
        # Compress video
        compressed_path = compress_video(creative.primary_file.path)
        
        if compressed_path:
            # Replace original file with compressed version
            with open(compressed_path, 'rb') as comp_file:
                creative.primary_file.save(
                    creative.primary_file.name,
                    ContentFile(comp_file.read()),
                    save=True
                )
            
            # Clean up temporary file
            os.remove(compressed_path)
            
            # Update file size
            creative.file_size = creative.primary_file.size
            creative.save()
            
            logger.info(f"Video optimization completed for creative: {creative.name}")
            return {'success': True, 'optimized': True}
        
        return {'success': True, 'optimized': False, 'message': 'No optimization needed'}
        
    except Creative.DoesNotExist:
        logger.error(f"Creative not found: {creative_id}")
        return {'error': 'Creative not found'}
    except Exception as exc:
        logger.error(f"Error optimizing video creative {creative_id}: {str(exc)}")
        return {'error': str(exc)}


# Compliance Tasks
@shared_task
def check_compliance(creative_id):
    """
    Check creative compliance.
    
    Args:
        creative_id (int): Creative instance ID
        
    Returns:
        dict: Compliance check results
    """
    try:
        creative = Creative.objects.get(id=creative_id)
        
        logger.info(f"Checking compliance for creative: {creative.name}")
        
        compliance_results = {
            'creative_id': creative_id,
            'checks': [],
            'score': 0,
            'is_compliant': True,
            'issues': []
        }
        
        # File format compliance
        format_check = check_file_format_compliance(creative)
        compliance_results['checks'].append(format_check)
        
        # Content compliance (if applicable)
        if creative.creative_type in ['image', 'video']:
            content_check = check_content_compliance(creative)
            compliance_results['checks'].append(content_check)
        
        # Technical compliance
        technical_check = check_technical_compliance(creative)
        compliance_results['checks'].append(technical_check)
        
        # Calculate overall score
        total_score = sum(check['score'] for check in compliance_results['checks'])
        max_score = len(compliance_results['checks']) * 100
        compliance_results['score'] = (total_score / max_score) * 100 if max_score > 0 else 0
        
        # Determine compliance status
        compliance_results['is_compliant'] = compliance_results['score'] >= 80
        
        # Collect all issues
        for check in compliance_results['checks']:
            compliance_results['issues'].extend(check.get('issues', []))
        
        # Update creative compliance
        creative.is_compliant = compliance_results['is_compliant']
        creative.compliance_score = compliance_results['score']
        creative.save()
        
        # Create or update compliance record
        compliance, created = CreativeCompliance.objects.get_or_create(
            creative=creative,
            defaults={
                'compliance_status': 'compliant' if compliance_results['is_compliant'] else 'non_compliant',
                'compliance_score': compliance_results['score'],
                'compliance_data': compliance_results,
                'checked_at': timezone.now()
            }
        )
        
        if not created:
            compliance.compliance_status = 'compliant' if compliance_results['is_compliant'] else 'non_compliant'
            compliance.compliance_score = compliance_results['score']
            compliance.compliance_data = compliance_results
            compliance.checked_at = timezone.now()
            compliance.save()
        
        logger.info(f"Compliance check completed for creative: {creative.name} (Score: {compliance_results['score']:.1f})")
        return compliance_results
        
    except Creative.DoesNotExist:
        logger.error(f"Creative not found: {creative_id}")
        return {'error': 'Creative not found'}
    except Exception as exc:
        logger.error(f"Error checking compliance for creative {creative_id}: {str(exc)}")
        return {'error': str(exc)}


def check_file_format_compliance(creative):
    """
    Check file format compliance.
    
    Args:
        creative (Creative): Creative instance
        
    Returns:
        dict: Format compliance results
    """
    result = {
        'check_type': 'file_format',
        'score': 100,
        'issues': []
    }
    
    try:
        if not creative.primary_file:
            result['score'] = 0
            result['issues'].append('No file uploaded')
            return result
        
        # Check file extension
        file_ext = os.path.splitext(creative.primary_file.name)[1].lower()
        
        allowed_extensions = {
            'image': ['.jpg', '.jpeg', '.png', '.gif', '.webp'],
            'video': ['.mp4', '.mov', '.avi', '.webm'],
            'audio': ['.mp3', '.wav', '.aac', '.ogg'],
            'html': ['.html', '.htm'],
            'banner': ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.html']
        }
        
        if creative.creative_type in allowed_extensions:
            if file_ext not in allowed_extensions[creative.creative_type]:
                result['score'] -= 30
                result['issues'].append(f'Invalid file extension: {file_ext}')
        
        # Check file size
        if creative.file_size and creative.file_size > 50 * 1024 * 1024:  # 50MB
            result['score'] -= 20
            result['issues'].append('File size exceeds 50MB limit')
        
        # Check dimensions for images
        if creative.creative_type == 'image' and creative.dimensions:
            width, height = map(int, creative.dimensions.split('x'))
            if width > 4096 or height > 4096:
                result['score'] -= 10
                result['issues'].append('Image dimensions exceed 4096x4096 limit')
        
        return result
        
    except Exception as exc:
        logger.error(f"Error in file format compliance check: {str(exc)}")
        result['score'] = 0
        result['issues'].append(f'Error checking file format: {str(exc)}')
        return result


def check_content_compliance(creative):
    """
    Check content compliance using external API.
    
    Args:
        creative (Creative): Creative instance
        
    Returns:
        dict: Content compliance results
    """
    result = {
        'check_type': 'content',
        'score': 100,
        'issues': []
    }
    
    try:
        # This would integrate with external content moderation API
        # For now, we'll simulate the check
        
        # Simulate API call delay
        import time
        time.sleep(1)
        
        # Simulate content analysis results
        content_score = 95  # Simulated score
        
        if content_score < 80:
            result['score'] = content_score
            result['issues'].append('Content may violate platform policies')
        
        return result
        
    except Exception as exc:
        logger.error(f"Error in content compliance check: {str(exc)}")
        result['score'] = 0
        result['issues'].append(f'Error checking content: {str(exc)}')
        return result


def check_technical_compliance(creative):
    """
    Check technical compliance.
    
    Args:
        creative (Creative): Creative instance
        
    Returns:
        dict: Technical compliance results
    """
    result = {
        'check_type': 'technical',
        'score': 100,
        'issues': []
    }
    
    try:
        # Check if file is corrupted
        if creative.primary_file:
            try:
                # Try to open and validate file
                if creative.creative_type == 'image':
                    with Image.open(creative.primary_file.path) as img:
                        img.verify()
                elif creative.creative_type == 'video':
                    # Basic video file check
                    if not os.path.exists(creative.primary_file.path):
                        raise ValueError("Video file not found")
            except Exception:
                result['score'] -= 50
                result['issues'].append('File appears to be corrupted')
        
        # Check metadata completeness
        if not creative.file_size:
            result['score'] -= 10
            result['issues'].append('Missing file size information')
        
        if creative.creative_type in ['image', 'video'] and not creative.dimensions:
            result['score'] -= 10
            result['issues'].append('Missing dimensions information')
        
        if creative.creative_type == 'video' and not creative.duration:
            result['score'] -= 10
            result['issues'].append('Missing duration information')
        
        return result
        
    except Exception as exc:
        logger.error(f"Error in technical compliance check: {str(exc)}")
        result['score'] = 0
        result['issues'].append(f'Error checking technical compliance: {str(exc)}')
        return result


# Notification Tasks
@shared_task
def send_processing_notification(creative_id, status, message):
    """
    Send processing notification.
    
    Args:
        creative_id (int): Creative instance ID
        status (str): Processing status
        message (str): Notification message
        
    Returns:
        dict: Notification results
    """
    try:
        creative = Creative.objects.get(id=creative_id)
        
        # Send email notification
        if creative.created_by and creative.created_by.email:
            subject = f'Creative Processing {status.title()}: {creative.name}'
            
            context = {
                'creative': creative,
                'status': status,
                'message': message,
                'user': creative.created_by
            }
            
            html_message = render_to_string('creatives/emails/processing_notification.html', context)
            plain_message = render_to_string('creatives/emails/processing_notification.txt', context)
            
            send_mail(
                subject=subject,
                message=plain_message,
                html_message=html_message,
                from_email=settings.DEFAULT_FROM_EMAIL,
                recipient_list=[creative.created_by.email],
                fail_silently=False
            )
            
            logger.info(f"Processing notification sent for creative: {creative.name}")
            return {'success': True, 'email_sent': True}
        
        return {'success': True, 'email_sent': False, 'message': 'No email address'}
        
    except Creative.DoesNotExist:
        logger.error(f"Creative not found: {creative_id}")
        return {'error': 'Creative not found'}
    except Exception as exc:
        logger.error(f"Error sending processing notification: {str(exc)}")
        return {'error': str(exc)}


@shared_task
def send_approval_notification(creative_id, approval_status, reviewer_id, comments=None):
    """
    Send approval notification.
    
    Args:
        creative_id (int): Creative instance ID
        approval_status (str): Approval status
        reviewer_id (int): Reviewer user ID
        comments (str): Optional comments
        
    Returns:
        dict: Notification results
    """
    try:
        creative = Creative.objects.get(id=creative_id)
        reviewer = User.objects.get(id=reviewer_id)
        
        # Send email notification to creative owner
        if creative.created_by and creative.created_by.email:
            subject = f'Creative {approval_status.title()}: {creative.name}'
            
            context = {
                'creative': creative,
                'approval_status': approval_status,
                'reviewer': reviewer,
                'comments': comments,
                'user': creative.created_by
            }
            
            html_message = render_to_string('creatives/emails/approval_notification.html', context)
            plain_message = render_to_string('creatives/emails/approval_notification.txt', context)
            
            send_mail(
                subject=subject,
                message=plain_message,
                html_message=html_message,
                from_email=settings.DEFAULT_FROM_EMAIL,
                recipient_list=[creative.created_by.email],
                fail_silently=False
            )
            
            logger.info(f"Approval notification sent for creative: {creative.name}")
            return {'success': True, 'email_sent': True}
        
        return {'success': True, 'email_sent': False, 'message': 'No email address'}
        
    except (Creative.DoesNotExist, User.DoesNotExist) as exc:
        logger.error(f"Object not found: {str(exc)}")
        return {'error': str(exc)}
    except Exception as exc:
        logger.error(f"Error sending approval notification: {str(exc)}")
        return {'error': str(exc)}


# Cleanup Tasks
@shared_task
def cleanup_old_versions(days=30):
    """
    Clean up old creative versions.
    
    Args:
        days (int): Number of days to keep versions
        
    Returns:
        dict: Cleanup results
    """
    try:
        cutoff_date = timezone.now() - timedelta(days=days)
        
        # Find old versions to delete
        old_versions = CreativeVersion.objects.filter(
            created_at__lt=cutoff_date
        ).exclude(
            creative__versions__version_number=1  # Keep first version
        )
        
        deleted_count = 0
        freed_space = 0
        
        for version in old_versions:
            if version.file:
                try:
                    file_size = version.file.size
                    version.file.delete()
                    freed_space += file_size
                except Exception as exc:
                    logger.warning(f"Error deleting version file: {str(exc)}")
            
            version.delete()
            deleted_count += 1
        
        logger.info(f"Cleaned up {deleted_count} old versions, freed {freed_space} bytes")
        return {
            'success': True,
            'deleted_count': deleted_count,
            'freed_space': freed_space
        }
        
    except Exception as exc:
        logger.error(f"Error cleaning up old versions: {str(exc)}")
        return {'error': str(exc)}


@shared_task
def cleanup_orphaned_files():
    """
    Clean up orphaned creative files.
    
    Returns:
        dict: Cleanup results
    """
    try:
        # This would scan the media directory for files not referenced in the database
        # Implementation depends on storage backend
        
        logger.info("Orphaned file cleanup completed")
        return {'success': True, 'message': 'Orphaned file cleanup completed'}
        
    except Exception as exc:
        logger.error(f"Error cleaning up orphaned files: {str(exc)}")
        return {'error': str(exc)}


# Batch Processing Tasks
@shared_task
def batch_process_creatives(creative_ids):
    """
    Process multiple creatives in batch.
    
    Args:
        creative_ids (list): List of creative IDs
        
    Returns:
        dict: Batch processing results
    """
    try:
        results = {
            'total': len(creative_ids),
            'processed': 0,
            'failed': 0,
            'errors': []
        }
        
        for creative_id in creative_ids:
            try:
                process_creative_file.delay(creative_id)
                results['processed'] += 1
            except Exception as exc:
                results['failed'] += 1
                results['errors'].append(f"Creative {creative_id}: {str(exc)}")
        
        logger.info(f"Batch processing initiated for {results['processed']} creatives")
        return results
        
    except Exception as exc:
        logger.error(f"Error in batch processing: {str(exc)}")
        return {'error': str(exc)}


# Performance Tasks
@shared_task
def update_performance_metrics(creative_id, date=None):
    """
    Update performance metrics for creative.
    
    Args:
        creative_id (int): Creative instance ID
        date (str): Date for metrics (YYYY-MM-DD)
        
    Returns:
        dict: Update results
    """
    try:
        creative = Creative.objects.get(id=creative_id)
        
        if date:
            metric_date = datetime.strptime(date, '%Y-%m-%d').date()
        else:
            metric_date = timezone.now().date()
        
        # This would integrate with analytics APIs to fetch real performance data
        # For now, we'll simulate the data
        
        performance_data = {
            'impressions': 1000,
            'clicks': 50,
            'conversions': 5,
            'spend': 100.00,
            'revenue': 250.00
        }
        
        # Update or create performance record
        performance, created = CreativePerformance.objects.update_or_create(
            creative=creative,
            date=metric_date,
            defaults=performance_data
        )
        
        # Update creative aggregate metrics
        total_performance = CreativePerformance.objects.filter(
            creative=creative
        ).aggregate(
            total_impressions=models.Sum('impressions'),
            total_clicks=models.Sum('clicks'),
            total_conversions=models.Sum('conversions')
        )
        
        creative.impressions = total_performance['total_impressions'] or 0
        creative.clicks = total_performance['total_clicks'] or 0
        creative.conversions = total_performance['total_conversions'] or 0
        creative.save()
        
        logger.info(f"Performance metrics updated for creative: {creative.name}")
        return {'success': True, 'created': created}
        
    except Creative.DoesNotExist:
        logger.error(f"Creative not found: {creative_id}")
        return {'error': 'Creative not found'}
    except Exception as exc:
        logger.error(f"Error updating performance metrics: {str(exc)}")
        return {'error': str(exc)}


@shared_task
def generate_creative_report(creative_id, report_type='performance'):
    """
    Generate creative report.
    
    Args:
        creative_id (int): Creative instance ID
        report_type (str): Type of report to generate
        
    Returns:
        dict: Report generation results
    """
    try:
        creative = Creative.objects.get(id=creative_id)
        
        logger.info(f"Generating {report_type} report for creative: {creative.name}")
        
        if report_type == 'performance':
            report_data = generate_performance_report(creative)
        elif report_type == 'compliance':
            report_data = generate_compliance_report(creative)
        else:
            raise ValueError(f"Unknown report type: {report_type}")
        
        # Save report or send via email
        # Implementation depends on requirements
        
        logger.info(f"Report generated for creative: {creative.name}")
        return {'success': True, 'report_data': report_data}
        
    except Creative.DoesNotExist:
        logger.error(f"Creative not found: {creative_id}")
        return {'error': 'Creative not found'}
    except Exception as exc:
        logger.error(f"Error generating report: {str(exc)}")
        return {'error': str(exc)}


def generate_performance_report(creative):
    """
    Generate performance report data.
    
    Args:
        creative (Creative): Creative instance
        
    Returns:
        dict: Performance report data
    """
    performance_data = creative.performance_data.all().order_by('-date')[:30]
    
    return {
        'creative_name': creative.name,
        'total_impressions': creative.impressions,
        'total_clicks': creative.clicks,
        'total_conversions': creative.conversions,
        'ctr': (creative.clicks / creative.impressions * 100) if creative.impressions else 0,
        'daily_performance': [
            {
                'date': p.date.isoformat(),
                'impressions': p.impressions,
                'clicks': p.clicks,
                'conversions': p.conversions
            }
            for p in performance_data
        ]
    }


def generate_compliance_report(creative):
    """
    Generate compliance report data.
    
    Args:
        creative (Creative): Creative instance
        
    Returns:
        dict: Compliance report data
    """
    compliance_data = creative.compliance_data.first()
    
    return {
        'creative_name': creative.name,
        'is_compliant': creative.is_compliant,
        'compliance_score': creative.compliance_score,
        'compliance_details': compliance_data.compliance_data if compliance_data else None,
        'last_checked': compliance_data.checked_at.isoformat() if compliance_data else None
    }