"""
Celery tasks for loan management
"""
try:
    from celery import shared_task
    CELERY_AVAILABLE = True
except ImportError:
    # Celery not installed, create a dummy decorator
    CELERY_AVAILABLE = False
    def shared_task(func):
        """Dummy decorator when celery is not available"""
        return func

from django.utils import timezone
from django.db.models import Sum
from decimal import Decimal
import logging

logger = logging.getLogger(__name__)


@shared_task
def apply_automatic_penalties():
    """
    Apply penalties to overdue loans with automatic penalty mode
    This task should be run daily via Celery Beat
    """
    from loans.models import Loan, PenaltyCharge, LoanProduct
    
    logger.info("Starting automatic penalty application")
    
    # Get all active overdue loans with automatic penalty mode
    overdue_loans = Loan.objects.filter(
        status='active',
        due_date__lt=timezone.now()
    ).select_related('application__loan_product', 'borrower')
    
    total_penalties = Decimal('0.00')
    loans_processed = 0
    loans_skipped = 0
    
    for loan in overdue_loans:
        product = loan.application.loan_product
        
        # Skip if penalty mode is manual
        if hasattr(product, 'penalty_mode') and product.penalty_mode == 'manual':
            loans_skipped += 1
            continue
        
        # Check if loan is overdue based on repayment method
        if not loan.is_overdue:
            continue
        
        # Calculate penalty
        penalty_amount = calculate_penalty_for_loan(loan)
        
        if penalty_amount > 0:
            # Check if penalty has already been applied today
            today = timezone.now().date()
            existing_penalty_today = PenaltyCharge.objects.filter(
                loan=loan,
                applied_date__date=today,
                is_automatic=True
            ).exists()
            
            if not existing_penalty_today:
                # Create penalty charge record
                PenaltyCharge.objects.create(
                    loan=loan,
                    amount=penalty_amount,
                    penalty_rate=product.get_late_payment_penalty(),
                    days_overdue=loan.days_overdue,
                    outstanding_amount=loan.outstanding_amount,
                    is_automatic=True,
                    reason=f"Automatic penalty for {loan.days_overdue} days overdue"
                )
                
                loans_processed += 1
                total_penalties += penalty_amount
                
                logger.info(
                    f"Applied penalty to loan {loan.loan_number}: "
                    f"KES {penalty_amount:,.2f} for {loan.days_overdue} days overdue"
                )
                
                # Create audit log
                try:
                    from utils.models import AuditLog
                    AuditLog.objects.create(
                        action='penalty_applied',
                        model_name='Loan',
                        object_id=str(loan.id),
                        description=f'Automatic penalty of KES {penalty_amount:,.2f} applied to loan {loan.loan_number} '
                                  f'for {loan.days_overdue} days overdue '
                                  f'(rate: {product.get_late_payment_penalty()}%)'
                    )
                except Exception as e:
                    logger.warning(f"Failed to create audit log: {e}")
    
    logger.info(
        f"Automatic penalty application completed: "
        f"{loans_processed} penalties applied, "
        f"{loans_skipped} loans skipped (manual mode), "
        f"Total: KES {total_penalties:,.2f}"
    )
    
    return {
        'loans_processed': loans_processed,
        'loans_skipped': loans_skipped,
        'total_penalties': float(total_penalties)
    }


def calculate_penalty_for_loan(loan):
    """
    Calculate penalty for a specific loan based on product settings
    """
    from decimal import Decimal
    
    product = loan.application.loan_product
    penalty_rate = Decimal(str(product.get_late_payment_penalty())) / Decimal('100')
    outstanding = loan.outstanding_amount
    
    # Get penalty frequency (default to daily if not set)
    penalty_frequency = getattr(product, 'penalty_frequency', 'daily')
    
    if penalty_frequency == 'daily':
        # Daily penalty: rate applied per day
        penalty = outstanding * penalty_rate * Decimal(str(loan.days_overdue))
    elif penalty_frequency == 'weekly':
        # Weekly penalty: rate applied per week
        weeks_overdue = max(1, loan.days_overdue // 7)
        penalty = outstanding * penalty_rate * Decimal(str(weeks_overdue))
    else:  # monthly
        # Monthly penalty: rate applied per month
        months_overdue = max(1, loan.days_overdue // 30)
        penalty = outstanding * penalty_rate * Decimal(str(months_overdue))
    
    return penalty


@shared_task
def send_penalty_notifications():
    """
    Send notifications to borrowers about applied penalties
    This task should be run after apply_automatic_penalties
    """
    from loans.models import PenaltyCharge
    from django.utils import timezone
    from datetime import timedelta
    
    logger.info("Starting penalty notification task")
    
    # Get penalties applied in the last 24 hours
    yesterday = timezone.now() - timedelta(days=1)
    recent_penalties = PenaltyCharge.objects.filter(
        applied_date__gte=yesterday,
        is_automatic=True
    ).select_related('loan__borrower')
    
    notifications_sent = 0
    
    for penalty in recent_penalties:
        try:
            # Send SMS notification via Africa's Talking
            borrower = penalty.loan.borrower
            try:
                from payments.sms_service import send_overdue_reminder_sms
                send_overdue_reminder_sms(
                    borrower_name=borrower.get_full_name(),
                    overdue_amount=float(penalty.amount),
                    loan_number=penalty.loan.loan_number,
                    customer_phone=borrower.phone_number,
                )
            except Exception as sms_exc:
                logger.warning(f"Penalty SMS failed for {penalty.loan.loan_number}: {sms_exc}")

            logger.info(f"Notification sent to {borrower.phone_number} for penalty {penalty.id}")
            notifications_sent += 1
            
        except Exception as e:
            logger.error(f"Failed to send notification for penalty {penalty.id}: {e}")
    
    logger.info(f"Penalty notifications completed: {notifications_sent} sent")
    
    return {'notifications_sent': notifications_sent}
