import json
from django.core.serializers.json import DjangoJSONEncoder
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.db.models import Sum, Count, Q, F, Avg
from datetime import datetime, timedelta
from decimal import Decimal, DecimalException
from .models import (
    LoanProduct, LoanApplication, Loan, Repayment, 
    RolloverRequest, MpesaTransaction
)
from users.models import CustomUser
from reports.models import LoanScoring
from utils.models import AuditLog, SystemSetting, Notification
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.http import JsonResponse, HttpResponse
from django.db import models
import math
import os


@login_required
def dashboard(request):
    """Main dashboard view with statistics and charts"""
    # Get current date
    today = datetime.now().date()
    
    # Calculate date ranges
    six_months_ago = today - timedelta(days=180)
    one_year_ago = today - timedelta(days=365)
    
    # Convert dates to naive datetimes
    start_of_today = datetime.combine(today, datetime.min.time())
    start_of_six_months = datetime.combine(six_months_ago, datetime.min.time())
    start_of_year = datetime.combine(one_year_ago, datetime.min.time())

    # Use naive datetime queries
    total_users = CustomUser.objects.filter(role='borrower').count()
    active_users = CustomUser.objects.filter(role='borrower', is_active=True).count()
    dormant_users = CustomUser.objects.filter(role='borrower', last_login__lt=start_of_six_months).count()
    blacklisted_users = CustomUser.objects.filter(role='borrower', status='blacklisted').count()

    # Loan statistics with naive datetime queries
    total_loans = Loan.objects.count()
    active_loans = Loan.objects.filter(status='active').count()
    paid_loans = Loan.objects.filter(status='paid').count()
    defaulted_loans = Loan.objects.filter(status='defaulted').count()

    # Applications with naive datetime queries
    pending_applications = LoanApplication.objects.filter(status='pending').count()
    approved_applications = LoanApplication.objects.filter(status='approved').count()
    rejected_applications = LoanApplication.objects.filter(status='rejected').count()

    # Financial metrics with naive datetime queries
    total_disbursed = Loan.objects.aggregate(total=Sum('principal_amount'))['total'] or 0
    total_collected = Repayment.objects.aggregate(total=Sum('amount'))['total'] or 0
    outstanding_amount = total_disbursed - total_collected

    # Monthly metrics with naive datetime queries
    monthly_disbursements = Loan.objects.filter(
        created_at__gte=start_of_year
    ).aggregate(total=Sum('principal_amount'))['total'] or 0

    monthly_collections = Repayment.objects.filter(
        payment_date__gte=start_of_year
    ).aggregate(total=Sum('amount'))['total'] or 0

    # Calculate rates and changes with naive datetime queries
    total_loans_count = Loan.objects.count()
    defaulted_loans_count = Loan.objects.filter(status='defaulted').count()
    defaulted_rate = (defaulted_loans_count / total_loans_count * 100) if total_loans_count > 0 else 0

    # Previous month comparisons with naive datetime queries
    prev_month_start = start_of_year - timedelta(days=30)
    prev_active_loans = Loan.objects.filter(status='active', created_at__lt=start_of_year).count()
    prev_active_users = CustomUser.objects.filter(role='borrower', is_active=True, date_joined__lt=start_of_year).count()
    prev_pending_applications = LoanApplication.objects.filter(status='pending', submitted_at__lt=start_of_year).count()
    prev_defaulted_loans = Loan.objects.filter(status='defaulted', created_at__lt=start_of_year).count()
    prev_total_loans = Loan.objects.filter(created_at__lt=start_of_year).count()
    prev_default_rate = (prev_defaulted_loans / prev_total_loans * 100) if prev_total_loans > 0 else 0

    # Calculate changes
    active_loans_change = ((active_loans - prev_active_loans) / prev_active_loans * 100) if prev_active_loans > 0 else 0
    active_users_change = ((active_users - prev_active_users) / prev_active_users * 100) if prev_active_users > 0 else 0
    pending_applications_change = ((pending_applications - prev_pending_applications) / prev_pending_applications * 100) if prev_pending_applications > 0 else 0
    default_rate_change = defaulted_rate - prev_default_rate

    # Recent activity with naive datetime queries
    recent_activity = AuditLog.objects.select_related('user').order_by('-created_at')[:10]

    # Monthly data for charts with naive datetime queries
    monthly_data = []
    for i in range(6):
        month_start = datetime.now().replace(day=1) - timedelta(days=30*i)
        month_start = datetime.combine(month_start.date(), datetime.min.time())
        month_end = (month_start + timedelta(days=32)).replace(day=1)
        
        disbursed = Loan.objects.filter(
            created_at__gte=month_start,
            created_at__lt=month_end
        ).aggregate(total=Sum('principal_amount'))['total'] or 0
        
        repaid = Repayment.objects.filter(
            payment_date__gte=month_start,
            payment_date__lt=month_end
        ).aggregate(total=Sum('amount'))['total'] or 0
        
        monthly_data.append({
            'month': month_start.strftime('%B %Y'),
            'disbursed': str(disbursed),
            'repaid': str(repaid)
        })

    # Distribution data
    loan_statuses = Loan.objects.values('status').annotate(count=Count('id'))
    distribution_data = {
        'labels': [status['status'].title() for status in loan_statuses],
        'data': [str(status['count']) for status in loan_statuses],
        'colors': ['#3C9EBD', '#0A3D62', '#2ECC71', '#E74C3C']
    }

    # Client growth data with naive datetime queries
    client_growth = []
    for i in range(6):
        month_start = datetime.now().replace(day=1) - timedelta(days=30*i)
        month_start = datetime.combine(month_start.date(), datetime.min.time())
        month_end = (month_start + timedelta(days=32)).replace(day=1)
        
        new_clients = CustomUser.objects.filter(
            role='borrower',
            date_joined__gte=month_start,
            date_joined__lt=month_end
        ).count()
        
        client_growth.append({
            'month': month_start.strftime('%B %Y'),
            'new_clients': str(new_clients)
        })

    # Prepare dashboard data
    dashboard_data = {
        'monthlyData': monthly_data,
        'distributionData': distribution_data,
        'clientGrowth': client_growth
    }

    context = {
        'total_users': total_users,
        'active_users': active_users,
        'dormant_users': dormant_users,
        'blacklisted_users': blacklisted_users,
        'total_loans': total_loans,
        'active_loans': active_loans,
        'paid_loans': paid_loans,
        'defaulted_loans': defaulted_loans,
        'pending_applications': pending_applications,
        'approved_applications': approved_applications,
        'rejected_applications': rejected_applications,
        'total_disbursed': total_disbursed,
        'total_collected': total_collected,
        'outstanding_amount': outstanding_amount,
        'monthly_disbursements': monthly_disbursements,
        'monthly_collections': monthly_collections,
        'default_rate': round(defaulted_rate, 2),
        'recent_activity': recent_activity,
        'active_loans_change': round(active_loans_change, 2),
        'active_users_change': round(active_users_change, 2),
        'pending_applications_change': round(pending_applications_change, 2),
        'default_rate_change': round(default_rate_change, 2),
        'dashboard_data': dashboard_data,
    }
    
    return render(request, 'loans/dashboard.html', context)


@login_required
def loan_products(request):
    """List all loan products"""
    products = LoanProduct.objects.filter(is_active=True)
    return render(request, 'loans/loan_products.html', {'products': products})


@login_required
def loan_product_detail(request, pk):
    """Detail view for a loan product"""
    product = get_object_or_404(LoanProduct, pk=pk)
    return render(request, 'loans/loan_product_detail.html', {'product': product})


@login_required
def loan_applications(request):
    """List all loan applications"""
    # Get filter parameters
    status = request.GET.get('status')
    product = request.GET.get('product')
    client = request.GET.get('client')
    date_from = request.GET.get('date_from')
    date_to = request.GET.get('date_to')
    
    # Base queryset
    applications = LoanApplication.objects.select_related(
        'borrower', 'loan_product', 'reviewed_by'
    ).order_by('-submitted_at')
    
    # Apply filters
    if status:
        applications = applications.filter(status=status)
    if product:
        applications = applications.filter(loan_product__product_type=product)
    if client:
        applications = applications.filter(borrower__id=client)
    if date_from:
        applications = applications.filter(submitted_at__date__gte=date_from)
    if date_to:
        applications = applications.filter(submitted_at__date__lte=date_to)
    
    # Get filter options
    loan_products = LoanProduct.objects.filter(is_active=True)
    clients = CustomUser.objects.filter(role='borrower', status='active')
    
    context = {
        'applications': applications,
        'loan_products': loan_products,
        'clients': clients,
        'statuses': LoanApplication.STATUS_CHOICES,
        'filters': {
            'status': status,
            'product': product,
            'client': client,
            'date_from': date_from,
            'date_to': date_to
        }
    }
    return render(request, 'loans/applications.html', context)


@login_required
def new_application(request):
    """Create a new loan application"""
    try:
        # Get client if specified
        client_id = request.GET.get('client_id')
        client = None
        if client_id:
            client = get_object_or_404(CustomUser, pk=client_id, role='borrower')
        
        # Get all active loan products (prioritize Boost, Mwamba, Imara)
        loan_products = LoanProduct.objects.filter(is_active=True).order_by(
            models.Case(
                models.When(product_type='boost', then=models.Value(1)),
                models.When(product_type='mwamba', then=models.Value(2)),
                models.When(product_type='imara', then=models.Value(3)),
                default=models.Value(4)
            ),
            'name'
        )
        
        if request.method == 'POST':
            try:
                # Get form data with detailed validation
                client_id = request.POST.get('client_id')
                if not client_id:
                    return JsonResponse({'status': 'error', 'message': 'Please select a client'}, status=400)

                loan_product_id = request.POST.get('loan_product')
                if not loan_product_id:
                    return JsonResponse({'status': 'error', 'message': 'Please select a loan product'}, status=400)

                try:
                    requested_amount = Decimal(request.POST.get('amount', '0'))
                except (TypeError, ValueError, DecimalException):
                    return JsonResponse({'status': 'error', 'message': 'Please enter a valid loan amount'}, status=400)

                try:
                    requested_duration = int(request.POST.get('duration', '0'))
                except (TypeError, ValueError):
                    return JsonResponse({'status': 'error', 'message': 'Please enter a valid duration'}, status=400)

                purpose = request.POST.get('purpose')
                if not purpose:
                    return JsonResponse({'status': 'error', 'message': 'Please enter the loan purpose'}, status=400)

                repayment_method = request.POST.get('repayment_method')
                if not repayment_method:
                    return JsonResponse({'status': 'error', 'message': 'Please select a repayment method'}, status=400)

                # Get loan product and client
                loan_product = get_object_or_404(LoanProduct, pk=loan_product_id)
                client = get_object_or_404(CustomUser, pk=client_id, role='borrower')
                
                # Validate amount, duration, and repayment method
                try:
                    loan_product.validate_amount(requested_amount)
                except ValueError as e:
                    return JsonResponse({'status': 'error', 'message': str(e)}, status=400)

                try:
                    loan_product.validate_duration(requested_duration)
                except ValueError as e:
                    return JsonResponse({'status': 'error', 'message': str(e)}, status=400)

                try:
                    loan_product.validate_repayment_method(repayment_method)
                except ValueError as e:
                    return JsonResponse({'status': 'error', 'message': str(e)}, status=400)
                
                # Calculate amounts
                months = Decimal(str(math.ceil(requested_duration / 30)))  # Convert days to months
                interest_amount = loan_product.calculate_interest(requested_amount, months)
                processing_fee_amount = loan_product.calculate_processing_fee(requested_amount)
                total_amount = requested_amount + interest_amount + processing_fee_amount
                
                # Create loan application
                application = LoanApplication.objects.create(
                    borrower=client,
                    loan_product=loan_product,
                    requested_amount=requested_amount,
                    requested_duration=requested_duration,
                    purpose=purpose,
                    repayment_method=repayment_method,
                    interest_amount=interest_amount,
                    processing_fee_amount=processing_fee_amount,
                    total_amount=total_amount
                )
                
                # Auto-calculate credit score
                try:
                    credit_score = LoanScoring.objects.get(user=client)
                    application.credit_score = credit_score.total_score
                    
                    # Auto-approve if credit score is high enough and amount is within limit
                    auto_approval_min_score = SystemSetting.get_int('auto_approval_min_score', 80)
                    auto_approval_max_amount = Decimal(str(SystemSetting.get_float('auto_approval_max_amount', float(loan_product.get_max_amount()) * 0.5)))
                    
                    if credit_score.total_score >= auto_approval_min_score and requested_amount <= auto_approval_max_amount:
                        application.auto_approved = True
                        application.status = 'approved'
                        application.reviewed_by = None
                        application.reviewed_at = datetime.now()
                        application.approval_notes = 'Auto-approved based on credit score'
                        
                        # Create loan record
                        loan = Loan.objects.create(
                            application=application,
                            borrower=client,
                            principal_amount=requested_amount,
                            interest_amount=interest_amount,
                            processing_fee=processing_fee_amount,
                            total_amount=total_amount,
                                            disbursement_date=datetime.now(),
                due_date=datetime.now() + timedelta(days=requested_duration),
                            duration_days=requested_duration,
                            status='active'  # Set initial status as active
                        )
                        
                        # Generate a unique loan number
                        loan.loan_number = f"LOAN-{str(loan.id).split('-')[0][:6].upper()}"
                        loan.save()
                        
                        messages.success(request, f'{loan_product.name} loan has been recorded and auto-approved!')
                    else:
                        messages.success(request, f'{loan_product.name} loan has been recorded and is under review.')
                except LoanScoring.DoesNotExist:
                    messages.success(request, f'{loan_product.name} loan has been recorded and is under review.')
                
                application.save()
                
                # Create audit log
                AuditLog.objects.create(
                    user=request.user,
                    action='create',
                    model_name='LoanApplication',
                    object_id=str(application.id),
                    description=f'Added {loan_product.name} loan for {client.get_full_name()}'
                )
                
                # Create notification for admins
                if not application.auto_approved and SystemSetting.get_bool('email_notifications', True):
                    Notification.objects.create(
                        title=f'New {loan_product.name} Loan',
                        message=f'A new {loan_product.name} loan has been recorded for {client.get_full_name()}',
                        priority='medium'
                    )
                
                return JsonResponse({'status': 'success', 'message': 'Loan application submitted successfully'})
                
            except Exception as e:
                import traceback
                print("Error in loan application:", str(e))
                print(traceback.format_exc())
                return JsonResponse({
                    'status': 'error',
                    'message': str(e) if str(e) else 'An error occurred while processing your application'
                }, status=500)
        
        # Get all active borrowers
        clients = CustomUser.objects.filter(
            role='borrower',
            status='active'
        ).select_related().order_by('first_name', 'last_name')
        
        # Convert loan products to dict with current settings
        loan_products_data = [product.to_dict() for product in loan_products]
        
        context = {
            'loan_products': loan_products,
            'loan_products_json': json.dumps(loan_products_data, cls=DjangoJSONEncoder),
            'clients': clients,
            'selected_client': client
        }
        return render(request, 'loans/new_application.html', context)
        
    except Exception as e:
        import traceback
        print("Error in loan application view:", str(e))
        print(traceback.format_exc())
        return JsonResponse({
            'status': 'error',
            'message': str(e) if str(e) else 'An unexpected error occurred'
        }, status=500)


@login_required
def application_detail(request, pk):
    """Detail view for a loan application"""
    application = get_object_or_404(LoanApplication, pk=pk)
    return render(request, 'loans/application_detail.html', {'application': application})


@login_required
def approve_application(request, pk):
    """Approve a loan application"""
    application = get_object_or_404(LoanApplication, pk=pk)
    
    # Get loan statistics
    defaulted_loans = application.borrower.loans.filter(status='defaulted').count()
    paid_loans = application.borrower.loans.filter(status='paid').count()
    
    if request.method == 'POST':
        # Approve application and create loan
        loan = application.approve(request.user, request.POST.get('notes', ''))
        
        # Create audit log
        AuditLog.objects.create(
            user=request.user,
            action='create',
            model_name='Loan',
            object_id=str(loan.id),
            description=f'Created loan {loan.loan_number} for {loan.borrower.get_full_name()}'
        )
        
        messages.success(request, 'Application approved and loan created successfully.')
        return redirect('loans:loans')  # Redirect to loans page
    
    return render(request, 'loans/approve_application.html', {
        'application': application,
        'defaulted_loans': defaulted_loans,
        'paid_loans': paid_loans
    })


@login_required
def reject_application(request, pk):
    """Reject a loan application"""
    application = get_object_or_404(LoanApplication, pk=pk)
    if request.method == 'POST':
        application.reject(request.user, request.POST.get('notes', ''))
        messages.success(request, 'Application rejected.')
        return redirect('loans:application_detail', pk=pk)
    
    return render(request, 'loans/reject_application.html', {'application': application})


@login_required
def loans(request):
    """View for managing all loans with filtering, pagination, and reporting"""
    # Get all loan applications with related data
    loans_list = LoanApplication.objects.all().select_related(
        'borrower',
        'loan_product',
        'loan'
    ).prefetch_related(
        'loan__repayments'
    ).order_by('-submitted_at')
    
    # Apply filters
    status = request.GET.get('status')
    product_type = request.GET.get('product_type')
    search = request.GET.get('search')
    date_from = request.GET.get('date_from')
    date_to = request.GET.get('date_to')
    
    if status:
        if status in ['active', 'paid', 'defaulted', 'rolled_over', 'written_off']:
            loans_list = loans_list.filter(loan__status=status)
        elif status in ['pending', 'under_review', 'approved', 'rejected']:
            loans_list = loans_list.filter(status=status)
    
    if product_type:
        loans_list = loans_list.filter(loan_product__product_type=product_type)
    
    if search:
        loans_list = loans_list.filter(
            Q(application_number__icontains=search) |
            Q(loan__loan_number__icontains=search) |
            Q(borrower__first_name__icontains=search) |
            Q(borrower__last_name__icontains=search) |
            Q(borrower__email__icontains=search) |
            Q(borrower__phone_number__icontains=search) |
            Q(borrower__business_name__icontains=search)
        )

    if date_from:
        try:
            date_from = datetime.strptime(date_from, '%Y-%m-%d')
            loans_list = loans_list.filter(
                Q(submitted_at__date__gte=date_from) |
                Q(loan__disbursement_date__date__gte=date_from)
            )
        except ValueError:
            pass

    if date_to:
        try:
            date_to = datetime.strptime(date_to, '%Y-%m-%d')
            loans_list = loans_list.filter(
                Q(submitted_at__date__lte=date_to) |
                Q(loan__disbursement_date__date__lte=date_to)
            )
        except ValueError:
            pass
    
    # Get summary statistics
    loans_with_loan = loans_list.filter(loan__isnull=False)
    total_loans = loans_with_loan.count()
    active_loans = loans_with_loan.filter(loan__status='active').count()
    total_disbursed = loans_with_loan.aggregate(
        total=Sum('loan__principal_amount')
    )['total'] or 0
    total_collected = Repayment.objects.filter(
        loan__application__in=loans_with_loan
    ).aggregate(total=Sum('amount'))['total'] or 0
    
    # Advanced statistics
    advanced_stats = {
        'overdue_loans': loans_with_loan.filter(
            loan__status='active',
            loan__due_date__lt=datetime.now()
        ).count(),
        'default_rate': (
            loans_with_loan.filter(loan__status='defaulted').count() / 
            total_loans * 100
        ) if total_loans > 0 else 0,
        'avg_loan_amount': loans_with_loan.aggregate(
            avg=Avg('loan__principal_amount')
        )['avg'] or 0,
        'loans_by_product': loans_with_loan.values(
            'loan_product__product_type',
            'loan_product__name'
        ).annotate(
            count=Count('id'),
            total_amount=Sum('loan__principal_amount')
        ).order_by('loan_product__product_type'),
        'loans_by_status': loans_with_loan.values(
            'loan__status'
        ).annotate(
            count=Count('id'),
            total_amount=Sum('loan__principal_amount')
        ).order_by('loan__status'),
        'client_summary': loans_with_loan.values(
            'borrower__first_name',
            'borrower__last_name'
        ).annotate(
            total_loans=Count('id'),
            total_amount=Sum('loan__principal_amount'),
            active_loans=Count('loan', filter=Q(loan__status='active'))
        ).order_by('-total_loans')[:5]
    }
    
    # Handle report generation
    if request.GET.get('generate_report') == 'true':
        from .reports import generate_loan_statistics, generate_enhanced_charts, generate_enhanced_pdf_report
        
        # Get filter parameters for report
        product_type = request.GET.get('product_type')
        loan_product = None
        if product_type:
            loan_product = LoanProduct.objects.filter(product_type=product_type).first()
        
        borrower_id = request.GET.get('borrower')
        borrower = None
        if borrower_id:
            borrower = CustomUser.objects.filter(id=borrower_id).first()
        
        # Generate statistics and charts
        stats = generate_loan_statistics(
            start_date=date_from,
            end_date=date_to,
            borrower=borrower,
            loan_product=loan_product
        )
        charts = generate_enhanced_charts(stats)
        
        # Generate PDF
        pdf = generate_enhanced_pdf_report(stats, charts, report_type='general')
        
        # Return PDF response
        filename = "loan_report"
        if borrower:
            filename = f"loans_{borrower.get_full_name()}"
        if loan_product:
            filename += f"_{loan_product.name}"
        if date_from:
            filename += f"_from_{date_from}"
        if date_to:
            filename += f"_to_{date_to}"
        
        response = HttpResponse(pdf, content_type='application/pdf')
        response['Content-Disposition'] = f'attachment; filename="{filename}.pdf"'
        return response
    
    # Pagination
    paginator = Paginator(loans_list, 10)
    page = request.GET.get('page')
    try:
        loans = paginator.page(page)
    except PageNotAnInteger:
        loans = paginator.page(1)
    except EmptyPage:
        loans = paginator.page(paginator.num_pages)
    
    context = {
        'loans': loans,
        'total_loans': total_loans,
        'active_loans': active_loans,
        'total_disbursed': total_disbursed,
        'total_collected': total_collected,
        'advanced_stats': advanced_stats,
        'selected_status': status,
        'selected_product_type': product_type,
        'search_query': search,
        'date_from': date_from,
        'date_to': date_to,
        'loan_statuses': [
            ('pending', 'Pending'),
            ('under_review', 'Under Review'),
            ('approved', 'Approved'),
            ('rejected', 'Rejected'),
            ('active', 'Active'),
            ('paid', 'Paid'),
            ('defaulted', 'Defaulted'),
            ('written_off', 'Written Off'),
            ('rolled_over', 'Rolled Over')
        ],
        'product_types': [
            ('personal', 'Personal Loan'),
            ('business', 'Business Advance'),
            ('salary', 'Salary Loan'),
            ('emergency', 'Emergency Loan'),
            ('asset', 'Asset Finance')
        ]
    }
    
    return render(request, 'loans/loans.html', context)


@login_required
def loan_detail(request, pk):
    """Detailed view of a loan with all related information and report generation"""
    loan = get_object_or_404(Loan.objects.select_related(
        'borrower',
        'application',
        'application__loan_product'
    ), pk=pk)
    
    # Get all repayments
    repayments = Repayment.objects.filter(loan=loan).order_by('-payment_date')
    
    # Get rollover requests
    rollovers = RolloverRequest.objects.filter(loan=loan).order_by('-requested_at')
    
    # Calculate loan statistics
    total_paid = repayments.aggregate(total=Sum('amount'))['total'] or 0
    remaining_amount = loan.total_amount - total_paid
    payment_progress = (total_paid / loan.total_amount * 100) if loan.total_amount > 0 else 0
    
    # Calculate late payments
    late_payments = repayments.filter(
        payment_date__gt=loan.due_date
    ).count()
    
    # Get payment schedule
    payment_schedule = []
    if loan.disbursement_date:
        current_date = loan.disbursement_date
        remaining = loan.total_amount
        installment = loan.total_amount / loan.duration_days if loan.duration_days > 0 else 0
        
        for i in range(loan.duration_days):
            due_date = current_date + timedelta(days=30)
            actual_payment = repayments.filter(
                payment_date__gte=current_date,
                payment_date__lt=due_date
            ).aggregate(total=Sum('amount'))['total'] or 0
            
            payment_schedule.append({
                'due_date': due_date,
                'expected_amount': installment,
                'actual_amount': actual_payment,
                'status': 'paid' if actual_payment >= installment else 'pending',
                'difference': actual_payment - installment
            })
            
            remaining -= actual_payment
            current_date = due_date
    
    context = {
        'loan': loan,
        'repayments': repayments,
        'rollovers': rollovers,
        'total_paid': total_paid,
        'remaining_amount': remaining_amount,
        'payment_progress': payment_progress,
        'payment_schedule': payment_schedule,
        'is_overdue': loan.is_overdue,
        'days_overdue': loan.days_overdue if loan.is_overdue else 0,
        'late_payments': late_payments,
    }
    
    # Handle report generation
    if request.GET.get('generate_report') == 'true':
        from .reports import generate_loan_statistics, generate_enhanced_charts, generate_enhanced_pdf_report
        
        # Generate statistics and charts
        stats = generate_loan_statistics(borrower=loan.borrower, loan_product=loan.application.loan_product)
        charts = generate_enhanced_charts(stats)
        
        # Generate PDF
        pdf = generate_enhanced_pdf_report(stats, charts, report_type='borrower', borrower=loan.borrower)
        
        # Return PDF response
        response = HttpResponse(pdf, content_type='application/pdf')
        response['Content-Disposition'] = f'attachment; filename="loan_{loan.loan_number}_report.pdf"'
        return response
    
    return render(request, 'loans/loan_detail.html', context)


@login_required
def disburse_loan(request, pk):
    """Disburse a loan"""
    loan = get_object_or_404(Loan, pk=pk)
    if request.method == 'POST':
        # Handle disbursement logic
        messages.success(request, 'Loan disbursed successfully.')
        return redirect('loans:loan_detail', pk=pk)
    
    return render(request, 'loans/disburse_loan.html', {'loan': loan})


@login_required
def repayments(request):
    """List all repayments"""
    repayments = Repayment.objects.select_related('loan', 'borrower').order_by('-payment_date')
    return render(request, 'loans/repayments.html', {'repayments': repayments})


@login_required
def new_repayment(request):
    """Create a new repayment"""
    if request.method == 'POST':
        # Handle form submission
        messages.success(request, 'Repayment recorded successfully.')
        return redirect('loans:repayments')
    
    loans = Loan.objects.filter(status='active')
    return render(request, 'loans/new_repayment.html', {'loans': loans})


@login_required
def repayment_detail(request, pk):
    """Detail view for a repayment"""
    repayment = get_object_or_404(Repayment, pk=pk)
    return render(request, 'loans/repayment_detail.html', {'repayment': repayment})


@login_required
def rollovers(request):
    """List all rollover requests"""
    rollovers = RolloverRequest.objects.select_related('loan', 'borrower').order_by('-requested_at')
    return render(request, 'loans/rollovers.html', {'rollovers': rollovers})


@login_required
def approve_rollover(request, pk):
    """Approve a rollover request"""
    rollover = get_object_or_404(RolloverRequest, pk=pk)
    
    if request.method == 'POST':
        notes = request.POST.get('notes', '')
        
        # Process rollover approval
        new_loan = rollover.approve(
            approved_by=request.user,
            notes=notes
        )
        
        messages.success(request, 'Rollover request approved successfully')
        return redirect('loans:loan_detail', pk=new_loan.pk)
    
    return redirect('loans:loan_detail', pk=rollover.loan.pk)


@login_required
def reject_rollover(request, pk):
    """Reject a rollover request"""
    rollover = get_object_or_404(RolloverRequest, pk=pk)
    
    if request.method == 'POST':
        notes = request.POST.get('notes', '')
        
        # Process rollover rejection
        rollover.reject(
            rejected_by=request.user,
            notes=notes
        )
        
        messages.success(request, 'Rollover request rejected')
        return redirect('loans:loan_detail', pk=rollover.loan.pk)
    
    return redirect('loans:loan_detail', pk=rollover.loan.pk)


@login_required
def mpesa_transactions(request):
    """List all M-Pesa transactions"""
    transactions = MpesaTransaction.objects.order_by('-created_at')
    return render(request, 'loans/mpesa_transactions.html', {'transactions': transactions})


@login_required
def mpesa_detail(request, pk):
    """Detail view for an M-Pesa transaction"""
    transaction = get_object_or_404(MpesaTransaction, pk=pk)
    return render(request, 'loans/mpesa_detail.html', {'transaction': transaction})

@login_required
def record_repayment(request, pk):
    """Record a new repayment for a loan"""
    loan = get_object_or_404(Loan, pk=pk)
    
    if request.method == 'POST':
        try:
            amount = Decimal(request.POST.get('amount'))
            payment_method = request.POST.get('payment_method')
            
            if amount <= 0:
                raise ValueError("Amount must be greater than 0")
            
            # Create repayment record
            # Create repayment record
            repayment = Repayment.objects.create(
                loan=loan,
                amount=amount,
                payment_method=payment_method,
                payment_date=datetime.now()
            )
            
            # Create audit log
            AuditLog.objects.create(
                user=request.user,
                action='payment',
                model_name='Repayment',
                object_id=str(repayment.id),
                description=f'Recorded payment of KES {amount:,.2f} for loan {loan.loan_number}'
            )
            
            # If M-Pesa, create transaction record
            if payment_method == 'mpesa':
                phone_number = request.POST.get('mpesa_phone')
                MpesaTransaction.objects.create(
                    repayment=repayment,
                    phone_number=phone_number,
                    amount=amount,
                    status='completed'
                )
            
            # Update loan status if fully paid
            loan.amount_paid = loan.repayment_set.aggregate(
                total=Sum('amount')
            )['total'] or 0
            
            if loan.amount_paid >= loan.total_amount:
                loan.status = 'paid'
            loan.save()
            
            messages.success(request, 'Payment recorded successfully', extra_tags='loan_detail')
            return redirect('loans:loan_detail', pk=pk)
            
        except (ValueError, DecimalException) as e:
            messages.error(request, str(e), extra_tags='loan_detail')
            return redirect('loans:loan_detail', pk=pk)
    
    return redirect('loans:loan_detail', pk=pk)

@login_required
def request_rollover(request, pk):
    """Request a loan rollover"""
    loan = get_object_or_404(Loan, pk=pk)
    
    if request.method == 'POST':
        try:
            requested_duration = int(request.POST.get('requested_duration'))
            reason = request.POST.get('reason')
            
            if requested_duration <= 0:
                raise ValueError("Duration must be greater than 0 days")
            
            # Create rollover request
            RolloverRequest.objects.create(
                loan=loan,
                requested_duration=requested_duration,
                reason=reason,
                borrower=request.user
            )
            
            messages.success(request, 'Rollover request submitted successfully', extra_tags='loan_detail')
            return redirect('loans:loan_detail', pk=pk)
            
        except ValueError as e:
            messages.error(request, str(e), extra_tags='loan_detail')
            return redirect('loans:loan_detail', pk=pk)
    
    return redirect('loans:loan_detail', pk=pk)

@login_required
def add_existing_loan(request):
    """Add an existing loan to the system, with client search on GET"""
    from users.models import CustomUser
    if request.method == 'POST':
        try:
            # Get form data
            client = get_object_or_404(CustomUser, pk=request.POST.get('client'), role='borrower')
            loan_number = request.POST.get('loan_number')
            amount = Decimal(request.POST.get('amount'))
            disbursement_date = request.POST.get('disbursement_date')
            due_date = request.POST.get('due_date')
            status = request.POST.get('status')
            # Create loan application
            application = LoanApplication.objects.create(
                borrower=client,
                loan_product=LoanProduct.objects.first(),  # Use default product for existing loans
                requested_amount=amount,
                status='approved',
                reviewed_by=request.user,
                reviewed_at=datetime.now(),
                approval_notes='Added as existing loan'
            )
            # Create loan record
            loan = Loan.objects.create(
                application=application,
                borrower=client,
                loan_number=loan_number,
                principal_amount=amount,
                total_amount=amount,  # For existing loans, use principal as total
                disbursement_date=disbursement_date,
                due_date=due_date,
                status=status,
                created_by=request.user
            )
            # Create audit log
            AuditLog.objects.create(
                user=request.user,
                action='create',
                model_name='Loan',
                object_id=str(loan.id),
                description=f'Added existing loan for {client.get_full_name()}'
            )
            messages.success(request, 'Existing loan added successfully!', extra_tags='loan_detail')
            return redirect('loans:loan_detail', pk=loan.pk)
        except Exception as e:
            messages.error(request, f'Error adding loan: {str(e)}', extra_tags='loans')
    # GET: Render form with client search
    borrowers = CustomUser.objects.filter(role='borrower', is_active=True)
    return render(request, 'loans/add_existing_loan.html', {'borrowers': borrowers})

@login_required
def api_loan_data(request):
    """API endpoint for loan data"""
    period = request.GET.get('period', '6m')
    today = datetime.now().date()
    
    if period == '1y':
        start_date = today - timedelta(days=365)
    elif period == 'all':
        start_date = today - timedelta(days=730)  # 2 years
    else:  # 6m default
        start_date = today - timedelta(days=180)
        
    # Convert to naive datetime
    start_datetime = datetime.combine(start_date, datetime.min.time())
    
    # Get monthly data
    monthly_data = []
    for i in range(6):
        month_start = datetime.now().replace(day=1) - timedelta(days=30*i)
        month_start = datetime.combine(month_start.date(), datetime.min.time())
        month_end = (month_start + timedelta(days=32)).replace(day=1)
        
        disbursed = Loan.objects.filter(
            created_at__gte=month_start,
            created_at__lt=month_end
        ).aggregate(total=Sum('principal_amount'))['total'] or 0
        
        repaid = Repayment.objects.filter(
            payment_date__gte=month_start,
            payment_date__lt=month_end
        ).aggregate(total=Sum('amount'))['total'] or 0
        
        monthly_data.append({
            'month': month_start.strftime('%B %Y'),
            'disbursed': str(disbursed),
            'repaid': str(repaid)
        })
    
    return JsonResponse({
        'labels': [data['month'] for data in monthly_data],
        'disbursements': [data['disbursed'] for data in monthly_data],
        'repayments': [data['repaid'] for data in monthly_data]
    })

@login_required
def loans_ajax(request):
    """AJAX endpoint for loans list with filters"""
    try:
        # Get filter parameters
        search = request.GET.get('search', '').strip()
        status_filter = request.GET.get('status', '')
        product_type_filter = request.GET.get('product_type', '')
        date_from = request.GET.get('date_from', '')
        date_to = request.GET.get('date_to', '')
        
        # Start with all loans and applications
        loans = Loan.objects.select_related('borrower', 'loan_product').all()
        applications = LoanApplication.objects.select_related('borrower', 'loan_product').all()
        
        # Apply search filter
        if search:
            loans = loans.filter(
                Q(loan_number__icontains=search) |
                Q(borrower__first_name__icontains=search) |
                Q(borrower__last_name__icontains=search) |
                Q(borrower__business_name__icontains=search) |
                Q(borrower__phone_number__icontains=search)
            )
            applications = applications.filter(
                Q(application_number__icontains=search) |
                Q(borrower__first_name__icontains=search) |
                Q(borrower__last_name__icontains=search) |
                Q(borrower__business_name__icontains=search) |
                Q(borrower__phone_number__icontains=search)
            )
        
        # Apply status filter
        if status_filter:
            loans = loans.filter(status=status_filter)
            applications = applications.filter(status=status_filter)
        
        # Apply product type filter
        if product_type_filter:
            loans = loans.filter(loan_product__product_type=product_type_filter)
            applications = applications.filter(loan_product__product_type=product_type_filter)
        
        # Apply date filters
        if date_from:
            loans = loans.filter(created_at__gte=date_from)
            applications = applications.filter(submitted_at__gte=date_from)
        
        if date_to:
            loans = loans.filter(created_at__lte=date_to)
            applications = applications.filter(submitted_at__lte=date_to)
        
        # Combine and order by creation date
        all_items = list(loans) + list(applications)
        all_items.sort(key=lambda x: x.created_at if hasattr(x, 'created_at') else x.submitted_at, reverse=True)
        
        # Render the table HTML
        from django.template.loader import render_to_string
        html = render_to_string('loans/loans_table.html', {
            'loans': all_items,
            'request': request
        }, request=request)
        
        return JsonResponse({
            'success': True,
            'html': html,
            'count': len(all_items)
        })
        
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        })


@login_required
def api_recent_activity(request):
    """API endpoint for recent activity"""
    # Get recent activity with naive datetime queries
    recent_activity = AuditLog.objects.select_related('user').order_by('-created_at')[:10]
    
    activities = []
    for activity in recent_activity:
        activity_type = activity.action
        icon = {
            'create': 'plus-circle',
            'update': 'edit',
            'delete': 'trash',
            'payment': 'money-bill-wave',
            'login': 'sign-in-alt',
            'logout': 'sign-out-alt'
        }.get(activity_type, 'info')
        
        activities.append({
            'type': activity_type,
            'user': activity.user.get_full_name() if activity.user else 'System',
            'action': activity.description,
            'timestamp': activity.created_at.isoformat(),
            'icon': icon
        })
    
    return JsonResponse({'activities': activities})
