from django.core.management.base import BaseCommand
from django.utils import timezone
from django.db.models import Sum
from loans.models import Loan, PenaltyCharge
from decimal import Decimal
import logging

logger = logging.getLogger(__name__)


class Command(BaseCommand):
    help = 'Apply penalties to overdue loans based on individual product penalty rates'

    def add_arguments(self, parser):
        parser.add_argument(
            '--dry-run',
            action='store_true',
            help='Show what penalties would be applied without making changes',
        )
        parser.add_argument(
            '--min-days-overdue',
            type=int,
            default=1,
            help='Minimum number of days overdue before applying penalty (default: 1)',
        )

    def handle(self, *args, **options):
        dry_run = options['dry_run']
        min_days_overdue = options['min_days_overdue']
        
        self.stdout.write(
            self.style.SUCCESS(f'Starting penalty application {"(DRY RUN)" if dry_run else ""}')
        )
        
        # Get all active overdue loans
        overdue_loans = Loan.objects.filter(
            status='active',
            due_date__lt=timezone.now()
        ).select_related('application__loan_product')
        
        total_penalties = Decimal('0.00')
        loans_processed = 0
        
        for loan in overdue_loans:
            if loan.days_overdue >= min_days_overdue:
                # Calculate penalty using the product-specific penalty rate
                penalty_amount = loan.calculate_penalty()
                
                if penalty_amount > 0:
                    loans_processed += 1
                    total_penalties += penalty_amount
                    
                    self.stdout.write(
                        f'Loan {loan.loan_number} ({loan.application.loan_product.name}): '
                        f'{loan.days_overdue} days overdue, '
                        f'penalty: KES {penalty_amount:,.2f} '
                        f'(rate: {loan.application.loan_product.get_late_payment_penalty()}% monthly)'
                    )
                    
                    if not dry_run:
                        # Check if penalty has already been applied for this period
                        # to avoid double-charging
                        today = timezone.now().date()
                        existing_penalty_today = PenaltyCharge.objects.filter(
                            loan=loan,
                            applied_date__date=today
                        ).exists()
                        
                        if not existing_penalty_today:
                            # Create penalty charge record
                            PenaltyCharge.objects.create(
                                loan=loan,
                                amount=penalty_amount,
                                penalty_rate=loan.application.loan_product.get_late_payment_penalty(),
                                days_overdue=loan.days_overdue,
                                outstanding_amount=loan.total_amount - loan.amount_paid
                            )
                            
                            # Create an audit record for the penalty
                            from utils.models import AuditLog
                            try:
                                AuditLog.objects.create(
                                    action='penalty_applied',
                                    model_name='Loan',
                                    object_id=str(loan.id),
                                    description=f'Penalty of KES {penalty_amount:,.2f} applied to loan {loan.loan_number} '
                                              f'for {loan.days_overdue} days overdue '
                                              f'(rate: {loan.application.loan_product.get_late_payment_penalty()}% daily)'
                                )
                            except Exception as e:
                                self.stdout.write(
                                    self.style.WARNING(f'Failed to create audit log: {e}')
                                )
                        else:
                            self.stdout.write(
                                f'  -> Penalty already applied today for loan {loan.loan_number}'
                            )
        
        # Summary
        self.stdout.write(
            self.style.SUCCESS(
                f'\nSummary {"(DRY RUN)" if dry_run else ""}:\n'
                f'- Total overdue loans checked: {overdue_loans.count()}\n'
                f'- Loans with penalties applied: {loans_processed}\n'
                f'- Total penalties: KES {total_penalties:,.2f}'
            )
        )
        
        if dry_run:
            self.stdout.write(
                self.style.WARNING(
                    'This was a dry run. Use without --dry-run to apply penalties.'
                )
            )
        elif loans_processed > 0:
            self.stdout.write(
                self.style.SUCCESS(
                    f'Successfully applied penalties to {loans_processed} loans.'
                )
            )