
from django.utils import timezone
from django.db.models import Q
from datetime import timedelta
from decimal import Decimal


class ServicePeriodManager:
    """
    Service for managing customer service periods and billing cycles
    """
    
    @staticmethod
    def get_customer_current_service_status(customer):
        """
        Get current service status for a customer
        Returns dict with status, expires_at, and other details
        """
        from .models import ServicePeriod
        
        now = timezone.now()
        
        # Get the most recent active service period
        current_period = ServicePeriod.objects.filter(
            customer=customer,
            status='active',
            service_start__lte=now
        ).order_by('-service_start').first()
        
        if not current_period:
            return {
                'status': 'inactive',
                'message': 'No active service period',
                'expires_at': None,
                'days_remaining': 0
            }
        
        if current_period.is_expired:
            return {
                'status': 'expired',
                'message': 'Service has expired',
                'expires_at': current_period.service_end,
                'days_remaining': 0
            }
        
        return {
            'status': 'active',
            'message': 'Service is active',
            'expires_at': current_period.service_end,
            'days_remaining': current_period.days_remaining,
            'service_period': current_period
        }
    
    @staticmethod
    def create_service_period(customer, service, start_time=None, invoice=None):
        """
        Create a new service period for a customer
        """
        from .models import ServicePeriod
        
        if not start_time:
            start_time = timezone.now()
        
        # Calculate end time based on billing cycle
        if service.billing_cycle == 'monthly':
            end_time = start_time + timedelta(days=30)
        elif service.billing_cycle == 'quarterly':
            end_time = start_time + timedelta(days=90)
        else:  # annually
            end_time = start_time + timedelta(days=365)
        
        service_period = ServicePeriod.objects.create(
            customer=customer,
            service=service,
            invoice=invoice,
            service_start=start_time,
            service_end=end_time,
            status='active'
        )
        
        return service_period
    
    @staticmethod
    def renew_service_period(customer):
        """
        Attempt to renew customer's service period using account balance
        """
        from .models import ServicePeriod
        from customers.models import CustomerBalanceTransaction
        
        # Get current service period
        current_period = ServicePeriod.objects.filter(
            customer=customer,
            status='active'
        ).order_by('-service_start').first()
        
        if not current_period or not customer.service:
            return {'success': False, 'message': 'No active service or service plan'}
        
        # Check if customer has sufficient balance
        if customer.account_balance < customer.service.price:
            return {'success': False, 'message': 'Insufficient account balance'}
        
        # Calculate next period dates
        next_start, next_end = current_period.calculate_next_period_dates()
        
        # Create new service period
        new_period = ServicePeriod.objects.create(
            customer=customer,
            service=customer.service,
            service_start=next_start,
            service_end=next_end,
            status='active',
            is_auto_renewed=True,
            renewal_attempted_at=timezone.now()
        )
        
        # Deduct from account balance
        old_balance = customer.account_balance
        customer.account_balance -= customer.service.price
        customer.save()
        
        # Record transaction
        CustomerBalanceTransaction.objects.create(
            customer=customer,
            transaction_type='debit',
            amount=customer.service.price,
            description=f'Auto-renewal for service period {new_period.id}',
            reference_id=f'SP-{new_period.id}',
            balance_before=old_balance,
            balance_after=customer.account_balance
        )
        
        return {'success': True, 'service_period': new_period}


class AutoBillingService:
    """
    Service for automated billing processes
    """
    
    @staticmethod
    def run_daily_billing_tasks():
        """
        Run daily billing tasks including renewals and notifications
        """
        from customers.models import Customer
        from .models import ServicePeriod
        
        results = {
            'expired_services': {'renewed': 0, 'suspended': 0, 'failed': 0},
            'upcoming_invoices': 0
        }
        
        # Handle expired services
        expired_periods = ServicePeriod.objects.filter(
            status='active',
            service_end__lte=timezone.now()
        )
        
        for period in expired_periods:
            customer = period.customer
            
            # Attempt auto-renewal if customer has balance
            if customer.can_auto_renew:
                renewal_result = ServicePeriodManager.renew_service_period(customer)
                if renewal_result['success']:
                    results['expired_services']['renewed'] += 1
                else:
                    period.status = 'suspended'
                    period.suspended_at = timezone.now()
                    period.save()
                    results['expired_services']['suspended'] += 1
            else:
                period.status = 'suspended'
                period.suspended_at = timezone.now()
                period.save()
                results['expired_services']['suspended'] += 1
        
        return results
