"""
Simple test script for calculation service that can be run directly.
This bypasses Django's test framework to avoid migration issues.
"""

import os
import sys

# Add project root to path
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, project_root)

import django

# Setup Django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'branch_system.settings')
django.setup()

from decimal import Decimal
from django.utils import timezone
from datetime import timedelta
import uuid

from loans.models import Loan, LoanProduct, LoanApplication, Repayment, PenaltyCharge
from users.models import CustomUser
from reports.calculation_service import LoanCalculationService


def test_amount_paid_with_no_repayments():
    """Test that amount_paid is 0 when there are no repayments"""
    print("Testing amount_paid with no repayments...")
    
    # Create test user
    user = CustomUser.objects.create_user(
        username=f'test_user_{uuid.uuid4().hex[:8]}',
        email=f'test_{uuid.uuid4().hex[:8]}@example.com',
        phone_number=f'+2547{uuid.uuid4().hex[:8]}',
        first_name='Test',
        last_name='User'
    )
    
    # Create test product
    product = LoanProduct.objects.create(
        name=f'Test Product {uuid.uuid4().hex[:6]}',
        product_type='boost',
        description='Test product',
        min_amount=Decimal('1000'),
        max_amount=Decimal('50000'),
        interest_rate=Decimal('10.0'),
        processing_fee=Decimal('5.0'),
        min_duration=7,
        max_duration=90,
        available_repayment_methods=['monthly']
    )
    
    # Create loan application
    app = LoanApplication.objects.create(
        application_number=f'APP-{uuid.uuid4().hex[:6]}',
        borrower=user,
        loan_product=product,
        requested_amount=Decimal('10000'),
        requested_duration=30,
        purpose='Test',
        status='approved'
    )
    
    # Create loan
    loan = Loan.objects.create(
        loan_number=f'LOAN-{uuid.uuid4().hex[:6]}',
        application=app,
        borrower=user,
        principal_amount=Decimal('10000'),
        interest_amount=Decimal('1000'),
        processing_fee=Decimal('500'),
        total_amount=Decimal('11500'),
        disbursement_date=timezone.now(),
        due_date=timezone.now() + timedelta(days=30),
        duration_days=30,
        status='active'
    )
    
    # Calculate amount paid
    amount_paid = LoanCalculationService.calculate_amount_paid(loan)
    
    # Verify
    assert amount_paid == Decimal('0.00'), f"Expected 0.00, got {amount_paid}"
    print("[PASS] Amount paid is 0 when no repayments exist")
    
    # Cleanup (ignore errors due to database schema issues)
    try:
        loan.delete()
        app.delete()
        product.delete()
        user.delete()
    except Exception:
        pass  # Ignore cleanup errors


def test_amount_paid_with_repayments():
    """Test that amount_paid equals sum of repayments"""
    print("Testing amount_paid with repayments...")
    
    # Create test user
    user = CustomUser.objects.create_user(
        username=f'test_user_{uuid.uuid4().hex[:8]}',
        email=f'test_{uuid.uuid4().hex[:8]}@example.com',
        phone_number=f'+2547{uuid.uuid4().hex[:8]}',
        first_name='Test',
        last_name='User'
    )
    
    # Create test product
    product = LoanProduct.objects.create(
        name=f'Test Product {uuid.uuid4().hex[:6]}',
        product_type='boost',
        description='Test product',
        min_amount=Decimal('1000'),
        max_amount=Decimal('50000'),
        interest_rate=Decimal('10.0'),
        processing_fee=Decimal('5.0'),
        min_duration=7,
        max_duration=90,
        available_repayment_methods=['monthly']
    )
    
    # Create loan application
    app = LoanApplication.objects.create(
        application_number=f'APP-{uuid.uuid4().hex[:6]}',
        borrower=user,
        loan_product=product,
        requested_amount=Decimal('10000'),
        requested_duration=30,
        purpose='Test',
        status='approved'
    )
    
    # Create loan
    loan = Loan.objects.create(
        loan_number=f'LOAN-{uuid.uuid4().hex[:6]}',
        application=app,
        borrower=user,
        principal_amount=Decimal('10000'),
        interest_amount=Decimal('1000'),
        processing_fee=Decimal('500'),
        total_amount=Decimal('11500'),
        disbursement_date=timezone.now(),
        due_date=timezone.now() + timedelta(days=30),
        duration_days=30,
        status='active'
    )
    
    # Create repayments
    repayment_amounts = [Decimal('1000'), Decimal('2000'), Decimal('1500')]
    expected_total = sum(repayment_amounts)
    
    for i, amount in enumerate(repayment_amounts):
        Repayment.objects.create(
            loan=loan,
            amount=amount,
            payment_method='mpesa',
            receipt_number=f'RCP-TEST-{uuid.uuid4().hex[:8]}',
            payment_date=timezone.now() - timedelta(days=i)
        )
    
    # Calculate amount paid
    amount_paid = LoanCalculationService.calculate_amount_paid(loan)
    
    # Verify
    assert amount_paid == expected_total, f"Expected {expected_total}, got {amount_paid}"
    print(f"[PASS] Amount paid {amount_paid} equals sum of repayments {expected_total}")
    
    # Cleanup (ignore errors due to database schema issues)
    try:
        loan.delete()
        app.delete()
        product.delete()
        user.delete()
    except Exception:
        pass  # Ignore cleanup errors


def test_outstanding_amount_calculation():
    """Test outstanding amount calculation"""
    print("Testing outstanding amount calculation...")
    
    # Create test user
    user = CustomUser.objects.create_user(
        username=f'test_user_{uuid.uuid4().hex[:8]}',
        email=f'test_{uuid.uuid4().hex[:8]}@example.com',
        phone_number=f'+2547{uuid.uuid4().hex[:8]}',
        first_name='Test',
        last_name='User'
    )
    
    # Create test product
    product = LoanProduct.objects.create(
        name=f'Test Product {uuid.uuid4().hex[:6]}',
        product_type='boost',
        description='Test product',
        min_amount=Decimal('1000'),
        max_amount=Decimal('50000'),
        interest_rate=Decimal('10.0'),
        processing_fee=Decimal('5.0'),
        min_duration=7,
        max_duration=90,
        available_repayment_methods=['monthly']
    )
    
    # Create loan application
    app = LoanApplication.objects.create(
        application_number=f'APP-{uuid.uuid4().hex[:6]}',
        borrower=user,
        loan_product=product,
        requested_amount=Decimal('10000'),
        requested_duration=30,
        purpose='Test',
        status='approved'
    )
    
    # Create loan
    total_amount = Decimal('11500')
    loan = Loan.objects.create(
        loan_number=f'LOAN-{uuid.uuid4().hex[:6]}',
        application=app,
        borrower=user,
        principal_amount=Decimal('10000'),
        interest_amount=Decimal('1000'),
        processing_fee=Decimal('500'),
        total_amount=total_amount,
        disbursement_date=timezone.now() - timedelta(days=35),
        due_date=timezone.now() - timedelta(days=5),
        duration_days=30,
        status='active'
    )
    
    # Create repayment
    repayment_amount = Decimal('2000')
    Repayment.objects.create(
        loan=loan,
        amount=repayment_amount,
        payment_method='mpesa',
        receipt_number=f'RCP-TEST-{uuid.uuid4().hex[:8]}',
        payment_date=timezone.now()
    )
    
    # Create penalty
    penalty_amount = Decimal('500')
    PenaltyCharge.objects.create(
        loan=loan,
        amount=penalty_amount,
        penalty_rate=Decimal('5.0'),
        days_overdue=5,
        outstanding_amount=total_amount - repayment_amount,
        applied_date=timezone.now()
    )
    
    # Calculate outstanding
    outstanding = LoanCalculationService.calculate_outstanding_amount(loan)
    
    # Expected: total + penalties - paid = 11500 + 500 - 2000 = 10000
    expected_outstanding = total_amount + penalty_amount - repayment_amount
    
    # Verify
    assert outstanding == expected_outstanding, f"Expected {expected_outstanding}, got {outstanding}"
    print(f"[PASS] Outstanding {outstanding} = total {total_amount} + penalties {penalty_amount} - paid {repayment_amount}")
    
    # Cleanup (ignore errors due to database schema issues)
    try:
        loan.delete()
        app.delete()
        product.delete()
        user.delete()
    except Exception:
        pass  # Ignore cleanup errors


def test_currency_formatting():
    """Test currency formatting"""
    print("Testing currency formatting...")
    
    test_cases = [
        (Decimal('1000'), "1000.00"),
        (Decimal('1000.5'), "1000.50"),
        (Decimal('1000.123'), "1000.12"),  # Should round
        (Decimal('0'), "0.00"),
        (Decimal('0.1'), "0.10"),
    ]
    
    for amount, expected in test_cases:
        formatted = LoanCalculationService.format_currency(amount)
        assert formatted == expected, f"Expected {expected}, got {formatted}"
        
        # Verify exactly 2 decimal places
        decimal_part = formatted.split('.')[1]
        assert len(decimal_part) == 2, f"Expected 2 decimal places, got {len(decimal_part)}"
    
    print("[PASS] All currency formatting tests passed")


def test_total_loan_amount_calculation():
    """Test total loan amount calculation"""
    print("Testing total loan amount calculation...")
    
    test_cases = [
        (Decimal('10000'), Decimal('1000'), Decimal('500'), Decimal('11500')),
        (Decimal('5000'), Decimal('0'), Decimal('0'), Decimal('5000')),
        (Decimal('20000'), Decimal('2400'), Decimal('1200'), Decimal('23600')),
    ]
    
    for principal, interest, fee, expected in test_cases:
        total = LoanCalculationService.calculate_total_loan_amount(principal, interest, fee)
        assert total == expected, f"Expected {expected}, got {total}"
    
    print("[PASS] All total loan amount calculations passed")


def run_all_tests():
    """Run all tests"""
    print("\n" + "="*60)
    print("Running Calculation Service Tests")
    print("="*60 + "\n")
    
    try:
        test_amount_paid_with_no_repayments()
        test_amount_paid_with_repayments()
        test_outstanding_amount_calculation()
        test_currency_formatting()
        test_total_loan_amount_calculation()
        
        print("\n" + "="*60)
        print("[SUCCESS] ALL TESTS PASSED")
        print("="*60 + "\n")
        return True
    except AssertionError as e:
        print(f"\n[FAIL] TEST FAILED: {e}\n")
        return False
    except Exception as e:
        print(f"\n[ERROR] ERROR: {e}\n")
        import traceback
        traceback.print_exc()
        return False


if __name__ == '__main__':
    success = run_all_tests()
    sys.exit(0 if success else 1)
