from django.contrib import admin
from django.utils.html import format_html
from django.utils import timezone
from django.urls import reverse
from utils.datetime_utils import get_current_datetime, make_datetime_compatible
from django import forms
from django.core.exceptions import ValidationError
from .models import (
    LoanProduct, LoanApplication, Loan, Repayment, 
    RolloverRequest, MpesaTransaction,
    BureauRecord, LoanDisbursement, LoanFee, LoanGuarantor, LoanStatus
)


class LoanProductAdminForm(forms.ModelForm):
    available_durations = forms.CharField(
        required=False,
        widget=forms.TextInput(attrs={'placeholder': '7,14,30,60,90'}),
        help_text="Enter duration options in days, separated by commas (e.g., 7,14,30,60,90). Leave empty to use min/max range."
    )
    
    class Meta:
        model = LoanProduct
        fields = '__all__'
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Convert list to comma-separated string for display
        if self.instance.pk and self.instance.available_durations:
            self.fields['available_durations'].initial = ','.join(map(str, self.instance.available_durations))
    
    def clean_available_durations(self):
        value = self.cleaned_data.get('available_durations', '')
        if not value.strip():
            return []
        
        try:
            # Parse comma-separated values
            durations = [int(x.strip()) for x in value.split(',') if x.strip()]
            
            # Validate each duration
            min_duration = self.cleaned_data.get('min_duration', 1)
            max_duration = self.cleaned_data.get('max_duration', 365)
            
            for duration in durations:
                if duration < 1:
                    raise ValidationError("Duration must be at least 1 day")
                if min_duration and duration < min_duration:
                    raise ValidationError(f"Duration {duration} is below minimum duration of {min_duration} days")
                if max_duration and duration > max_duration:
                    raise ValidationError(f"Duration {duration} exceeds maximum duration of {max_duration} days")
            
            return sorted(list(set(durations)))  # Remove duplicates and sort
            
        except ValueError:
            raise ValidationError("Please enter valid numbers separated by commas (e.g., 7,14,30)")


@admin.register(LoanProduct)
class LoanProductAdmin(admin.ModelAdmin):
    form = LoanProductAdminForm
    list_display = [
        'name', 'product_type', 'min_amount', 'max_amount', 
        'interest_rate', 'processing_fee', 'is_active'
    ]
    list_filter = ['product_type', 'is_active', 'requires_guarantor', 'requires_collateral']
    search_fields = ['name', 'description']
    ordering = ['name']
    
    fieldsets = (
        ('Basic Information', {
            'fields': ('name', 'product_type', 'description')
        }),
        ('Loan Amounts', {
            'fields': ('min_amount', 'max_amount')
        }),
        ('Interest & Fees', {
            'fields': ('interest_rate', 'processing_fee', 'late_payment_penalty')
        }),
        ('Terms', {
            'fields': ('min_duration', 'max_duration', 'available_durations')
        }),
        ('Requirements', {
            'fields': ('requires_guarantor', 'requires_collateral', 'minimum_income')
        }),
        ('Status', {
            'fields': ('is_active',)
        }),
    )


@admin.register(LoanApplication)
class LoanApplicationAdmin(admin.ModelAdmin):
    list_display = [
        'application_number', 'borrower', 'loan_product', 'requested_amount',
        'requested_duration', 'status', 'submitted_at', 'auto_approved', 'preview_link'
    ]
    list_filter = [
        'status', 'loan_product__product_type', 'auto_approved', 
        'submitted_at', 'reviewed_at'
    ]
    search_fields = [
        'application_number', 'borrower__username', 'borrower__first_name',
        'borrower__last_name', 'borrower__phone_number'
    ]
    ordering = ['-submitted_at']
    
    change_form_template = 'admin/loans/loanapplication/change_form.html'
    
    fieldsets = (
        ('Application Details', {
            'fields': ('application_number', 'borrower', 'loan_product')
        }),
        ('Loan Request', {
            'fields': ('requested_amount', 'requested_duration', 'repayment_method', 'purpose'),
            'description': (
                '<div style="background-color: #e3f2fd; padding: 12px; border-left: 4px solid #1976d2; margin-bottom: 10px;">'
                '<strong>ℹ Review and Edit:</strong> You can modify these fields before approving the loan. '
                'Changes will be reflected in the final loan amount calculations below.'
                '</div>'
            )
        }),
        ('Calculated Amounts - Editable Preview', {
            'fields': ('interest_amount', 'processing_fee_amount', 'total_amount'),
            'description': (
                '<div style="background-color: #fff3e0; padding: 12px; border-left: 4px solid #f57c00; margin-bottom: 10px;">'
                '<strong>⚠ Review These Amounts:</strong> These are automatically calculated based on the loan product settings. '
                'You can manually adjust these amounts if needed before approval. Changes here will be saved to the loan.'
                '</div>'
            )
        }),
        ('Status & Workflow', {
            'fields': ('status', 'submitted_at', 'reviewed_by', 'reviewed_at', 'approval_notes')
        }),
        ('Auto-Approval', {
            'fields': ('auto_approved', 'credit_score'),
            'classes': ('collapse',)
        }),
        ('Documents', {
            'fields': ('supporting_documents',)
        }),
    )
    
    readonly_fields = [
        'application_number', 'submitted_at'
    ]
    
    actions = ['approve_applications', 'reject_applications']
    
    def preview_link(self, obj):
        """Display link to preview loan details"""
        if obj.status == 'pending':
            return format_html(
                '<a href="{}" style="background-color: #1976d2; color: white; padding: 4px 12px; '
                'border-radius: 4px; text-decoration: none; font-size: 11px;">Review & Edit</a>',
                reverse('admin:loans_loanapplication_change', args=[obj.pk])
            )
        return '-'
    preview_link.short_description = 'Action'
    
    def approve_applications(self, request, queryset):
        approved_count = 0
        for application in queryset.filter(status='pending'):
            try:
                application.approve(request.user, "Bulk approved via admin")
                approved_count += 1
            except Exception as e:
                self.message_user(request, f"Failed to approve {application.application_number}: {str(e)}", level='ERROR')
        self.message_user(request, f"{approved_count} applications approved successfully.")
    approve_applications.short_description = "Approve selected applications"
    
    def reject_applications(self, request, queryset):
        rejected_count = 0
        for application in queryset.filter(status='pending'):
            application.reject(request.user, "Bulk rejected via admin")
            rejected_count += 1
        self.message_user(request, f"{rejected_count} applications rejected.")
    reject_applications.short_description = "Reject selected applications"
    
    def save_model(self, request, obj, form, change):
        """Override save to recalculate amounts if loan details change"""
        if change:
            # Recalculate if amounts were manually edited or if loan parameters changed
            if 'requested_amount' in form.changed_data or 'requested_duration' in form.changed_data:
                months = max(1, obj.requested_duration / 30)
                obj.interest_amount = obj.loan_product.calculate_interest(obj.requested_amount, months)
                obj.processing_fee_amount = obj.loan_product.calculate_processing_fee(obj.requested_amount, months)
                obj.total_amount = obj.requested_amount + obj.interest_amount + obj.processing_fee_amount
        
        super().save_model(request, obj, form, change)
        
        # Show summary of loan details after save
        if obj.status == 'pending':
            self.message_user(
                request,
                f"Loan application {obj.application_number}: Amount KES {obj.requested_amount:,.2f}, "
                f"Interest KES {obj.interest_amount:,.2f}, Processing Fee KES {obj.processing_fee_amount:,.2f}, "
                f"Total KES {obj.total_amount:,.2f}",
                level='INFO'
            )
    
    def change_view(self, request, object_id, form_url='', extra_context=None):
        """Override change_view to add loan history context"""
        extra_context = extra_context or {}
        
        try:
            from loans.models import Loan
            from decimal import Decimal
            
            application = self.get_object(request, object_id)
            if application and application.borrower:
                # Get all previous loans for this borrower (excluding current application if it's been converted to loan)
                previous_loans = Loan.objects.filter(
                    borrower=application.borrower
                ).select_related('borrower').order_by('-disbursement_date')
                
                # Calculate statistics and add repayment percentage to each loan
                loan_list = []
                total_borrowed = Decimal('0')
                total_repaid = Decimal('0')
                
                for loan in previous_loans[:10]:  # Show last 10 loans
                    # Calculate repayment percentage
                    if loan.total_amount and loan.total_amount > 0:
                        repayment_pct = (loan.amount_paid / loan.total_amount * 100)
                        loan.repayment_percentage = int(repayment_pct)
                    else:
                        loan.repayment_percentage = 0
                    
                    loan_list.append(loan)
                    total_borrowed += loan.principal_amount
                    total_repaid += loan.amount_paid
                
                active_loans_count = previous_loans.filter(status='active').count()
                completed_loans_count = previous_loans.filter(status='paid').count()
                
                # Add to context
                extra_context['previous_loans'] = loan_list
                extra_context['total_borrowed'] = total_borrowed
                extra_context['total_repaid'] = total_repaid
                extra_context['active_loans_count'] = active_loans_count
                extra_context['completed_loans_count'] = completed_loans_count
                
        except Exception as e:
            # If there's any error, just continue without the loan history
            pass
        
        return super().change_view(request, object_id, form_url, extra_context=extra_context)


class LoanAdminForm(forms.ModelForm):
    class Meta:
        model = Loan
        fields = '__all__'
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Get the current user from the request
        request = getattr(self, '_request', None)
        if request and hasattr(request, 'user'):
            user = request.user
            # If user is not admin, make disbursement_date readonly if it's in the past
            if not user.is_superuser and not getattr(user, 'is_admin', lambda: False)():
                if self.instance and self.instance.pk:
                    if self.instance.disbursement_date.date() < get_current_datetime().date():
                        self.fields['disbursement_date'].widget.attrs['readonly'] = True
                        self.fields['disbursement_date'].help_text = "Only administrators can modify past disbursement dates"


@admin.register(Loan)
class LoanAdmin(admin.ModelAdmin):
    form = LoanAdminForm
    list_display = [
        'loan_number', 'borrower', 'principal_amount', 'total_amount',
        'status', 'disbursement_date', 'due_date', 'is_overdue', 'outstanding_amount'
    ]
    list_filter = [
        'status', 'disbursement_date', 'due_date', 'is_rolled_over'
    ]
    search_fields = [
        'loan_number', 'borrower__username', 'borrower__first_name',
        'borrower__last_name', 'borrower__phone_number'
    ]
    ordering = ['-created_at']
    
    fieldsets = (
        ('Loan Details', {
            'fields': ('loan_number', 'application', 'borrower')
        }),
        ('Amounts', {
            'fields': ('principal_amount', 'interest_amount', 'processing_fee', 'total_amount')
        }),
        ('Terms', {
            'fields': ('disbursement_date', 'due_date', 'duration_days')
        }),
        ('Status', {
            'fields': ('status', 'is_rolled_over', 'original_loan')
        }),
        ('Repayment Tracking', {
            'fields': ('amount_paid', 'last_payment_date'),
            'classes': ('collapse',)
        }),
    )
    
    readonly_fields = [
        'loan_number', 'outstanding_amount', 'is_overdue', 'days_overdue'
    ]
    
    actions = ['delete_loans_with_repayments']
    
    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        # Pass the request to the form so it can access the user
        form._request = request
        return form
    
    def outstanding_amount(self, obj):
        return obj.outstanding_amount
    outstanding_amount.short_description = 'Outstanding Amount'
    
    def is_overdue(self, obj):
        return obj.is_overdue
    is_overdue.boolean = True
    is_overdue.short_description = 'Overdue'
    
    def delete_loans_with_repayments(self, request, queryset):
        """Custom delete action that shows repayment count"""
        total_repayments = 0
        total_receipts = 0
        
        for loan in queryset:
            total_repayments += loan.repayments.count()
            from utils.models import Receipt
            total_receipts += Receipt.objects.filter(loan=loan).count()
        
        count = queryset.count()
        queryset.delete()
        
        message = f"Deleted {count} loan(s)"
        if total_repayments > 0:
            message += f", {total_repayments} repayment(s)"
        if total_receipts > 0:
            message += f", and {total_receipts} receipt(s)"
        message += "."
        
        self.message_user(request, message)
    
    delete_loans_with_repayments.short_description = "Delete selected loans (including repayments)"


class RepaymentAdminForm(forms.ModelForm):
    payment_date = forms.DateTimeField(
        widget=forms.DateTimeInput(attrs={'type': 'datetime-local'}),
        help_text="Select the date and time when the payment was made"
    )
    
    class Meta:
        model = Repayment
        fields = '__all__'
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # If this is a new repayment, set default to current time
        if not self.instance.pk:
            self.fields['payment_date'].initial = get_current_datetime()


@admin.register(Repayment)
class RepaymentAdmin(admin.ModelAdmin):
    form = RepaymentAdminForm
    list_display = [
        'receipt_number', 'loan', 'get_borrower', 'amount', 'payment_method',
        'payment_source_display', 'payment_date', 'mpesa_transaction_id'
    ]
    list_filter = ['payment_method', 'payment_source', 'payment_date']
    search_fields = [
        'receipt_number', 'loan__loan_number', 'loan__borrower__username',
        'loan__borrower__first_name', 'loan__borrower__last_name', 'mpesa_transaction_id'
    ]
    ordering = ['-payment_date']
    
    fieldsets = (
        ('Payment Details', {
            'fields': ('receipt_number', 'loan', 'amount', 'payment_method', 'payment_source', 'payment_date')
        }),
        ('M-Pesa Details', {
            'fields': ('mpesa_transaction_id', 'mpesa_phone_number'),
            'classes': ('collapse',)
        }),
        ('Timestamps', {
            'fields': ('created_at',)
        }),
    )
    
    readonly_fields = ['receipt_number', 'created_at']
    
    actions = ['delete_selected_payments']
    
    def delete_selected_payments(self, request, queryset):
        """Custom delete action with loan amount recalculation"""
        count = queryset.count()
        loans_to_update = set()
        
        # Collect loans that will be affected
        for repayment in queryset:
            loans_to_update.add(repayment.loan)
        
        # Delete the repayments
        queryset.delete()
        
        # Recalculate loan amounts
        for loan in loans_to_update:
            loan.update_status_based_on_payments()
        
        self.message_user(request, f"{count} payment(s) deleted and loan amounts updated.")
    
    delete_selected_payments.short_description = "Delete selected payments and update loan amounts"
    
    def save_model(self, request, obj, form, change):
        """Override save to recalculate loan amounts when payment is modified"""
        old_loan = None
        if change and obj.pk:
            try:
                old_repayment = Repayment.objects.get(pk=obj.pk)
                old_loan = old_repayment.loan
            except Repayment.DoesNotExist:
                pass
        
        super().save_model(request, obj, form, change)
        
        # Update loan amounts for both old and new loans (in case loan was changed)
        if old_loan and old_loan != obj.loan:
            old_loan.update_status_based_on_payments()
        obj.loan.update_status_based_on_payments()
    
    def delete_model(self, request, obj):
        """Override delete to recalculate loan amounts when payment is deleted"""
        loan = obj.loan
        super().delete_model(request, obj)
        loan.update_status_based_on_payments()
    
    def get_borrower(self, obj):
        return obj.loan.borrower.get_full_name()
    get_borrower.short_description = 'Borrower'
    
    def payment_source_display(self, obj):
        """Display payment source with styling"""
        if obj.payment_source == 'automatic':
            return format_html(
                '<span style="background-color: #e8f5e8; color: #2e7d32; padding: 2px 8px; '
                'border-radius: 12px; font-size: 11px; font-weight: bold;">Automatic</span>'
            )
        else:
            return format_html(
                '<span style="background-color: #fff3e0; color: #f57c00; padding: 2px 8px; '
                'border-radius: 12px; font-size: 11px;">Manual</span>'
            )
    payment_source_display.short_description = 'Payment Source'


@admin.register(RolloverRequest)
class RolloverRequestAdmin(admin.ModelAdmin):
    list_display = [
        'loan', 'borrower', 'requested_duration', 'status', 
        'requested_at', 'reviewed_by'
    ]
    list_filter = ['status', 'requested_at', 'reviewed_at']
    search_fields = [
        'loan__loan_number', 'borrower__username', 'borrower__first_name',
        'borrower__last_name'
    ]
    ordering = ['-requested_at']
    
    fieldsets = (
        ('Request Details', {
            'fields': ('loan', 'borrower', 'requested_duration', 'reason', 'rollover_fee')
        }),
        ('Status', {
            'fields': ('status', 'reviewed_by', 'reviewed_at', 'review_notes')
        }),
        ('Timestamps', {
            'fields': ('requested_at',)
        }),
    )
    
    readonly_fields = ['requested_at']
    
    actions = ['approve_rollovers', 'reject_rollovers']
    
    def approve_rollovers(self, request, queryset):
        for rollover in queryset.filter(status='pending'):
            rollover.approve(request.user, "Bulk approved via admin")
        self.message_user(request, f"{queryset.count()} rollover requests approved.")
    approve_rollovers.short_description = "Approve selected rollover requests"
    
    def reject_rollovers(self, request, queryset):
        for rollover in queryset.filter(status='pending'):
            rollover.reject(request.user, "Bulk rejected via admin")
        self.message_user(request, f"{queryset.count()} rollover requests rejected.")
    reject_rollovers.short_description = "Reject selected rollover requests"


@admin.register(MpesaTransaction)
class MpesaTransactionAdmin(admin.ModelAdmin):
    list_display = [
        'transaction_type', 'amount', 'phone_number', 'status',
        'payment_source_display', 'borrower_link', 'mpesa_transaction_id', 'created_at'
    ]
    list_filter = ['transaction_type', 'status', 'payment_source', 'is_automatic', 'created_at']
    search_fields = [
        'phone_number', 'mpesa_transaction_id', 'merchant_request_id',
        'checkout_request_id', 'trans_id', 'borrower__first_name', 'borrower__last_name'
    ]
    ordering = ['-created_at']
    
    fieldsets = (
        ('Transaction Details', {
            'fields': ('transaction_type', 'amount', 'phone_number', 'payment_source', 'is_automatic')
        }),
        ('M-Pesa Response', {
            'fields': (
                'mpesa_transaction_id', 'merchant_request_id', 
                'checkout_request_id', 'trans_id'
            )
        }),
        ('Status', {
            'fields': ('status', 'result_code', 'result_description', 'processing_notes')
        }),
        ('Related Objects', {
            'fields': ('borrower', 'loan', 'repayment'),
            'classes': ('collapse',)
        }),
        ('Timestamps', {
            'fields': ('created_at', 'updated_at', 'processed_at')
        }),
    )
    
    readonly_fields = ['created_at', 'updated_at', 'processed_at']
    
    def payment_source_display(self, obj):
        """Display payment source with styling"""
        if obj.payment_source == 'automatic':
            return format_html(
                '<span style="background-color: #e8f5e8; color: #2e7d32; padding: 2px 8px; '
                'border-radius: 12px; font-size: 11px; font-weight: bold;">Automatic</span>'
            )
        else:
            return format_html(
                '<span style="background-color: #fff3e0; color: #f57c00; padding: 2px 8px; '
                'border-radius: 12px; font-size: 11px;">Manual</span>'
            )
    payment_source_display.short_description = 'Payment Source'
    
    def borrower_link(self, obj):
        """Display borrower with link"""
        if obj.borrower:
            url = reverse('admin:users_customuser_change', args=[obj.borrower.pk])
            return format_html(
                '<a href="{}">{}</a>',
                url,
                obj.borrower.get_full_name()
            )
        return 'No borrower'
    borrower_link.short_description = 'Borrower'



# ============================================================================
# Grazuri Schema Compatibility Model Admins
# ============================================================================

@admin.register(BureauRecord)
class BureauRecordAdmin(admin.ModelAdmin):
    list_display = ['id', 'borrower', 'baccount', 'bureau_name', 'credit_score', 'record_date', 'created_at']
    list_filter = ['bureau_name', 'record_date', 'created_at']
    search_fields = ['borrower__first_name', 'borrower__last_name', 'borrower__phone_number', 'baccount__loan_number']
    raw_id_fields = ['borrower', 'baccount']
    readonly_fields = ['created_at', 'updated_at']
    
    fieldsets = (
        ('Bureau Information', {
            'fields': ('borrower', 'baccount', 'bureau_name', 'credit_score')
        }),
        ('Record Details', {
            'fields': ('record_date', 'report_data')
        }),
        ('Timestamps', {
            'fields': ('created_at', 'updated_at'),
            'classes': ('collapse',)
        }),
    )


@admin.register(LoanDisbursement)
class LoanDisbursementAdmin(admin.ModelAdmin):
    list_display = ['id', 'loan', 'amount', 'disbursement_date', 'disbursement_method', 'reference_number', 'created_at']
    list_filter = ['disbursement_method', 'disbursement_date', 'created_at']
    search_fields = ['loan__loan_number', 'reference_number']
    raw_id_fields = ['loan']
    readonly_fields = ['created_at', 'updated_at']
    date_hierarchy = 'disbursement_date'
    
    fieldsets = (
        ('Loan Information', {
            'fields': ('loan',)
        }),
        ('Disbursement Details', {
            'fields': ('amount', 'disbursement_date', 'disbursement_method', 'reference_number')
        }),
        ('Additional Information', {
            'fields': ('notes',)
        }),
        ('Timestamps', {
            'fields': ('created_at', 'updated_at'),
            'classes': ('collapse',)
        }),
    )


@admin.register(LoanFee)
class LoanFeeAdmin(admin.ModelAdmin):
    list_display = ['id', 'loan', 'fee_name', 'fee_type', 'amount', 'is_paid', 'paid_date', 'created_at']
    list_filter = ['fee_type', 'is_paid', 'created_at', 'paid_date']
    search_fields = ['loan__loan_number', 'fee_name', 'fee_type']
    raw_id_fields = ['loan']
    readonly_fields = ['created_at', 'updated_at']
    
    fieldsets = (
        ('Loan Information', {
            'fields': ('loan',)
        }),
        ('Fee Details', {
            'fields': ('fee_type', 'fee_name', 'amount')
        }),
        ('Payment Status', {
            'fields': ('is_paid', 'paid_date')
        }),
        ('Timestamps', {
            'fields': ('created_at', 'updated_at'),
            'classes': ('collapse',)
        }),
    )


@admin.register(LoanGuarantor)
class LoanGuarantorAdmin(admin.ModelAdmin):
    list_display = ['id', 'borrower', 'guarantor_name', 'guarantor_phone', 'guarantor_email', 'relationship', 'is_active', 'created_at']
    list_filter = ['is_active', 'relationship', 'created_at']
    search_fields = ['borrower__first_name', 'borrower__last_name', 'guarantor_name', 'guarantor_phone', 'guarantor_email', 'guarantor_id_number']
    raw_id_fields = ['borrower']
    readonly_fields = ['created_at', 'updated_at']
    
    fieldsets = (
        ('Borrower Information', {
            'fields': ('borrower',)
        }),
        ('Guarantor Details', {
            'fields': ('guarantor_name', 'guarantor_phone', 'guarantor_email', 'guarantor_id_number', 'relationship')
        }),
        ('Status', {
            'fields': ('is_active',)
        }),
        ('Timestamps', {
            'fields': ('created_at', 'updated_at'),
            'classes': ('collapse',)
        }),
    )


@admin.register(LoanStatus)
class LoanStatusAdmin(admin.ModelAdmin):
    list_display = ['id', 'loan', 'status', 'status_date', 'changed_by', 'created_at']
    list_filter = ['status', 'status_date', 'created_at']
    search_fields = ['loan__loan_number', 'status', 'notes']
    raw_id_fields = ['loan', 'changed_by']
    readonly_fields = ['created_at']
    date_hierarchy = 'status_date'
    
    fieldsets = (
        ('Loan Information', {
            'fields': ('loan',)
        }),
        ('Status Details', {
            'fields': ('status', 'status_date', 'changed_by')
        }),
        ('Additional Information', {
            'fields': ('notes',)
        }),
        ('Timestamps', {
            'fields': ('created_at',),
            'classes': ('collapse',)
        }),
    )
