# -*- coding: utf-8 -*-
"""
Management command to clean up inactive users.

Usage:
    python manage.py cleanup_users --days 30 --dry-run
    python manage.py cleanup_users --days 90 --delete
    python manage.py cleanup_users --unverified --days 7
"""

from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth import get_user_model
from django.utils import timezone
from django.db import transaction
from datetime import timedelta
import logging

User = get_user_model()
logger = logging.getLogger(__name__)


class Command(BaseCommand):
    help = 'Clean up inactive users'
    
    def add_arguments(self, parser):
        parser.add_argument(
            '--days',
            type=int,
            default=30,
            help='Number of days of inactivity (default: 30)'
        )
        parser.add_argument(
            '--dry-run',
            action='store_true',
            help='Show what would be deleted without actually deleting'
        )
        parser.add_argument(
            '--delete',
            action='store_true',
            help='Actually delete the users (use with caution)'
        )
        parser.add_argument(
            '--unverified',
            action='store_true',
            help='Only target unverified users'
        )
        parser.add_argument(
            '--inactive',
            action='store_true',
            help='Only target inactive users (is_active=False)'
        )
        parser.add_argument(
            '--exclude-staff',
            action='store_true',
            default=True,
            help='Exclude staff users from cleanup (default: True)'
        )
        parser.add_argument(
            '--batch-size',
            type=int,
            default=100,
            help='Number of users to process in each batch (default: 100)'
        )
    
    def handle(self, *args, **options):
        days = options['days']
        dry_run = options['dry_run']
        delete = options['delete']
        unverified_only = options['unverified']
        inactive_only = options['inactive']
        exclude_staff = options['exclude_staff']
        batch_size = options['batch_size']
        
        if not dry_run and not delete:
            raise CommandError(
                'You must specify either --dry-run or --delete'
            )
        
        if dry_run and delete:
            raise CommandError(
                'Cannot specify both --dry-run and --delete'
            )
        
        # Calculate cutoff date
        cutoff_date = timezone.now() - timedelta(days=days)
        
        self.stdout.write(
            self.style.SUCCESS(
                f'Looking for users inactive since: {cutoff_date.strftime("%Y-%m-%d %H:%M:%S")}'
            )
        )
        
        # Build query
        queryset = User.objects.filter(
            last_login__lt=cutoff_date
        )
        
        # Apply filters
        if unverified_only:
            # Assuming email verification field exists
            if hasattr(User, 'email_verified'):
                queryset = queryset.filter(email_verified=False)
            else:
                self.stdout.write(
                    self.style.WARNING(
                        'email_verified field not found, skipping unverified filter'
                    )
                )
        
        if inactive_only:
            queryset = queryset.filter(is_active=False)
        
        if exclude_staff:
            queryset = queryset.filter(is_staff=False, is_superuser=False)
        
        # Get users to process
        users_to_process = queryset.order_by('date_joined')
        total_count = users_to_process.count()
        
        if total_count == 0:
            self.stdout.write(
                self.style.SUCCESS('No users found matching the criteria.')
            )
            return
        
        self.stdout.write(
            self.style.WARNING(
                f'Found {total_count} users matching the criteria.'
            )
        )
        
        # Show sample of users
        sample_users = users_to_process[:5]
        self.stdout.write('\nSample users:')
        for user in sample_users:
            last_login = user.last_login.strftime('%Y-%m-%d') if user.last_login else 'Never'
            self.stdout.write(
                f'  - {user.email} (joined: {user.date_joined.strftime("%Y-%m-%d")}, '
                f'last login: {last_login})'
            )
        
        if total_count > 5:
            self.stdout.write(f'  ... and {total_count - 5} more users')
        
        # Dry run mode
        if dry_run:
            self.stdout.write(
                self.style.SUCCESS(
                    f'\nDRY RUN: Would delete {total_count} users.'
                )
            )
            return
        
        # Confirm deletion
        if not self._confirm_deletion(total_count):
            self.stdout.write(self.style.ERROR('Operation cancelled.'))
            return
        
        # Delete users in batches
        deleted_count = 0
        
        try:
            with transaction.atomic():
                # Process in batches
                while True:
                    batch = list(users_to_process[:batch_size])
                    if not batch:
                        break
                    
                    # Log users being deleted
                    for user in batch:
                        logger.info(
                            f'Deleting inactive user: {user.email} '
                            f'(last login: {user.last_login})'
                        )
                    
                    # Delete batch
                    batch_ids = [user.id for user in batch]
                    User.objects.filter(id__in=batch_ids).delete()
                    
                    deleted_count += len(batch)
                    
                    self.stdout.write(
                        f'Deleted batch of {len(batch)} users '
                        f'({deleted_count}/{total_count})'
                    )
                
                self.stdout.write(
                    self.style.SUCCESS(
                        f'\nSuccessfully deleted {deleted_count} inactive users.'
                    )
                )
                
        except Exception as e:
            logger.error(f'Error during user cleanup: {str(e)}')
            raise CommandError(f'Error during cleanup: {str(e)}')
    
    def _confirm_deletion(self, count):
        """Confirm deletion with user input."""
        self.stdout.write(
            self.style.WARNING(
                f'\nThis will permanently delete {count} users.'
            )
        )
        
        response = input('Are you sure you want to continue? (yes/no): ')
        return response.lower() in ['yes', 'y']