#!/usr/bin/env python
"""
Test Manual Data Entry - Ensure system works perfectly for admin data entry
Tests: Creating clients, loans, payments manually through the system
"""
import os
import django
import sys
from decimal import Decimal
from datetime import datetime, timedelta

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'branch_system.settings')
django.setup()

from users.models import CustomUser, Branch
from loans.models import LoanProduct, LoanApplication, Loan
from django.db import transaction

print("=" * 100)
print("MANUAL DATA ENTRY TEST")
print("Testing: Client creation, Loan application, Loan approval - All manual processes")
print("=" * 100)

try:
    # Get admin user and branch
    admin = CustomUser.objects.filter(role='admin').first()
    if not admin:
        print("❌ No admin user found. Creating one...")
        admin = CustomUser.objects.create_user(
            username='testadmin',
            email='testadmin@havengrazuri.co.ke',
            password='Admin@2025',
            first_name='Test',
            last_name='Admin',
            role='admin',
            is_staff=True,
            is_superuser=True,
            phone_number='+254700000000',
            id_number='00000000'
        )
        print(f"✓ Created admin user: {admin.username}")
    
    branch = Branch.objects.first()
    if not branch:
        print("❌ No branch found. Creating one...")
        branch = Branch.objects.create(
            name='Test Branch',
            code='TEST',
            location='Nairobi',
            phone_number='+254112941830',
            email='test@havengrazuri.co.ke',
            status='active'
        )
        print(f"✓ Created branch: {branch.name}")
    
    # Get or create loan product
    loan_product = LoanProduct.objects.filter(is_active=True).first()
    if not loan_product:
        print("❌ No loan product found. Creating one...")
        loan_product = LoanProduct.objects.create(
            name='Test Loan Product',
            product_type='biashara',
            description='Test loan product for manual entry',
            min_amount=Decimal('1000.00'),
            max_amount=Decimal('1000000.00'),
            interest_rate=Decimal('10.00'),
            processing_fee=Decimal('5.00'),
            late_payment_penalty=Decimal('5.00'),
            duration_months=12,
            min_duration=30,
            max_duration=365,
            available_repayment_methods=['monthly', 'weekly'],
            requires_guarantor=False,
            requires_collateral=False,
            is_active=True
        )
        print(f"✓ Created loan product: {loan_product.name}")
    
    print("\n" + "=" * 100)
    print("TEST 1: Creating a Client Manually")
    print("=" * 100)
    
    # Test 1: Create a client (borrower)
    test_client_username = f'testclient_{datetime.now().strftime("%Y%m%d%H%M%S")}'
    
    with transaction.atomic():
        client = CustomUser.objects.create_user(
            username=test_client_username,
            email=f'{test_client_username}@example.com',
            password='Client@2025',
            first_name='Test',
            last_name='Client',
            role='borrower',
            phone_number=f'+254{datetime.now().strftime("%H%M%S")}',
            id_number=f'TEST{datetime.now().strftime("%Y%m%d%H%M%S")}',
            date_of_birth=datetime.now().date() - timedelta(days=365*25),
            gender='M',
            branch=branch,
            status='active',
            is_active=True
        )
        
        print(f"✓ Created client: {client.get_full_name()} (@{client.username})")
        print(f"  Email: {client.email}")
        print(f"  Phone: {client.phone_number}")
        print(f"  ID Number: {client.id_number}")
        print(f"  Branch: {client.branch.name}")
        print(f"  Status: {client.status}")
    
    print("\n" + "=" * 100)
    print("TEST 2: Creating a Loan Application Manually")
    print("=" * 100)
    
    # Test 2: Create a loan application
    with transaction.atomic():
        application = LoanApplication.objects.create(
            borrower=client,
            loan_product=loan_product,
            requested_amount=Decimal('50000.00'),
            requested_duration=90,  # 90 days
            purpose='Business expansion',
            repayment_method='monthly',
            status='pending'
        )
        
        print(f"✓ Created loan application: {application.application_number}")
        print(f"  Borrower: {application.borrower.get_full_name()}")
        print(f"  Amount: KES {application.requested_amount:,.2f}")
        print(f"  Duration: {application.requested_duration} days")
        print(f"  Interest: KES {application.interest_amount:,.2f}")
        print(f"  Processing Fee: KES {application.processing_fee_amount:,.2f}")
        print(f"  Total: KES {application.total_amount:,.2f}")
        print(f"  Status: {application.status}")
    
    print("\n" + "=" * 100)
    print("TEST 3: Approving Loan Application Manually")
    print("=" * 100)
    
    # Test 3: Approve the loan
    with transaction.atomic():
        loan = application.approve(
            approved_by=admin,
            notes="Approved for testing manual data entry",
            disbursement_date=datetime.now()
        )
        
        print(f"✓ Loan approved and created: {loan.loan_number}")
        print(f"  Borrower: {loan.borrower.get_full_name()}")
        print(f"  Principal: KES {loan.principal_amount:,.2f}")
        print(f"  Interest: KES {loan.interest_amount:,.2f}")
        print(f"  Processing Fee: KES {loan.processing_fee:,.2f}")
        print(f"  Total Amount: KES {loan.total_amount:,.2f}")
        print(f"  Disbursement Date: {loan.disbursement_date}")
        print(f"  Due Date: {loan.due_date}")
        print(f"  Status: {loan.status}")
    
    print("\n" + "=" * 100)
    print("TEST 4: Verifying Data Integrity")
    print("=" * 100)
    
    # Test 4: Verify everything is correct
    errors = []
    
    # Check client exists
    if not CustomUser.objects.filter(username=test_client_username).exists():
        errors.append("Client not found in database")
    else:
        print("✓ Client exists in database")
    
    # Check application exists
    if not LoanApplication.objects.filter(application_number=application.application_number).exists():
        errors.append("Loan application not found in database")
    else:
        print("✓ Loan application exists in database")
    
    # Check loan exists
    if not Loan.objects.filter(loan_number=loan.loan_number).exists():
        errors.append("Loan not found in database")
    else:
        print("✓ Loan exists in database")
    
    # Check loan is linked to application
    if loan.application != application:
        errors.append("Loan not properly linked to application")
    else:
        print("✓ Loan properly linked to application")
    
    # Check loan is linked to borrower
    if loan.borrower != client:
        errors.append("Loan not properly linked to borrower")
    else:
        print("✓ Loan properly linked to borrower")
    
    # Check amounts are correct
    expected_interest = loan_product.calculate_interest_from_days(
        application.requested_amount,
        application.requested_duration
    )
    if abs(loan.interest_amount - expected_interest) > Decimal('0.01'):
        errors.append(f"Interest calculation incorrect: {loan.interest_amount} vs {expected_interest}")
    else:
        print("✓ Interest amount calculated correctly")
    
    # Check total amount
    expected_total = loan.principal_amount + loan.interest_amount + loan.processing_fee
    if abs(loan.total_amount - expected_total) > Decimal('0.01'):
        errors.append(f"Total amount incorrect: {loan.total_amount} vs {expected_total}")
    else:
        print("✓ Total amount calculated correctly")
    
    print("\n" + "=" * 100)
    print("TEST RESULTS")
    print("=" * 100)
    
    if errors:
        print("\n❌ TESTS FAILED!")
        print("\nErrors found:")
        for error in errors:
            print(f"  - {error}")
        sys.exit(1)
    else:
        print("\n✅ ALL TESTS PASSED!")
        print("\n📊 Summary:")
        print(f"  ✓ Client created successfully")
        print(f"  ✓ Loan application created successfully")
        print(f"  ✓ Loan approved and disbursed successfully")
        print(f"  ✓ All data integrity checks passed")
        print(f"  ✓ All calculations are correct")
        
        print("\n🎉 System is PERFECT for manual data entry!")
        print("\n📝 Admin can now:")
        print("  1. Create clients manually without errors")
        print("  2. Create loan applications manually")
        print("  3. Approve and disburse loans")
        print("  4. All data is properly linked and calculated")
        
        print("\n" + "=" * 100)
        print("CLEANUP")
        print("=" * 100)
        
        # Ask if user wants to keep test data
        print("\nTest data created:")
        print(f"  - Client: {client.username}")
        print(f"  - Application: {application.application_number}")
        print(f"  - Loan: {loan.loan_number}")
        print("\nThis test data will remain in the system for verification.")
        
except Exception as e:
    print(f"\n❌ ERROR: {str(e)}")
    import traceback
    traceback.print_exc()
    sys.exit(1)
