"""
Views for penalty management
"""
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.utils import timezone
from django.db import transaction
from decimal import Decimal
import logging

from loans.models import Loan, PenaltyCharge
from users.decorators import staff_required

logger = logging.getLogger(__name__)


@login_required
@staff_required
def apply_manual_penalty(request, loan_id):
    """
    Manually apply a penalty to a specific loan (AJAX endpoint)
    """
    from django.http import JsonResponse
    from datetime import date
    
    loan = get_object_or_404(Loan, id=loan_id)
    
    if request.method == 'POST':
        try:
            # Get penalty data from form
            penalty_amount = Decimal(request.POST.get('penalty_amount', '0'))
            reason = request.POST.get('reason', '').strip()
            penalty_date_str = request.POST.get('penalty_date', '').strip()
            
            # Validate amount
            if penalty_amount <= 0:
                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return JsonResponse({
                        'success': False,
                        'error': 'Penalty amount must be greater than zero'
                    }, status=400)
                messages.error(request, 'Penalty amount must be greater than zero')
                return redirect('loans:loan_detail', pk=loan_id)
            
            # Validate reason
            if not reason:
                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return JsonResponse({
                        'success': False,
                        'error': 'Please provide a reason for the penalty'
                    }, status=400)
                messages.error(request, 'Please provide a reason for the penalty')
                return redirect('loans:loan_detail', pk=loan_id)
            
            # Parse and validate penalty_date
            penalty_date = None
            if penalty_date_str:
                try:
                    penalty_date = date.fromisoformat(penalty_date_str)
                    # Validate penalty_date is not in the future
                    if penalty_date > date.today():
                        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                            return JsonResponse({
                                'success': False,
                                'error': 'Penalty date cannot be in the future'
                            }, status=400)
                        messages.error(request, 'Penalty date cannot be in the future')
                        return redirect('loans:loan_detail', pk=loan_id)
                except ValueError:
                    if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                        return JsonResponse({
                            'success': False,
                            'error': 'Invalid penalty date format. Use YYYY-MM-DD'
                        }, status=400)
                    messages.error(request, 'Invalid penalty date format')
                    return redirect('loans:loan_detail', pk=loan_id)
            else:
                # Default to today if not provided
                penalty_date = date.today()
            
            # Create penalty charge
            with transaction.atomic():
                penalty = PenaltyCharge.objects.create(
                    loan=loan,
                    amount=penalty_amount,
                    penalty_rate=loan.application.loan_product.get_late_payment_penalty(),
                    days_overdue=loan.days_overdue if loan.is_overdue else 0,
                    outstanding_amount=loan.outstanding_amount,
                    is_automatic=False,
                    applied_by=request.user,
                    reason=reason,
                    penalty_date=penalty_date
                )
                
                # Create audit log
                try:
                    from utils.models import AuditLog
                    AuditLog.objects.create(
                        action='manual_penalty_applied',
                        model_name='Loan',
                        object_id=str(loan.id),
                        user=request.user,
                        description=f'Manual penalty of KES {penalty_amount:,.2f} applied to loan {loan.loan_number} for date {penalty_date}. Reason: {reason}'
                    )
                except Exception as e:
                    logger.warning(f"Failed to create audit log: {e}")
                
                # Return JSON response for AJAX requests
                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return JsonResponse({
                        'success': True,
                        'message': f'Penalty of KES {penalty_amount:,.2f} successfully applied',
                        'penalty': {
                            'id': str(penalty.id),
                            'amount': float(penalty_amount),
                            'penalty_date': penalty_date.isoformat(),
                            'applied_date': penalty.applied_date.isoformat(),
                            'reason': reason
                        },
                        'total_penalties': float(loan.total_penalties),
                        'outstanding_amount': float(loan.outstanding_amount)
                    })
                
                messages.success(
                    request,
                    f'✓ Penalty of KES {penalty_amount:,.2f} successfully applied to loan {loan.loan_number}'
                )
                
        except ValueError:
            error_msg = 'Invalid penalty amount'
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({'success': False, 'error': error_msg}, status=400)
            messages.error(request, error_msg)
        except Exception as e:
            logger.error(f"Error applying manual penalty: {str(e)}")
            error_msg = f'Error applying penalty: {str(e)}'
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({'success': False, 'error': error_msg}, status=500)
            messages.error(request, error_msg)
    
    return redirect('loans:loan_detail', pk=loan_id)


@login_required
@staff_required
def calculate_suggested_penalty(request, loan_id):
    """
    Calculate and display suggested penalty for a loan
    """
    loan = get_object_or_404(Loan, id=loan_id)
    
    if not loan.is_overdue:
        messages.info(request, 'This loan is not overdue')
        return redirect('loans:loan_detail', pk=loan_id)
    
    # Calculate suggested penalty
    product = loan.application.loan_product
    penalty_rate = Decimal(str(product.get_late_payment_penalty())) / Decimal('100')
    outstanding = loan.outstanding_amount
    
    # Get penalty frequency
    penalty_frequency = getattr(product, 'penalty_frequency', 'daily')
    
    if penalty_frequency == 'daily':
        suggested_penalty = outstanding * penalty_rate * Decimal(str(loan.days_overdue))
        frequency_text = f"{loan.days_overdue} days"
    elif penalty_frequency == 'weekly':
        weeks_overdue = max(1, loan.days_overdue // 7)
        suggested_penalty = outstanding * penalty_rate * Decimal(str(weeks_overdue))
        frequency_text = f"{weeks_overdue} weeks"
    else:  # monthly
        months_overdue = max(1, loan.days_overdue // 30)
        suggested_penalty = outstanding * penalty_rate * Decimal(str(months_overdue))
        frequency_text = f"{months_overdue} months"
    
    context = {
        'loan': loan,
        'suggested_penalty': suggested_penalty,
        'penalty_rate': product.get_late_payment_penalty(),
        'penalty_frequency': penalty_frequency,
        'frequency_text': frequency_text,
        'outstanding_amount': outstanding,
        'days_overdue': loan.days_overdue
    }
    
    return render(request, 'loans/apply_penalty.html', context)


@login_required
@staff_required
def delete_penalty(request, penalty_id):
    """
    Delete a penalty charge (admin only)
    """
    penalty = get_object_or_404(PenaltyCharge, id=penalty_id)
    loan = penalty.loan
    
    if request.method == 'POST':
        try:
            with transaction.atomic():
                # Create audit log before deletion
                try:
                    from utils.models import AuditLog
                    AuditLog.objects.create(
                        action='penalty_deleted',
                        model_name='PenaltyCharge',
                        object_id=str(penalty.id),
                        user=request.user,
                        description=f'Penalty of KES {penalty.amount:,.2f} deleted from loan {loan.loan_number}'
                    )
                except Exception as e:
                    logger.warning(f"Failed to create audit log: {e}")
                
                penalty.delete()
                
                messages.success(
                    request,
                    f'✓ Penalty of KES {penalty.amount:,.2f} successfully removed from loan {loan.loan_number}'
                )
                
        except Exception as e:
            logger.error(f"Error deleting penalty: {str(e)}")
            messages.error(request, f'Error deleting penalty: {str(e)}')
    
    return redirect('loans:loan_detail', pk=loan.id)


@login_required
@staff_required
def penalty_history(request, loan_id):
    """
    View penalty history for a specific loan
    """
    loan = get_object_or_404(Loan, id=loan_id)
    penalties = loan.penalty_charges.all().select_related('applied_by')
    
    context = {
        'loan': loan,
        'penalties': penalties,
        'total_penalties': loan.total_penalties
    }
    
    return render(request, 'loans/penalty_history.html', context)
