"""
Background tasks for user management and notifications.
"""

import logging
from celery import shared_task
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.conf import settings
from django.utils import timezone
from datetime import timedelta

logger = logging.getLogger(__name__)


@shared_task(bind=True, max_retries=3, default_retry_delay=60)
def send_welcome_email(self, user_id):
    """
    Send a welcome email to a newly registered user.
    
    Args:
        user_id: ID of the User
        
    Returns:
        str: Email send result
    """
    from apps.users.models import User
    
    try:
        user = User.objects.get(id=user_id)
        
        context = {
            'user': user,
            'site_url': getattr(settings, 'SITE_URL', 'https://thrillwiki.com'),
        }
        
        html_message = render_to_string('emails/welcome.html', context)
        
        send_mail(
            subject='Welcome to ThrillWiki! 🎢',
            message='',
            html_message=html_message,
            from_email=settings.DEFAULT_FROM_EMAIL,
            recipient_list=[user.email],
            fail_silently=False,
        )
        
        logger.info(f"Welcome email sent to {user.email}")
        return f"Welcome email sent to {user.email}"
        
    except User.DoesNotExist:
        logger.error(f"User {user_id} not found")
        raise
    except Exception as exc:
        logger.error(f"Error sending welcome email to user {user_id}: {str(exc)}")
        raise self.retry(exc=exc, countdown=60 * (2 ** self.request.retries))


@shared_task(bind=True, max_retries=3, default_retry_delay=60)
def send_password_reset_email(self, user_id, token, reset_url):
    """
    Send a password reset email with a secure token.
    
    Args:
        user_id: ID of the User
        token: Password reset token
        reset_url: Full URL for password reset
        
    Returns:
        str: Email send result
    """
    from apps.users.models import User
    
    try:
        user = User.objects.get(id=user_id)
        
        context = {
            'user': user,
            'reset_url': reset_url,
            'request_time': timezone.now(),
            'expiry_hours': 24,  # Configurable
            'site_url': getattr(settings, 'SITE_URL', 'https://thrillwiki.com'),
        }
        
        html_message = render_to_string('emails/password_reset.html', context)
        
        send_mail(
            subject='Reset Your ThrillWiki Password',
            message='',
            html_message=html_message,
            from_email=settings.DEFAULT_FROM_EMAIL,
            recipient_list=[user.email],
            fail_silently=False,
        )
        
        logger.info(f"Password reset email sent to {user.email}")
        return f"Password reset email sent to {user.email}"
        
    except User.DoesNotExist:
        logger.error(f"User {user_id} not found")
        raise
    except Exception as exc:
        logger.error(f"Error sending password reset email: {str(exc)}")
        raise self.retry(exc=exc, countdown=60 * (2 ** self.request.retries))


@shared_task(bind=True, max_retries=2)
def cleanup_expired_tokens(self):
    """
    Clean up expired JWT tokens and password reset tokens.
    
    This task runs daily to remove old tokens from the database.
    
    Returns:
        dict: Cleanup statistics
    """
    from rest_framework_simplejwt.token_blacklist.models import OutstandingToken
    from django.contrib.auth.tokens import default_token_generator
    
    try:
        # Clean up blacklisted JWT tokens older than 7 days
        cutoff = timezone.now() - timedelta(days=7)
        
        # Note: Actual implementation depends on token storage strategy
        # This is a placeholder for the concept
        
        logger.info("Token cleanup completed")
        
        return {
            'jwt_tokens_cleaned': 0,
            'reset_tokens_cleaned': 0,
        }
        
    except Exception as exc:
        logger.error(f"Error cleaning up tokens: {str(exc)}")
        raise self.retry(exc=exc, countdown=300)


@shared_task(bind=True, max_retries=3)
def send_account_notification(self, user_id, notification_type, context_data=None):
    """
    Send a generic account notification email.
    
    Args:
        user_id: ID of the User
        notification_type: Type of notification (e.g., 'security_alert', 'profile_update')
        context_data: Additional context data for the email
        
    Returns:
        str: Email send result
    """
    from apps.users.models import User
    
    try:
        user = User.objects.get(id=user_id)
        
        context = {
            'user': user,
            'notification_type': notification_type,
            'site_url': getattr(settings, 'SITE_URL', 'https://thrillwiki.com'),
        }
        
        if context_data:
            context.update(context_data)
        
        # For now, just log (would need specific templates for each type)
        logger.info(f"Account notification ({notification_type}) for user {user.email}")
        
        return f"Notification sent to {user.email}"
        
    except User.DoesNotExist:
        logger.error(f"User {user_id} not found")
        raise
    except Exception as exc:
        logger.error(f"Error sending account notification: {str(exc)}")
        raise self.retry(exc=exc, countdown=60 * (2 ** self.request.retries))


@shared_task(bind=True, max_retries=2)
def cleanup_inactive_users(self, days_inactive=365):
    """
    Clean up or flag users who haven't logged in for a long time.
    
    Args:
        days_inactive: Number of days of inactivity before flagging (default: 365)
        
    Returns:
        dict: Cleanup statistics
    """
    from apps.users.models import User
    
    try:
        cutoff = timezone.now() - timedelta(days=days_inactive)
        
        inactive_users = User.objects.filter(
            last_login__lt=cutoff,
            is_active=True
        )
        
        count = inactive_users.count()
        
        # For now, just log inactive users
        # In production, you might want to send reactivation emails
        # or mark accounts for deletion
        
        logger.info(f"Found {count} inactive users (last login before {cutoff})")
        
        return {
            'inactive_count': count,
            'cutoff_date': cutoff.isoformat(),
        }
        
    except Exception as exc:
        logger.error(f"Error cleaning up inactive users: {str(exc)}")
        raise self.retry(exc=exc, countdown=300)


@shared_task
def update_user_statistics():
    """
    Update user-related statistics across the database.
    
    Returns:
        dict: Updated statistics
    """
    from apps.users.models import User
    from django.db.models import Count
    from datetime import timedelta
    
    try:
        now = timezone.now()
        week_ago = now - timedelta(days=7)
        month_ago = now - timedelta(days=30)
        
        stats = {
            'total_users': User.objects.count(),
            'active_users': User.objects.filter(is_active=True).count(),
            'new_this_week': User.objects.filter(date_joined__gte=week_ago).count(),
            'new_this_month': User.objects.filter(date_joined__gte=month_ago).count(),
            'verified_users': User.objects.filter(email_verified=True).count(),
            'by_role': dict(
                User.objects.values('role__name')
                .annotate(count=Count('id'))
                .values_list('role__name', 'count')
            ),
        }
        
        logger.info(f"User statistics updated: {stats}")
        return stats
        
    except Exception as e:
        logger.error(f"Error updating user statistics: {str(e)}")
        raise


@shared_task(bind=True, max_retries=3)
def send_bulk_notification(self, user_ids, subject, message, html_message=None):
    """
    Send bulk email notifications to multiple users.
    
    This is useful for announcements, feature updates, etc.
    
    Args:
        user_ids: List of User IDs
        subject: Email subject
        message: Plain text message
        html_message: HTML version of message (optional)
        
    Returns:
        dict: Send statistics
    """
    from apps.users.models import User
    
    try:
        users = User.objects.filter(id__in=user_ids, is_active=True)
        
        sent_count = 0
        failed_count = 0
        
        for user in users:
            try:
                send_mail(
                    subject=subject,
                    message=message,
                    html_message=html_message,
                    from_email=settings.DEFAULT_FROM_EMAIL,
                    recipient_list=[user.email],
                    fail_silently=False,
                )
                sent_count += 1
            except Exception as e:
                logger.error(f"Failed to send to {user.email}: {str(e)}")
                failed_count += 1
                continue
        
        result = {
            'total': len(user_ids),
            'sent': sent_count,
            'failed': failed_count,
        }
        
        logger.info(f"Bulk notification sent: {result}")
        return result
        
    except Exception as exc:
        logger.error(f"Error sending bulk notification: {str(exc)}")
        raise self.retry(exc=exc, countdown=60 * (2 ** self.request.retries))


@shared_task(bind=True, max_retries=2)
def send_email_verification_reminder(self, user_id):
    """
    Send a reminder to users who haven't verified their email.
    
    Args:
        user_id: ID of the User
        
    Returns:
        str: Reminder result
    """
    from apps.users.models import User
    
    try:
        user = User.objects.get(id=user_id)
        
        if user.email_verified:
            logger.info(f"User {user.email} already verified, skipping reminder")
            return "User already verified"
        
        # Send verification reminder
        logger.info(f"Sending email verification reminder to {user.email}")
        
        # In production, generate new verification token and send email
        # For now, just log
        
        return f"Verification reminder sent to {user.email}"
        
    except User.DoesNotExist:
        logger.error(f"User {user_id} not found")
        raise
    except Exception as exc:
        logger.error(f"Error sending verification reminder: {str(exc)}")
        raise self.retry(exc=exc, countdown=60 * (2 ** self.request.retries))
