#!/usr/bin/env python
"""
Test script for the new repayment scheduling system

This script tests the repayment method-aware scheduling and arrears calculation
for all 4 loan products (Boost, Boost Plus, Mwamba, Imara) with different
repayment methods (daily, weekly, monthly).
"""

import os
import sys
import django
from datetime import datetime, timedelta, date
from decimal import Decimal

# Setup Django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'branch_system.settings')
django.setup()

from loans.models import Loan, LoanApplication, LoanProduct, Repayment
from loans.repayment_scheduler import RepaymentScheduler
from users.models import CustomUser


def create_test_loan_product(product_type, name, interest_rate, duration_months, min_amount, max_amount):
    """Create a test loan product"""
    product, created = LoanProduct.objects.get_or_create(
        product_type=product_type,
        defaults={
            'name': name,
            'description': f'Test {name} product',
            'interest_rate': interest_rate,
            'duration_months': duration_months,
            'min_amount': min_amount,
            'max_amount': max_amount,
            'min_duration': duration_months * 30,
            'max_duration': duration_months * 30,
            'available_repayment_methods': ['daily', 'weekly', 'monthly'],
            'is_active': True
        }
    )
    return product


def create_test_user():
    """Create a test user"""
    user, created = CustomUser.objects.get_or_create(
        email='test@example.com',
        defaults={
            'first_name': 'Test',
            'last_name': 'User',
            'phone_number': '254700000000',
            'is_active': True
        }
    )
    return user


def create_test_loan(product, borrower, amount, duration_days, repayment_method, disbursement_date=None):
    """Create a test loan"""
    if disbursement_date is None:
        disbursement_date = datetime.now() - timedelta(days=10)  # 10 days ago
    
    # Create application
    application = LoanApplication.objects.create(
        borrower=borrower,
        loan_product=product,
        requested_amount=amount,
        requested_duration=duration_days,
        repayment_method=repayment_method,
        purpose='Test loan',
        status='approved'
    )
    
    # Create loan
    loan = Loan.objects.create(
        application=application,
        borrower=borrower,
        principal_amount=amount,
        interest_amount=application.interest_amount,
        processing_fee=application.processing_fee_amount,
        total_amount=application.total_amount,
        disbursement_date=disbursement_date,
        due_date=disbursement_date + timedelta(days=duration_days),
        duration_days=duration_days,
        status='active'
    )
    
    return loan


def test_repayment_scheduling():
    """Test the repayment scheduling system"""
    print("=" * 80)
    print("TESTING REPAYMENT SCHEDULING SYSTEM")
    print("=" * 80)
    
    # Create test data
    user = create_test_user()
    
    # Get existing loan products or create them
    try:
        boost = LoanProduct.objects.filter(product_type='boost').first()
        if not boost:
            boost = create_test_loan_product('boost', 'Boost', 20.0, 1, 1000, 50000)
        
        boost_plus = LoanProduct.objects.filter(product_type='boost_plus').first()
        if not boost_plus:
            boost_plus = create_test_loan_product('boost_plus', 'Boost Plus', 20.0, 2, 1000, 50000)
        
        mwamba = LoanProduct.objects.filter(product_type='mwamba').first()
        if not mwamba:
            mwamba = create_test_loan_product('mwamba', 'Mwamba', 20.0, 3, 5000, 200000)
        
        imara = LoanProduct.objects.filter(product_type='imara').first()
        if not imara:
            imara = create_test_loan_product('imara', 'Imara', 10.0, 6, 10000, 500000)
    except Exception as e:
        print(f"Error getting loan products: {e}")
        # Use any available product as fallback
        products = LoanProduct.objects.all()[:4]
        if len(products) >= 4:
            boost, boost_plus, mwamba, imara = products[:4]
        else:
            print("Not enough loan products available for testing")
            return
    
    print(f"Created loan products:")
    print(f"- {boost.name}: {boost.interest_rate}% interest, {boost.duration_months} months")
    print(f"- {boost_plus.name}: {boost_plus.interest_rate}% interest, {boost_plus.duration_months} months")
    print(f"- {mwamba.name}: {mwamba.interest_rate}% interest, {mwamba.duration_months} months")
    print(f"- {imara.name}: {imara.interest_rate}% interest, {imara.duration_months} months")
    print()
    
    # Test cases
    test_cases = [
        {
            'name': 'Boost Daily Loan',
            'product': boost,
            'amount': 10000,
            'duration_days': 30,
            'repayment_method': 'daily',
            'disbursement_date': datetime.now() - timedelta(days=5)  # 5 days ago
        },
        {
            'name': 'Boost Plus Weekly Loan',
            'product': boost_plus,
            'amount': 20000,
            'duration_days': 60,
            'repayment_method': 'weekly',
            'disbursement_date': datetime.now() - timedelta(days=10)  # 10 days ago
        },
        {
            'name': 'Mwamba Monthly Loan',
            'product': mwamba,
            'amount': 50000,
            'duration_days': 90,
            'repayment_method': 'monthly',
            'disbursement_date': datetime.now() - timedelta(days=15)  # 15 days ago
        },
        {
            'name': 'Imara Monthly Loan',
            'product': imara,
            'amount': 100000,
            'duration_days': 180,
            'repayment_method': 'monthly',
            'disbursement_date': datetime.now() - timedelta(days=20)  # 20 days ago
        }
    ]
    
    loans = []
    
    # Create test loans
    for test_case in test_cases:
        loan = create_test_loan(
            test_case['product'],
            user,
            test_case['amount'],
            test_case['duration_days'],
            test_case['repayment_method'],
            test_case['disbursement_date']
        )
        loans.append((test_case['name'], loan))
        print(f"Created {test_case['name']}: {loan.loan_number}")
    
    print()
    print("=" * 80)
    print("TESTING REPAYMENT SCHEDULER")
    print("=" * 80)
    
    # Test each loan
    for name, loan in loans:
        print(f"\n{name} ({loan.loan_number})")
        print("-" * 50)
        
        # Test repayment method
        repayment_method = RepaymentScheduler.get_repayment_method(loan)
        print(f"Repayment Method: {repayment_method}")
        
        # Test expected payment amount
        expected_amount = RepaymentScheduler.calculate_expected_payment_amount(loan)
        print(f"Expected Payment Amount: KES {expected_amount:,.2f}")
        
        # Test payment frequency
        frequency_days = RepaymentScheduler.get_payment_period_days(repayment_method)
        print(f"Payment Frequency: Every {frequency_days} days")
        
        # Test next payment due date
        next_due_date = RepaymentScheduler.get_next_payment_due_date(loan)
        print(f"Next Payment Due: {next_due_date}")
        
        # Test arrears calculation
        arrears_amount = RepaymentScheduler.calculate_arrears_amount(loan)
        print(f"Arrears Amount: KES {arrears_amount:,.2f}")
        
        # Test if in arrears
        is_in_arrears = RepaymentScheduler.is_loan_in_arrears(loan)
        print(f"In Arrears: {is_in_arrears}")
        
        # Test arrears summary
        arrears_summary = RepaymentScheduler.get_arrears_summary(loan)
        print(f"Days Overdue: {arrears_summary['days_overdue']}")
        print(f"Missed Periods: {arrears_summary['missed_periods_count']}")
        print(f"Payment Status: {arrears_summary.get('payment_status', 'N/A')}")
        
        # Test payment schedule
        payment_schedule = RepaymentScheduler.generate_payment_schedule(loan)
        print(f"Payment Schedule: {len(payment_schedule)} periods")
        
        # Show first few periods
        for i, period in enumerate(payment_schedule[:3]):
            status = "PAID" if period['is_paid'] else "PENDING"
            overdue = " (OVERDUE)" if period['is_overdue'] else ""
            print(f"  Period {period['period']}: {period['due_date']} - KES {period['expected_amount']:,.2f} {status}{overdue}")
        
        if len(payment_schedule) > 3:
            print(f"  ... and {len(payment_schedule) - 3} more periods")
    
    print()
    print("=" * 80)
    print("TESTING ARREARS DETECTION")
    print("=" * 80)
    
    # Test loans in arrears
    loans_in_arrears = RepaymentScheduler.get_loans_in_arrears()
    print(f"Total loans in arrears: {len(loans_in_arrears)}")
    
    for loan_data in loans_in_arrears:
        loan = loan_data['loan']
        summary = loan_data['arrears_summary']
        print(f"- {loan.loan_number}: KES {summary['arrears_amount']:,.2f} overdue ({summary['days_overdue']} days)")
    
    print()
    print("=" * 80)
    print("TESTING LOAN MODEL PROPERTIES")
    print("=" * 80)
    
    # Test loan model properties
    for name, loan in loans:
        print(f"\n{name} ({loan.loan_number})")
        print("-" * 30)
        print(f"Repayment Method: {loan.repayment_method}")
        print(f"Expected Payment: KES {loan.expected_payment_amount:,.2f}")
        print(f"Payment Frequency: {loan.payment_frequency_days} days")
        print(f"Next Due Date: {loan.next_payment_due_date}")
        print(f"Payment Status: {loan.payment_status}")
        print(f"Is Overdue: {loan.is_overdue}")
        print(f"Days Overdue: {loan.days_overdue}")
    
    print()
    print("=" * 80)
    print("TESTING WITH SAMPLE PAYMENTS")
    print("=" * 80)
    
    # Add some sample payments to test the system
    for name, loan in loans:
        print(f"\nAdding sample payments to {name}...")
        
        # Add a partial payment for daily loan
        if loan.repayment_method == 'daily':
            partial_amount = loan.expected_payment_amount * Decimal('0.5')  # 50% of expected
            Repayment.objects.create(
                loan=loan,
                amount=partial_amount,
                payment_method='cash',
                payment_date=datetime.now() - timedelta(days=2)
            )
            print(f"  Added partial payment: KES {partial_amount:,.2f}")
        
        # Add full payment for weekly loan
        elif loan.repayment_method == 'weekly':
            Repayment.objects.create(
                loan=loan,
                amount=loan.expected_payment_amount,
                payment_method='mpesa',
                payment_date=datetime.now() - timedelta(days=5)
            )
            print(f"  Added full payment: KES {loan.expected_payment_amount:,.2f}")
    
    # Re-test arrears after payments
    print("\nRe-testing arrears after payments...")
    loans_in_arrears_after = RepaymentScheduler.get_loans_in_arrears()
    print(f"Total loans in arrears after payments: {len(loans_in_arrears_after)}")
    
    for loan_data in loans_in_arrears_after:
        loan = loan_data['loan']
        summary = loan_data['arrears_summary']
        print(f"- {loan.loan_number}: KES {summary['arrears_amount']:,.2f} overdue ({summary['days_overdue']} days)")
    
    print()
    print("=" * 80)
    print("TEST COMPLETED SUCCESSFULLY!")
    print("=" * 80)


if __name__ == '__main__':
    test_repayment_scheduling()
