# -*- coding: utf-8 -*-
"""
Campaigns App Signals

This module contains signal handlers for campaign-related events.
"""

from django.db.models.signals import post_save, pre_save, post_delete
from django.dispatch import receiver
from django.utils import timezone
from django.core.mail import send_mail
from django.conf import settings
from django.template.loader import render_to_string

from .models import Campaign
import logging

logger = logging.getLogger(__name__)


@receiver(pre_save, sender=Campaign)
def campaign_pre_save(sender, instance, **kwargs):
    """
    Handle campaign pre-save operations.
    """
    # Track status changes
    if instance.pk:
        try:
            old_instance = Campaign.objects.get(pk=instance.pk)
            instance._old_status = old_instance.status
        except Campaign.DoesNotExist:
            instance._old_status = None
    else:
        instance._old_status = None
    
    # Auto-set dates based on status
    if instance.status == 'active' and not instance.start_date:
        instance.start_date = timezone.now().date()
    
    if instance.status == 'completed' and not instance.end_date:
        instance.end_date = timezone.now().date()


@receiver(post_save, sender=Campaign)
def campaign_post_save(sender, instance, created, **kwargs):
    """
    Handle campaign post-save operations.
    """
    if created:
        logger.info(f"New campaign created: {instance.name} (ID: {instance.pk})")
        
        # Send notification email for new campaign
        send_campaign_notification(
            instance,
            'Campaign Created',
            'emails/campaign_created.html'
        )
        
    else:
        logger.info(f"Campaign updated: {instance.name} (ID: {instance.pk})")
        
        # Check for status changes
        old_status = getattr(instance, '_old_status', None)
        if old_status and old_status != instance.status:
            handle_status_change(instance, old_status, instance.status)


@receiver(post_delete, sender=Campaign)
def campaign_post_delete(sender, instance, **kwargs):
    """
    Handle campaign deletion.
    """
    logger.info(f"Campaign deleted: {instance.name} (ID: {instance.pk})")
    
    # Send notification email for campaign deletion
    send_campaign_notification(
        instance,
        'Campaign Deleted',
        'emails/campaign_deleted.html'
    )


def handle_status_change(instance, old_status, new_status):
    """
    Handle campaign status changes.
    """
    logger.info(
        f"Campaign {instance.name} status changed from {old_status} to {new_status}"
    )
    
    # Send status change notifications
    status_messages = {
        'active': 'Campaign Activated',
        'paused': 'Campaign Paused',
        'completed': 'Campaign Completed',
        'cancelled': 'Campaign Cancelled',
    }
    
    if new_status in status_messages:
        send_campaign_notification(
            instance,
            status_messages[new_status],
            f'emails/campaign_{new_status}.html'
        )
    
    # Handle specific status transitions
    if new_status == 'active':
        handle_campaign_activation(instance)
    elif new_status == 'paused':
        handle_campaign_pause(instance)
    elif new_status == 'completed':
        handle_campaign_completion(instance)
    elif new_status == 'cancelled':
        handle_campaign_cancellation(instance)


def handle_campaign_activation(instance):
    """
    Handle campaign activation.
    """
    logger.info(f"Activating campaign: {instance.name}")
    
    # Validate campaign before activation
    if not instance.start_date:
        instance.start_date = timezone.now().date()
        instance.save(update_fields=['start_date'])
    
    # Check budget allocation
    if instance.budget <= 0:
        logger.warning(f"Campaign {instance.name} activated with zero budget")
    
    # Trigger campaign start tasks
    # This could include:
    # - Starting ad serving
    # - Initializing tracking
    # - Setting up analytics
    
    logger.info(f"Campaign {instance.name} successfully activated")


def handle_campaign_pause(instance):
    """
    Handle campaign pause.
    """
    logger.info(f"Pausing campaign: {instance.name}")
    
    # Pause all related activities
    # This could include:
    # - Stopping ad serving
    # - Pausing automated bidding
    # - Sending pause notifications
    
    logger.info(f"Campaign {instance.name} successfully paused")


def handle_campaign_completion(instance):
    """
    Handle campaign completion.
    """
    logger.info(f"Completing campaign: {instance.name}")
    
    # Set end date if not already set
    if not instance.end_date:
        instance.end_date = timezone.now().date()
        instance.save(update_fields=['end_date'])
    
    # Generate final reports
    # This could include:
    # - Performance summary
    # - Budget utilization report
    # - ROI analysis
    
    logger.info(f"Campaign {instance.name} successfully completed")


def handle_campaign_cancellation(instance):
    """
    Handle campaign cancellation.
    """
    logger.info(f"Cancelling campaign: {instance.name}")
    
    # Stop all campaign activities immediately
    # This could include:
    # - Stopping ad serving
    # - Cancelling scheduled tasks
    # - Processing refunds if applicable
    
    logger.info(f"Campaign {instance.name} successfully cancelled")


def send_campaign_notification(instance, subject, template_name):
    """
    Send email notification for campaign events.
    """
    try:
        # Get agency users for notification
        agency_users = instance.advertiser.agency.users.all()
        recipient_emails = [user.email for user in agency_users if user.email]
        
        if not recipient_emails:
            logger.warning(f"No email recipients found for campaign {instance.name}")
            return
        
        # Render email content
        context = {
            'campaign': instance,
            'advertiser': instance.advertiser,
            'agency': instance.advertiser.agency,
        }
        
        html_message = render_to_string(template_name, context)
        
        # Send email
        send_mail(
            subject=f"[Ad-tlas] {subject}: {instance.name}",
            message='',  # Plain text version
            html_message=html_message,
            from_email=settings.DEFAULT_FROM_EMAIL,
            recipient_list=recipient_emails,
            fail_silently=True
        )
        
        logger.info(f"Notification sent for campaign {instance.name}: {subject}")
        
    except Exception as e:
        logger.error(f"Failed to send notification for campaign {instance.name}: {str(e)}")


@receiver(post_save, sender=Campaign)
def update_campaign_metrics(sender, instance, created, **kwargs):
    """
    Update campaign-related metrics and analytics.
    """
    if not created:
        # Update agency-level metrics
        agency = instance.advertiser.agency
        
        # This could trigger updates to:
        # - Agency dashboard metrics
        # - Performance tracking
        # - Budget utilization calculations
        
        logger.debug(f"Updated metrics for campaign {instance.name}")


@receiver(post_save, sender=Campaign)
def schedule_campaign_tasks(sender, instance, created, **kwargs):
    """
    Schedule campaign-related tasks.
    """
    if instance.status == 'active':
        # Schedule recurring tasks for active campaigns
        # This could include:
        # - Daily performance reports
        # - Budget monitoring
        # - Automated optimizations
        
        logger.debug(f"Scheduled tasks for active campaign {instance.name}")
    
    elif instance.status in ['completed', 'cancelled']:
        # Cancel scheduled tasks for inactive campaigns
        logger.debug(f"Cancelled tasks for inactive campaign {instance.name}")