from django.core.management.base import BaseCommand
from django.utils import timezone
from datetime import timedelta
from customers.models import Customer
from customers.services import CustomerServiceManager, CustomerNotificationService
from billing.models import ServicePeriod


class Command(BaseCommand):
    help = 'Process customer service statuses and send notifications'

    def add_arguments(self, parser):
        parser.add_argument(
            '--dry-run',
            action='store_true',
            help='Run in dry-run mode without making changes',
        )

    def handle(self, *args, **options):
        dry_run = options['dry_run']
        now = timezone.now()

        self.stdout.write(
            self.style.SUCCESS(f'Processing service statuses at {now}')
        )

        if dry_run:
            self.stdout.write(
                self.style.WARNING('Running in DRY-RUN mode - no changes will be made')
            )

        stats = {
            'inactive_set': 0,
            'suspended': 0,
            'activated': 0,
            'reminders_sent': 0,
            'trial_processed': 0
        }

        # 1. Set customers without services to inactive
        customers_without_service = Customer.objects.filter(
            service__isnull=True
        ).exclude(service_status='inactive')

        for customer in customers_without_service:
            old_status = customer.service_status
            if not dry_run:
                customer.service_status = 'inactive'
                customer.save()
                self.stdout.write(f'Set {customer.customer_id} to inactive (no service assigned) - was {old_status}')
            else:
                self.stdout.write(f'Would set {customer.customer_id} to inactive (no service assigned) - currently {old_status}')
            stats['inactive_set'] += 1

        # 2. Process customers with active services
        customers_with_service = Customer.objects.filter(
            service__isnull=False,
            is_active=True
        ).select_related('service')

        for customer in customers_with_service:
            try:
                # Get current service periods
                active_periods = ServicePeriod.objects.filter(
                    customer=customer,
                    status='active'
                ).order_by('-service_end')

                current_period = active_periods.first()

                if not current_period:
                    # No active service period but has service assigned
                    if customer.service_status in ['active', 'trial']:
                        if not dry_run:
                            customer.service_status = 'suspended'
                            customer.save()
                            self.stdout.write(f'Suspended {customer.customer_id} (has service but no active period)')
                        else:
                            self.stdout.write(f'Would suspend {customer.customer_id} (has service but no active period)')
                        stats['suspended'] += 1
                    continue

                # Check if service period has expired
                if current_period.is_expired:
                    if customer.service_status in ['active', 'trial']:
                        if not dry_run:
                            customer.service_status = 'suspended'
                            customer.save()
                            current_period.status = 'expired'
                            current_period.save()
                            CustomerNotificationService.send_service_suspended_notification(
                                customer, "service expired"
                            )
                            self.stdout.write(f'Suspended {customer.customer_id} (service expired on {current_period.service_end})')
                        else:
                            self.stdout.write(f'Would suspend {customer.customer_id} (service expired on {current_period.service_end})')
                        stats['suspended'] += 1
                    continue

                # Check for upcoming expiry (3 days before)
                days_until_expiry = (current_period.service_end - now).days
                if days_until_expiry == 3:
                    if not dry_run:
                        CustomerNotificationService.send_service_expiry_reminder(
                            customer, days_until_expiry
                        )
                        self.stdout.write(f'Sent 3-day reminder to {customer.customer_id}')
                    stats['reminders_sent'] += 1

                # Ensure active customers with valid periods are marked as active
                if customer.service_status != 'active' and current_period.is_active:
                    if not dry_run:
                        customer.service_status = 'active'
                        customer.save()
                        self.stdout.write(f'Activated {customer.customer_id} (valid service period)')
                    stats['activated'] += 1

            except Exception as e:
                self.stdout.write(
                    self.style.ERROR(f'Error processing {customer.customer_id}: {str(e)}')
                )

        # 3. Process trial periods
        expired_trials = Customer.objects.filter(
            service_status='trial',
            trial_end_date__lte=now
        )

        for customer in expired_trials:
            if not dry_run:
                try:
                    result = CustomerServiceManager.process_trial_completion(customer)
                    if result['success']:
                        self.stdout.write(f'Processed trial for {customer.customer_id}')
                    stats['trial_processed'] += 1
                except Exception as e:
                    self.stdout.write(
                        self.style.ERROR(f'Error processing trial for {customer.customer_id}: {str(e)}')
                    )

        # 4. Final validation - check for any remaining inconsistencies
        inconsistent_customers = Customer.objects.filter(
            service__isnull=True,
            service_status='active'
        )

        if inconsistent_customers.exists():
            self.stdout.write(self.style.WARNING(f'Found {inconsistent_customers.count()} customers still marked active without services'))
            for customer in inconsistent_customers:
                if not dry_run:
                    customer.service_status = 'inactive'
                    customer.save()
                    self.stdout.write(f'Fixed: Set {customer.customer_id} to inactive')
                    stats['inactive_set'] += 1

        # Check for expired services still marked active
        expired_active_customers = []
        for customer in Customer.objects.filter(service__isnull=False, service_status='active'):
            active_periods = ServicePeriod.objects.filter(
                customer=customer,
                status='active'
            ).order_by('-service_end')

            current_period = active_periods.first()
            if current_period and current_period.is_expired:
                expired_active_customers.append((customer, current_period))

        if expired_active_customers:
            self.stdout.write(self.style.WARNING(f'Found {len(expired_active_customers)} customers with expired services still marked active'))
            for customer, period in expired_active_customers:
                if not dry_run:
                    customer.service_status = 'suspended'
                    customer.save()
                    period.status = 'expired'
                    period.save()
                    self.stdout.write(f'Fixed: Suspended {customer.customer_id} (expired {period.service_end})')
                    stats['suspended'] += 1

        # Print summary
        self.stdout.write(
            self.style.SUCCESS(
                f"\nProcessing completed:\n"
                f"- Set to inactive: {stats['inactive_set']}\n"
                f"- Suspended: {stats['suspended']}\n"
                f"- Activated: {stats['activated']}\n"
                f"- Reminders sent: {stats['reminders_sent']}\n"
                f"- Trials processed: {stats['trial_processed']}"
            )
        )